diff --git a/docs/api/commands/prompt.mdx b/docs/api/commands/prompt.mdx index 34f0c45caf..a7cd464f83 100644 --- a/docs/api/commands/prompt.mdx +++ b/docs/api/commands/prompt.mdx @@ -11,7 +11,14 @@ sidebar_custom_props: { 'new_label': true } # prompt -`cy.prompt` is a Cypress command that uses AI to convert natural language test steps into executable Cypress tests. It's designed to be flexible - you can use it to quickly generate tests and commit them to source control, or keep it running continuously for self-healing tests that adapt to your app's changes. You can choose the workflow that fits your project's needs. +`cy.prompt` is a Cypress command that uses AI to convert natural language test steps into executable Cypress tests. You can view the generated Cypress code at any time using the **Code** button in the Command Log, giving you full visibility into what commands were created from your prompts. + +**`cy.prompt` supports two flexible workflows:** + +1. **Generate and export** - Use AI to quickly create tests, review the generated code, and save it to your test files for predictable, version-controlled tests +2. **Continuous self-healing** - Keep `cy.prompt` running in your tests to automatically adapt when your app changes + +You can choose the workflow that fits your project's needs. :::note @@ -21,6 +28,7 @@ sidebar_custom_props: { 'new_label': true } - [Choosing your workflow](#Choose-your-workflow) — decide between one-time generation or continuous self-healing - [How to write effective prompts](#How-to-write-effective-prompts) — craft clear, reliable natural language steps - [What you can do](#What-you-can-do) — explore supported actions and capabilities +- [Viewing and exporting generated code](#Viewing-and-exporting-generated-code) — see the Cypress code generated from your prompts and save it to your files - [Setup](#Setup) — enable the command and configure authentication ::: @@ -94,7 +102,7 @@ When you call `cy.prompt`, Cypress performs a multi-step process: 2. **Generate selectors:** Cypress evaluates your app's DOM and picks a selector based on priority rules (unique identifiers that are likely to be stable). -3. **Generate Cypress code:** Commands are generated and executed in sequence. The Command Log shows both your natural language step and the commands Cypress ran. +3. **Generate Cypress code:** Commands are generated and executed in sequence. The Command Log shows both your natural language step and the commands Cypress ran. You can view the complete generated code at any time using the **Code** button in the Command Log. 4. **Cache for speed:** Generated code is cached. Re-running the same test does not re-call the AI model unless the prompt or DOM changes in a way that invalidates the cached code. @@ -138,7 +146,13 @@ cy.prompt( ) ``` -Use the **Get code** button to view the generated Cypress code. This will display the generated code in a dialog where you can preview what Cypress generated from your prompt. You can save the code to your test file, commit it to your version control system, or copy it to your clipboard. +After the test runs, click the **Code** button in the Command Log to view the generated Cypress code. This opens a dialog showing the complete Cypress commands that were generated from your natural language steps. From there, you can: + +- **Save to file** - Replace your `cy.prompt` call with the generated code directly in your test file +- **Copy to clipboard** - Copy the code for use elsewhere +- **Review and modify** - Inspect the generated selectors and commands before committing + +This workflow lets you use AI to quickly generate test code, then commit the exact generated code to your repository for predictable, version-controlled tests. { }) ``` +## Viewing and exporting generated code + +At any time during or after a test run, you can view the exact Cypress code that `cy.prompt` generated from your natural language steps. This transparency is built into every `cy.prompt` execution. + +### How to view generated code + +- **Run your test** with `cy.prompt` in Cypress App +- **Click the "Code" button** - This button appears next to each `cy.prompt` command in the Command Log + + + +- **Review the generated code** - A dialog displays the complete Cypress code with all of the generated commands (e.g., `cy.get()`, `cy.click()`, `cy.type()`) and comments showing which prompt step generated each command. + + + +### What you can do with the generated code + +Once you have the generated code, you can: + +- **Save code to your test file** - Replace the `cy.prompt` call with the generated Cypress commands for predictable, version-controlled tests. +- **Copy code to your clipboard** - Use the code in other files or share it with your team. + +This helps you review and modify the generated code as needed or just use it as a reference to understand what `cy.prompt` is doing behind the scenes. + +### Customizing selectors in generated code + +You can customize which selectors `cy.prompt` uses when generating Cypress code by configuring the [ElementSelector API](/api/cypress-api/element-selector-api). This lets you control which attributes Cypress prioritizes (like `data-*`, `id`, `aria-label`, etc.) when creating selectors, ensuring the generated code matches your project's selector strategy. + +Configure the selector priority in your support file or test file: + +```javascript +// cypress/support/e2e.js or in your test file +Cypress.ElementSelector.defaults({ + selectorPriority: [ + 'data-cy', // Prefer data-cy attributes + 'attribute:role', // Then ARIA roles + 'attribute:aria-label', // Then ARIA labels + 'id', // Then IDs + 'class', // Finally classes + ], +}) +``` + +For more examples and details, see the [ElementSelector API documentation](/api/cypress-api/element-selector-api). + ## Setup ### Enable the command diff --git a/package-lock.json b/package-lock.json index c2b1cf732b..717fbc38ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -151,6 +151,7 @@ "version": "4.22.1", "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.22.1.tgz", "integrity": "sha512-yb05NA4tNaOgx3+rOxAmFztgMTtGBi97X7PC3jyNeGiwkAjOZc2QrdZBYyIdcDLoI09N0gjtpClcackoTN0gPA==", + "peer": true, "dependencies": { "@algolia/client-common": "4.22.1", "@algolia/requester-common": "4.22.1", @@ -317,6 +318,7 @@ "version": "7.23.7", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.23.5", @@ -2351,6 +2353,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.1.1.tgz", "integrity": "sha512-2nQfKFcf+MLEM7JXsXwQxPOmQAR6ytKMZVSx7tVi9HEm9WtfwBH1fp6bn8Gj4zLUhjWKCLoysQ9/Wm+EZCQ4yQ==", + "peer": true, "dependencies": { "@babel/core": "^7.23.3", "@babel/generator": "^7.23.3", @@ -2741,6 +2744,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.1.1.tgz", "integrity": "sha512-GiPE/jbWM8Qv1A14lk6s9fhc0LhPEQ00eIczRO4QL2nAQJZXkjPG6zaVx+1cZxPFWbAsqSjKe2lqkwF3fGkQ7Q==", + "peer": true, "dependencies": { "@docusaurus/core": "3.1.1", "@docusaurus/mdx-loader": "3.1.1", @@ -2956,6 +2960,7 @@ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz", "integrity": "sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==", "hasInstallScript": true, + "peer": true, "dependencies": { "@fortawesome/fontawesome-common-types": "6.5.1" }, @@ -3492,6 +3497,7 @@ "version": "6.5.1", "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.5.1.tgz", "integrity": "sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==", + "peer": true, "dependencies": { "@babel/core": "^7.19.6", "@svgr/babel-preset": "^6.5.1", @@ -3851,6 +3857,7 @@ "version": "18.2.48", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", + "peer": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -4181,6 +4188,7 @@ "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4236,6 +4244,7 @@ "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -4278,6 +4287,7 @@ "version": "4.22.1", "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.22.1.tgz", "integrity": "sha512-jwydKFQJKIx9kIZ8Jm44SdpigFwRGPESaxZBaHSV0XWN2yBJAOT4mT7ppvlrpA4UGzz92pqFnVKr/kaZXrcreg==", + "peer": true, "dependencies": { "@algolia/cache-browser-local-storage": "4.22.1", "@algolia/cache-common": "4.22.1", @@ -4845,6 +4855,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001565", "electron-to-chromium": "^1.4.601", @@ -6753,6 +6764,7 @@ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, + "peer": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -7400,6 +7412,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -7635,6 +7648,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -13244,6 +13258,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", @@ -13924,6 +13939,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -14204,6 +14220,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -14349,6 +14366,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -14404,6 +14422,7 @@ "version": "5.5.2", "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", + "peer": true, "dependencies": { "@types/react": "*", "prop-types": "^15.6.2" @@ -14431,6 +14450,7 @@ "version": "5.3.4", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -15097,6 +15117,7 @@ "version": "1.70.0", "resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz", "integrity": "sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==", + "peer": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -15149,6 +15170,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -16216,6 +16238,7 @@ "version": "3.4.14", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", + "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -16329,6 +16352,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -16649,6 +16673,7 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -16996,6 +17021,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -17238,6 +17264,7 @@ "version": "5.89.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -17482,6 +17509,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", diff --git a/static/img/api/prompt/cy-prompt-export-code.png b/static/img/api/prompt/cy-prompt-export-code.png new file mode 100644 index 0000000000..a91f985a67 Binary files /dev/null and b/static/img/api/prompt/cy-prompt-export-code.png differ diff --git a/static/img/api/prompt/cy-prompt-generated-test-code.png b/static/img/api/prompt/cy-prompt-generated-test-code.png new file mode 100644 index 0000000000..2a41298a8c Binary files /dev/null and b/static/img/api/prompt/cy-prompt-generated-test-code.png differ