Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(utils): [grid,select] add vitest for utils package #2813

Merged
merged 6 commits into from
Jan 16, 2025

Conversation

shenjunjian
Copy link
Collaborator

@shenjunjian shenjunjian commented Jan 16, 2025

PR

为@opentiny/utils增加vitest的测试用例
简化 log的实现
删除nanoid的代码
简化总的index的导出写法
添加grid的utils依赖

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Introduced a new logging utility for enhanced logging capabilities.
  • Bug Fixes

    • Streamlined logging mechanisms across multiple components.
    • Improved import and module management for utility functions.
  • Refactor

    • Consolidated utility imports and exports.
    • Simplified cryptographic and logging implementations.
    • Removed deprecated logging and nanoid modules.
  • Documentation

    • Updated README for utils package with installation instructions.
  • Tests

    • Added test cases for XSS utility functions.
    • Introduced Vitest testing framework.
  • Chores

    • Updated package configurations.
    • Cleaned up unused code and modules.

Copy link

coderabbitai bot commented Jan 16, 2025

Walkthrough

This pull request involves a comprehensive refactoring of the utility modules within the @opentiny/utils package. The changes primarily focus on streamlining import statements, removing deprecated logging mechanisms, simplifying cryptographic utilities, and updating module exports. The modifications affect multiple files across the utils package, including crypt, log, nanoid, and index modules, with the goal of consolidating and simplifying the utility functions.

Changes

File Change Summary
packages/mobile/components/file-upload/src/renderless/index.ts Updated import statements and simplified default parameter declarations for handleStart and abortDownload functions.
packages/renderless/src/common/index.ts Removed log function and its import statement.
packages/renderless/src/tree/index.ts Updated log import from local to package.
packages/utils/README.md Updated header and added installation instructions.
packages/utils/package.json Added "type": "module", new test script, and Vitest dependency.
packages/utils/src/crypt/* Significant refactoring of cryptographic utilities, including removal of core.ts and sha256.ts files.
packages/utils/src/index.ts Simplified module imports and exports, removing unnecessary type definitions.
packages/utils/src/log/index.ts Added new logging utility with a logger property.
packages/utils/src/logger/* Removed previous logging implementation.
packages/utils/src/nanoid/* Removed Nanoid-related files and functionality.
packages/vue/src/grid/package.json Added @opentiny/utils dependency.
packages/vue/src/grid/src/tools/logger.ts Updated logging import and method to access logger through log.logger.
packages/utils/src/xss/__test__/xss.test.ts Added new test cases for XSS utility functions using Vitest.
examples/sites/demos/pc/app/grid/editor/custom-edit.spec.js Modified test case for multi-line editing feature in grid editor application.

Suggested labels

enhancement

Suggested reviewers

  • zzcr

Poem

🐰 Hop, hop, utilities dance!
Imports streamlined with rabbit's glance
Logs trimmed, crypto refined
Code now sleek and redesigned
A utility ballet, oh so neat! 🎩✨

Possibly related PRs


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5528dec and ccdef55.

📒 Files selected for processing (1)
  • examples/sites/demos/pc/app/grid/editor/custom-edit.spec.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/sites/demos/pc/app/grid/editor/custom-edit.spec.js
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: PR Unit Test
  • GitHub Check: PR E2E Test (pnpm test:e2e3)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@shenjunjian shenjunjian added the enhancement New feature or request (功能增强) label Jan 16, 2025
@github-actions github-actions bot removed the enhancement New feature or request (功能增强) label Jan 16, 2025
Copy link

Walkthrough

此PR为@opentiny/utils包增加了vitest测试用例,简化了log的实现,删除了nanoid代码,简化了index的导出写法,并为grid添加了utils依赖。

Changes

文件 概要
packages/mobile/components/file-upload/src/renderless/index.ts 更新了log和xss的导入路径,移除了函数参数的默认值类型声明。
packages/renderless/src/common/index.ts 移除了log的导入和相关实现。
packages/renderless/src/tree/index.ts 更新了log的导入路径。
packages/utils/README.md 添加了安装说明。
packages/utils/package.json 更新了包信息。
packages/utils/src/crypt/test/snapshots/crypt.test.ts.snap 更新了快照测试。
packages/utils/src/crypt/test/crypt.test.ts 添加了sha256的测试用例。
packages/utils/src/crypt/core.ts 删除了整个文件,移除了不再使用的加密实现。
packages/utils/src/crypt/index.ts 重写了sha256函数,移除了对旧加密实现的依赖。
packages/utils/src/crypt/sha256.ts 删除了整个文件,移除了不再使用的SHA256实现。
packages/utils/src/index.ts 简化了模块导出,移除了nanoid和logger。
packages/utils/src/log/index.ts 添加了新的log实现。
packages/utils/src/logger/README.md 删除了logger的使用说明。
packages/utils/src/logger/index.ts 删除了整个文件,移除了不再使用的logger实现。
packages/utils/src/nanoid/README.md 删除了nanoid的使用说明。
packages/utils/src/nanoid/index.ts 删除了整个文件,移除了不再使用的nanoid实现。
packages/utils/src/nanoid/nanoid.ts 删除了整个文件,移除了不再使用的nanoid实现。
packages/utils/src/xss/test/xss.test.ts 添加了xss的测试用例。
packages/vue/src/grid/package.json 更新了包信息。
packages/vue/src/grid/src/tools/logger.ts 更新了log的导入路径和使用方式。

const msgUint8 = isArrayBuffer ? message : new TextEncoder().encode(message) // 编码为(utf-8)Uint8Array
const hashBuffer = await window.crypto.subtle.digest(algo, msgUint8) // 计算消息的哈希值
const msgUint8 = isArrayBuffer ? message : new TextEncoder().encode(message as string) // 编码为(utf-8)Uint8Array
const hashBuffer = await getWindow().crypto.subtle.digest('SHA-256', msgUint8) // 计算消息的哈希值

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getWindow().crypto.subtle.digest method is used here, which relies on the browser's Web Crypto API. Ensure that this method is supported in the environments where this code will run, as it may not be available in all JavaScript environments.

Copy link

[e2e-test-warn]
The component to be tested is missing.

The title of the Pull request should look like "fix(vue-renderless): [action-menu, alert] fix xxx bug".

Please make sure you've read our contributing guide

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


Walkthrough

This PR adds vitest test cases to the @opentiny/utils package, simplifies the implementation of log, deletes nanoid code, simplifies the way to export index, and adds utils dependency for grid.

Changes

Documentation Summary
packages/mobile/components/file-upload/src/renderless/index.ts Updated the import paths of log and xss, and removed the default value type declaration of function parameters.
packages/renderless/src/common/index.ts Removed log import and related implementation.
packages/renderless/src/tree/index.ts Updated the import path of log.
packages/utils/README.md Added installation instructions.
packages/utils/package.json Updated package information.
packages/utils/src/crypt/test/snapshots/crypt.test.ts.snap Updated snapshot tests.
packages/utils/src/crypt/test/crypt.test.ts Added test cases for sha256.
packages/utils/src/crypt/core.ts Deleted the entire file and removed the encryption implementation that is no longer used.
packages/utils/src/crypt/index.ts Rewritten the sha256 function to remove dependence on the old encryption implementation.
packages/utils/src/crypt/sha256.ts Deleted the entire file, removing the SHA256 implementation that is no longer used.
packages/utils/src/index.ts Simplified module export, removed nanoid and logger.
packages/utils/src/log/index.ts New log implementation added.
packages/utils/src/logger/README.md Removed the logger usage instructions.
packages/utils/src/logger/index.ts Deleted the entire file and removed the logger implementation that is no longer used.
packages/utils/src/nanoid/README.md Removed nanoid usage instructions.
packages/utils/src/nanoid/index.ts Deleted the entire file and removed the nanoid implementation that is no longer used.
packages/utils/src/nanoid/nanoid.ts Deleted the entire file and removed the nanoid implementation that is no longer used.
packages/utils/src/xss/test/xss.test.ts Added xss test cases.
packages/vue/src/grid/package.json Updated package information.
packages/vue/src/grid/src/tools/logger.ts Updated the import path and usage of log.

@zzcr zzcr changed the title test(utils): add vitest for utils package test(utils): [grid,select] add vitest for utils package Jan 16, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (8)
packages/utils/src/crypt/__test__/crypt.test.ts (1)

4-7: Add a test case for ArrayBuffer input

The current test covers the sha256 function with a string input. Since sha256 also accepts an ArrayBuffer, consider adding a test case to verify that it handles ArrayBuffer inputs correctly.

Apply this diff to add the test case:

test('测试sha256', async () => {
  // 简单记录加密的结果,测试用来保证sha256算法不变化
  expect(await sha256('hello world')).toMatchSnapshot()
+ const arrayBuffer = new TextEncoder().encode('hello world').buffer
+ expect(await sha256(arrayBuffer)).toMatchSnapshot()
})
packages/utils/src/log/index.ts (2)

3-3: Consider using a more specific type than any.

Using any type reduces type safety. Consider using a more specific type that includes the console property.

-const _win: any = getWindow()
+interface WindowWithConsole {
+  console: Console;
+}
+const _win = getWindow() as WindowWithConsole

4-5: Add JSDoc documentation for the exported log utility.

The exported log utility would benefit from comprehensive JSDoc documentation in English, including:

  • Purpose of the utility
  • Usage examples
  • Type information
+/**
+ * A wrapper around console to provide consistent logging across the application
+ * @example
+ * import { log } from '@opentiny/utils'
+ * log.logger.warn('Warning message')
+ */
 export const log = { logger: _win.console as Console }
packages/vue/src/grid/src/tools/logger.ts (1)

Line range hint 4-12: Add null check for i18n message.

The i18n message lookup could return undefined. Consider adding a fallback for undefined translations.

 const outLog = (type) => (message, detail) => {
-  let msg = `[tiny-grid] ${GlobalConfig.i18n(message) || message}`
+  const translatedMessage = GlobalConfig.i18n(message)
+  let msg = `[tiny-grid] ${translatedMessage !== undefined ? translatedMessage : message}`

   if (detail) {
     msg += `: ${detail}`
   }

   log.logger.log(msg, type)

   return msg
 }
packages/utils/src/xss/__test__/xss.test.ts (1)

4-17: Enhance test coverage with additional test cases.

While the current tests cover basic scenarios, consider adding:

  1. Edge cases (empty strings, null values)
  2. Complex HTML with nested elements
  3. URLs with query parameters and fragments
  4. International characters in URLs

Example additional test cases:

// Edge cases
expect(filterHtml('')).toMatchInlineSnapshot(`""`)
expect(filterUrl('')).toMatchInlineSnapshot(`""`)

// Complex HTML
expect(filterHtml(`<div><script>alert('XSS')</script><p>Safe</p></div>`))
  .toMatchInlineSnapshot(`"<div><p>Safe</p></div>"`)

// URLs with query params
expect(filterUrl(`https://s.com/user?id=1&name=test#hash`))
  .toMatchInlineSnapshot(`"https://s.com/user?id=1&name=test#hash"`)

// International URLs
expect(filterUrl(`https://测试.com/path`))
  .toMatchInlineSnapshot(`"https://测试.com/path"`)
packages/renderless/src/common/index.ts (1)

13-13: Consider using TypeScript enums for constants.

The file contains several constant objects that could be converted to TypeScript enums for better type safety and IDE support.

Example transformation:

export enum Position {
  Left = 'left',
  Right = 'right',
  Top = 'top',
  Bottom = 'bottom'
}

export enum Sort {
  Asc = 'asc',
  Desc = 'desc'
}
packages/utils/README.md (1)

1-5: Enhance documentation with testing instructions.

Since this PR introduces Vitest testing capabilities, consider adding:

  • A section about running tests (npm test)
  • Examples of writing tests
  • Test coverage information

Also, consider maintaining consistency in language usage (Chinese vs English).

packages/utils/package.json (1)

20-20: Enhance test script configuration.

Consider adding more comprehensive test scripts:

-    "test": "vitest"
+    "test": "vitest",
+    "test:watch": "vitest watch",
+    "test:coverage": "vitest run --coverage",
+    "test:ui": "vitest --ui"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9ed39c7 and 2e6acdc.

⛔ Files ignored due to path filters (1)
  • packages/utils/src/crypt/__test__/__snapshots__/crypt.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (19)
  • packages/mobile/components/file-upload/src/renderless/index.ts (4 hunks)
  • packages/renderless/src/common/index.ts (1 hunks)
  • packages/renderless/src/tree/index.ts (1 hunks)
  • packages/utils/README.md (1 hunks)
  • packages/utils/package.json (2 hunks)
  • packages/utils/src/crypt/__test__/crypt.test.ts (1 hunks)
  • packages/utils/src/crypt/core.ts (0 hunks)
  • packages/utils/src/crypt/index.ts (1 hunks)
  • packages/utils/src/crypt/sha256.ts (0 hunks)
  • packages/utils/src/index.ts (1 hunks)
  • packages/utils/src/log/index.ts (1 hunks)
  • packages/utils/src/logger/README.md (0 hunks)
  • packages/utils/src/logger/index.ts (0 hunks)
  • packages/utils/src/nanoid/README.md (0 hunks)
  • packages/utils/src/nanoid/index.ts (0 hunks)
  • packages/utils/src/nanoid/nanoid.ts (0 hunks)
  • packages/utils/src/xss/__test__/xss.test.ts (1 hunks)
  • packages/vue/src/grid/package.json (1 hunks)
  • packages/vue/src/grid/src/tools/logger.ts (2 hunks)
💤 Files with no reviewable changes (7)
  • packages/utils/src/logger/README.md
  • packages/utils/src/crypt/sha256.ts
  • packages/utils/src/nanoid/README.md
  • packages/utils/src/logger/index.ts
  • packages/utils/src/crypt/core.ts
  • packages/utils/src/nanoid/index.ts
  • packages/utils/src/nanoid/nanoid.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/renderless/src/tree/index.ts
  • packages/mobile/components/file-upload/src/renderless/index.ts
🔇 Additional comments (4)
packages/utils/src/index.ts (1)

1-10: Simplification of imports and exports looks good

The refactoring of module imports and exports enhances code readability and removes unnecessary dependencies. The removal of nanoid appears to be intentional and aligns with the PR objectives.

packages/utils/package.json (2)

3-3: LGTM! ESM configuration added.

The addition of "type": "module" aligns with modern JavaScript practices.


4-6: Update package description.

The description still mentions "nanoid" which has been removed according to the PR objectives. Consider updating it to better reflect the current package contents.

Let's verify if nanoid is actually removed:

✅ Verification successful

The package description is indeed outdated and should be updated

The verification confirms that nanoid has been removed from the codebase (as evidenced by the changelog) with no remaining dependencies or imports. The only remaining reference is in the package description itself, which should be updated to accurately reflect the current package contents.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if nanoid still exists in the codebase
rg -g '!package*.json' 'nanoid' packages/utils/

Length of output: 47


Script:

#!/bin/bash
# Check package.json for nanoid dependency
echo "=== Checking package.json for nanoid ==="
cat packages/utils/package.json | grep -i nanoid

# Search for import statements with nanoid
echo -e "\n=== Checking for nanoid imports ==="
rg "import.*nanoid|require.*nanoid" packages/utils/

# Search entire repo for nanoid references
echo -e "\n=== Checking entire repo for nanoid ==="
rg -g '!package-lock.json' -g '!yarn.lock' "nanoid"

Length of output: 703

packages/vue/src/grid/package.json (1)

29-30: LGTM! Dependency addition looks good.

The addition of @opentiny/utils as a workspace dependency is correctly configured.

Comment on lines +4 to 13
export async function sha256(message: ArrayBuffer | string) {
const isArrayBuffer = Object.prototype.toString.call(message) === '[object ArrayBuffer]'
const msgUint8 = isArrayBuffer ? message : new TextEncoder().encode(message) // 编码为(utf-8)Uint8Array
const hashBuffer = await window.crypto.subtle.digest(algo, msgUint8) // 计算消息的哈希值
const msgUint8 = isArrayBuffer ? message : new TextEncoder().encode(message as string) // 编码为(utf-8)Uint8Array
const hashBuffer = await getWindow().crypto.subtle.digest('SHA-256', msgUint8) // 计算消息的哈希值
const hashArray = Array.from(new Uint8Array(hashBuffer)) // 将缓冲区转换为字节数组
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('') // 将字节数组转换为十六进制字符串

return hashHex
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Consider adding error handling for unsupported environments

The sha256 function assumes that getWindow().crypto.subtle.digest is always available. In environments where the Web Crypto API is not supported, this will lead to runtime errors. To ensure broader compatibility, consider adding error handling or a fallback implementation.

Apply this diff to add error handling:

export async function sha256(message: ArrayBuffer | string) {
  const isArrayBuffer = Object.prototype.toString.call(message) === '[object ArrayBuffer]'
  const msgUint8 = isArrayBuffer ? message : new TextEncoder().encode(message as string) // 编码为(utf-8)Uint8Array
+ const crypto = getWindow().crypto
+ if (!crypto || !crypto.subtle || typeof crypto.subtle.digest !== 'function') {
+   throw new Error('Web Crypto API is not supported in this environment.')
+ }
  const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8) // 计算消息的哈希值
  const hashArray = Array.from(new Uint8Array(hashBuffer)) // 将缓冲区转换为字节数组
  const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('') // 将字节数组转换为十六进制字符串
  return hashHex
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function sha256(message: ArrayBuffer | string) {
const isArrayBuffer = Object.prototype.toString.call(message) === '[object ArrayBuffer]'
const msgUint8 = isArrayBuffer ? message : new TextEncoder().encode(message) // 编码为(utf-8)Uint8Array
const hashBuffer = await window.crypto.subtle.digest(algo, msgUint8) // 计算消息的哈希值
const msgUint8 = isArrayBuffer ? message : new TextEncoder().encode(message as string) // 编码为(utf-8)Uint8Array
const hashBuffer = await getWindow().crypto.subtle.digest('SHA-256', msgUint8) // 计算消息的哈希值
const hashArray = Array.from(new Uint8Array(hashBuffer)) // 将缓冲区转换为字节数组
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('') // 将字节数组转换为十六进制字符串
return hashHex
}
export async function sha256(message: ArrayBuffer | string) {
const isArrayBuffer = Object.prototype.toString.call(message) === '[object ArrayBuffer]'
const msgUint8 = isArrayBuffer ? message : new TextEncoder().encode(message as string) // 编码为(utf-8)Uint8Array
const crypto = getWindow().crypto
if (!crypto || !crypto.subtle || typeof crypto.subtle.digest !== 'function') {
throw new Error('Web Crypto API is not supported in this environment.')
}
const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8) // 计算消息的哈希值
const hashArray = Array.from(new Uint8Array(hashBuffer)) // 将缓冲区转换为字节数组
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('') // 将字节数组转换为十六进制字符串
return hashHex
}

@zzcr zzcr merged commit 312dbcf into opentiny:dev Jan 16, 2025
6 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants