{"id":21045465,"url":"https://github.com/ymzuiku/testing-candy","last_synced_at":"2026-04-28T10:32:48.471Z","repository":{"id":153973124,"uuid":"631305357","full_name":"ymzuiku/testing-candy","owner":"ymzuiku","description":"Easy use testing in your browser","archived":false,"fork":false,"pushed_at":"2023-04-26T21:22:22.000Z","size":3546,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-29T20:21:10.981Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ymzuiku.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-22T15:45:42.000Z","updated_at":"2023-04-22T20:07:37.000Z","dependencies_parsed_at":"2023-07-06T20:46:31.414Z","dependency_job_id":null,"html_url":"https://github.com/ymzuiku/testing-candy","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ymzuiku%2Ftesting-candy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ymzuiku%2Ftesting-candy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ymzuiku%2Ftesting-candy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ymzuiku%2Ftesting-candy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ymzuiku","download_url":"https://codeload.github.com/ymzuiku/testing-candy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243489829,"owners_count":20299001,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-19T14:22:36.734Z","updated_at":"2025-12-29T11:15:38.737Z","avatar_url":"https://github.com/ymzuiku.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# testing-candy\n\nIn your Browser run e2e testing\n\n![](/candy.gif)\n\n### 1. Install\n\n```sh\nnpm/pnpm/yarn install @amarkdown/testing-candy\n```\n\n### 2. Use import(\"@amarkdown/testing-candy\") in your project\n\nonly import library in dev host:\n\n```ts\nimport { router } from \"router\";\nimport { registerE2e, roleE2e, memberE2e, databaseE2e } from \"./e2e\";\n\nconst isWebDev =\n  process.env.NODE_ENV === \"development\" ||\n  location.host === \"your-dev-host.com\";\n\nif (isWebDev) {\n  import(\"@amarkdown/testing-candy\").then(\n    ({ testingOptions, createTesting }) =\u003e {\n      // option, default: testingOptions.push = ()=\u003e location.href = url;\n      testingOptions.push = router.push;\n\n      createTesting({\n        onError: (err: Error, key: string) =\u003e {\n          alert(err);\n        },\n        onSuccess: (key) =\u003e {\n          alert(key);\n        },\n        tests: {\n          role: [\n            { name: \"login\", test: registerE2e },\n            { name: \"role\", test: roleE2e },\n          ],\n          member: [\n            { name: \"register\", test: registerE2e },\n            { name: \"member\", test: memberE2e },\n          ],\n          databases: [\n            { name: \"register\", test: registerE2e },\n            { name: \"role\", test: roleE2e },\n            { name: \"member\", test: memberE2e },\n            { name: \"database\", test: databaseE2e },\n          ],\n        },\n      });\n    }\n  );\n}\n```\n\n### 3. Write your e2e functions:\n\n- testingLibrary is `@testing-library/dom`\n- userEvent is `@testing-library/user-event`\n- faker is `@faker-js/faker`\n- candy is base the `testingLibrary`, add auto wait for network \\ log \\ waiting feature\n\n```ts\nimport type { Testing } from \"@amarkdown/testing-candy\";\n\nexport async function registerE2e({ candy, faker, testingLibrary }: Testing) {\n  await candy.push(\"/\", { beforeWait: 1000 });\n  const email = faker.internet.email();\n  const pwd = faker.internet.password() + \"a1\";\n  console.log(\"test account:\", email, pwd);\n\n  // role, testId, text, labelText: https://testing-library.com/docs/queries/about\n  await candy.clickByRole(\"register\");\n  await candy.clickByRole(\"goto_register\");\n  await candy.changeByRole(\"register_email\", email);\n  await candy.changeByRole(\"register_password\", pwd);\n  await candy.changeByRole(\"register_password2\", pwd);\n  await candy.clickByRole(\"verification_button\");\n  await candy.changeByRole(\"register_username\", email.split(\"@\")[0]);\n  await candy.clickByTestId(\"successful_send_verification\");\n  await candy.changeByRole(\"register_code\", \"999999\");\n  await candy.clickByRole(\"submit\");\n}\n\nexport async function roleE2e() {\n  // ...\n}\nexport async function memberE2e() {\n  // ...\n}\nexport async function databaseE2e() {\n  // ...\n}\n```\n\n### Example\n\n- [example/src/main.tsx](https://github.com/ymzuiku/testing-candy/blob/main/example/src/main.tsx)\n- [example/src/click-e2e.ts](https://github.com/ymzuiku/testing-candy/blob/main/example/src/click-e2e.ts)\n\n### In NextJs or MutilPage project:\n\nAll test state save in memory, if use mutil-page or nextjs, We need save state in session, and ignore old task. Use `keepSameKey`, every candy.clickByRole can save a sessionStorage key, if the key runed, testing can ignore the task.\n\n1. open `keepSameKey`:\n\n```ts\n import(\"@amarkdown/testing-candy\").then(({ testingOptions, createTesting }) =\u003e {\n    testingOptings.keepSameKey = true;\n    // .... other codes\n )}\n```\n\n2. add candy every key:\n\n```ts\n// if keepSameKey = true:\n\nawait candy.clickByRole(\"button\");\nawait candy.clickByRole(\"button\"); // this task is ignore\n\nawait candy.clickByRole(\"count\", { key: \"some-key\" });\nawait candy.clickByRole(\"count\", { key: \"some-key\" }); // this task is ignore\nawait candy.clickByRole(\"count\", { key: \"some-key2\" }); // right, add unique key\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fymzuiku%2Ftesting-candy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fymzuiku%2Ftesting-candy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fymzuiku%2Ftesting-candy/lists"}