├── .gitignore ├── shots ├── cy-e2e-09.jpg ├── cy-e2e-10.jpg ├── cy-e2e-11.jpg ├── cy-e2e-15.jpg ├── cy-e2e-16.jpg ├── cy-e2e-17.png └── cye2e_banner.png ├── .npmignore ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── src ├── utils │ ├── ignore.js │ ├── pipeline.js │ ├── cypressSetup.js │ ├── npmDependencies.js │ └── config.js └── templates │ └── prompter.js ├── package.json ├── LICENSE ├── index.js ├── README.md ├── CONTRIBUTING.md └── CODE_OF_CONDUCT.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .vscode/ 3 | .idea/ 4 | .DS_Store 5 | dist/ 6 | -------------------------------------------------------------------------------- /shots/cy-e2e-09.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhadmus/cye2e/HEAD/shots/cy-e2e-09.jpg -------------------------------------------------------------------------------- /shots/cy-e2e-10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhadmus/cye2e/HEAD/shots/cy-e2e-10.jpg -------------------------------------------------------------------------------- /shots/cy-e2e-11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhadmus/cye2e/HEAD/shots/cy-e2e-11.jpg -------------------------------------------------------------------------------- /shots/cy-e2e-15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhadmus/cye2e/HEAD/shots/cy-e2e-15.jpg -------------------------------------------------------------------------------- /shots/cy-e2e-16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhadmus/cye2e/HEAD/shots/cy-e2e-16.jpg -------------------------------------------------------------------------------- /shots/cy-e2e-17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhadmus/cye2e/HEAD/shots/cy-e2e-17.png -------------------------------------------------------------------------------- /shots/cye2e_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhadmus/cye2e/HEAD/shots/cye2e_banner.png -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | test/ 3 | shots/ 4 | package-lock.json 5 | .vscode/ 6 | .DS_Store 7 | .idea/ -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /src/utils/ignore.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import fs from "fs-extra"; 4 | import path from "path"; 5 | 6 | export async function createGitIgnoreFile(answers) { 7 | 8 | // Define the content with no leading whitespace 9 | const ignoreContent = ` 10 | # node_modules 11 | node_modules/ 12 | # MacOS file 13 | .DS_Store 14 | # Jetbrains generated file 15 | .idea/ 16 | # VsCode generated file 17 | .vscode/ 18 | # Cypress reports 19 | cypress/videos/ 20 | cypress/screenshots/`.trim(); 21 | 22 | if (answers.ignoreFile) { 23 | const ignorePath = path.join(process.cwd(), ".gitignore"); 24 | 25 | // Write .gitignore file as plain text 26 | await fs.writeFile(ignorePath, ignoreContent, "utf8"); 27 | 28 | console.log("Created .gitignore"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cye2e", 3 | "version": "2.1.2", 4 | "type": "module", 5 | "description": "", 6 | "main": "index.js", 7 | "scripts": { 8 | "start": "cye2e" 9 | }, 10 | "bin": { 11 | "cye2e": "./index.js" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/bhadmus/cye2e.git" 16 | }, 17 | "keywords": [ 18 | "cypress", 19 | "configuration", 20 | "cli" 21 | ], 22 | "author": "Ademola Bhadmus", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/bhadmus/cye2e/issues" 26 | }, 27 | "homepage": "https://github.com/bhadmus/cye2e#readme", 28 | "dependencies": { 29 | "inquirer": "^9.3.4", 30 | "fs-extra": "^10.0.0", 31 | "path": "^0.12.7", 32 | "child_process": "^1.0.2" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 sanguine 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { collectInfo } from "./src/templates/prompter.js"; 4 | import { createConfigFile } from "./src/utils/config.js"; 5 | import { createPackageJsonFile } from "./src/utils/npmDependencies.js"; 6 | import { createConfigurationFile } from "./src/utils/cypressSetup.js"; 7 | import { createGitIgnoreFile } from "./src/utils/ignore.js"; 8 | import { createPipelineFile } from "./src/utils/pipeline.js"; 9 | import { exec } from "child_process"; 10 | 11 | async function main() { 12 | const answers = await collectInfo(); 13 | await createConfigFile(answers); 14 | await createGitIgnoreFile(answers); 15 | await createPackageJsonFile(answers); 16 | await createConfigurationFile(answers); 17 | await createPipelineFile(answers); 18 | 19 | if (answers.installDependencies) { 20 | console.log("Running npm install..."); 21 | exec("npm install", (error, stdout, stderr) => { 22 | if (error) { 23 | console.error(`exec error: ${error}`); 24 | return; 25 | } 26 | console.log(`stdout: ${stdout}`); 27 | console.error(`stderr: ${stderr}`); 28 | }); 29 | } 30 | } 31 | 32 | main(); 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Image](shots/cye2e_banner.png) 2 | # cye2e 3 | 4 | Are you a newbie in QA Engineering? Are you trying to ease your way into Automation? Have you been learning Cypress? Would you like to be able to set up Cypress with a BDD framework and reporter without stress? 5 | 6 | If yes, this plugin is for you. Since I started training people in software automation, the majority of problems that I have had to help people resolve is usually around set up. Hence, the reason that I decided to create this plugin so that people can easily setup cypress. 7 | 8 | You can create a cypress Template project that you can easily edit to suit your purpose. 9 | 10 | ## Installation 11 | `npm install -g cye2e` 12 | 13 | ## Usage 14 | - After Installation, open the terminal in your desired directory and run `cye2e` 15 | 16 | ## Example 17 | 18 | Going through the questions looks like this 19 | 20 | 21 | | ![BDD](shots/cy-e2e-09.jpg) | 22 | |:--:| 23 | | *BDD Typsecript Config with reporter selected* | 24 | 25 | | ![TDD](shots/cy-e2e-10.jpg) | 26 | |:--:| 27 | | *Cypress Config with no BDD or reporter selected* | 28 | 29 | 30 | | ![TDD and Eslint](shots/cy-e2e-17.png) | 31 | |:--:| 32 | | *Cypress Config with no BDD or reporter selected but eslint selected* | 33 | 34 | | ![Project-Structure](shots/cy-e2e-11.jpg) | 35 | |:--:| 36 | | *Cypress Project Created* | 37 | 38 | | ![CI/CD-Structure](shots/cy-e2e-16.jpg) | 39 | |:--:| 40 | | *Cypress Config with BDD, Reporter, and GitHub Template* | 41 | 42 | | ![CI/CD-Structure](shots/cy-e2e-15.jpg) | 43 | |:--:| 44 | | *Cypress BDD Folder Structure with GitHub Template* | 45 | 46 | You can run the `npx cypress run` or `npx cypress open` command to see it execute. 47 | 48 | What's left is to continue to edit the template created to suit your needs 49 | 50 | 51 | ## Compatibility 52 | 53 | - It should be compatible with all versions of Cypress 54 | - Node version >= 18+ 55 | 56 | ## Support 57 | 58 | [Issues](https://github.com/bhadmus/cy-config/issues) 59 | 60 | 61 | 62 | > [!NOTE] 63 | > The [Browserify](https://github.com/badeball/cypress-cucumber-preprocessor/issues/1273) has an issue. 64 | > Until it is stable, it will be disabled, You can still use esbuild, or webpack. 65 | -------------------------------------------------------------------------------- /src/utils/pipeline.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import fs from "fs-extra"; 4 | import path from "path"; 5 | 6 | export async function createPipelineFile(answers) { 7 | const bitbucketFilePath = path.join(process.cwd(), "bitbucket-pipelines.yml"); 8 | const gitlabFilePath = path.join(process.cwd(), ".gitlab-ci.yml"); 9 | 10 | let pipelineConfigContent; 11 | 12 | if (answers.pipelineConfig) { 13 | switch (answers.versionControl) { 14 | case "gitlab": 15 | pipelineConfigContent = `stages: 16 | - test-build 17 | 18 | test: 19 | image: cypress/browsers:node-20.9.0-chrome-118.0.5993.88-1-ff-118.0.2-edge-118.0.2088.46-1 20 | stage: test-build 21 | script: 22 | # install dependencies 23 | - npm i 24 | - npx cypress run 25 | `; 26 | await fs.writeFile(gitlabFilePath, pipelineConfigContent); 27 | break; 28 | case "bitbucket": 29 | pipelineConfigContent = `image: cypress/browsers:node-20.9.0-chrome-118.0.5993.88-1-ff-118.0.2-edge-118.0.2088.46-1 30 | 31 | pipelines: 32 | default: 33 | - step: 34 | name: "Install and Run Test, Upload Result" 35 | script: 36 | # install dependencies 37 | - npm i 38 | # run cypress 39 | - npx cypress run 40 | `; 41 | await fs.writeFile(bitbucketFilePath, pipelineConfigContent); 42 | break; 43 | case "github": 44 | pipelineConfigContent = `name: Run Cypress Test 45 | 46 | on: [push] 47 | 48 | jobs: 49 | cypress-runner: 50 | runs-on: ubuntu-latest 51 | 52 | steps: 53 | - name: Intialize NPM 54 | uses: actions/checkout@v4 55 | 56 | - name: Run Cypress 57 | uses: cypress-io/github-action@v6 58 | 59 | `; 60 | const githubDir = path.join(process.cwd(), ".github", "workflows"); 61 | await fs.ensureDir(githubDir); 62 | const githubFilePath = path.join(githubDir, "runner.yml"); 63 | await fs.writeFile(githubFilePath, pipelineConfigContent); 64 | } 65 | } 66 | if (answers.versionControl === undefined){ 67 | console.log(` `); 68 | }else{ 69 | console.log(`Pipeline config for ${answers.versionControl} has been created successfully.`); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to cye2e 2 | 3 | Thank you for considering contributing to the **cye2e** project! This guide outlines how to get involved and contribute effectively. 4 | 5 | ## Table of Contents 6 | 7 | - [Code of Conduct](#code-of-conduct) 8 | - [How Can I Contribute?](#how-can-i-contribute) 9 | - [Reporting Issues](#reporting-issues) 10 | - [Suggesting Enhancements](#suggesting-enhancements) 11 | - [Submitting Code Changes](#submitting-code-changes) 12 | - [Setting up the Development Environment](#setting-up-the-development-environment) 13 | - [Pull Request Guidelines](#pull-request-guidelines) 14 | - [Style Guide](#style-guide) 15 | - [License](#license) 16 | 17 | ## Code of Conduct 18 | 19 | Please read our [Code of Conduct](./CODE_OF_CONDUCT.md) to understand how we expect contributors to conduct themselves while participating in this project. 20 | 21 | ## How Can I Contribute? 22 | 23 | ### Reporting Issues 24 | 25 | If you encounter a bug or have a question about the project, please: 26 | 27 | 1. **Search for existing issues** to ensure it's not a duplicate. 28 | 2. **Create a new issue** if one doesn't exist. Use a clear and descriptive title and provide as much information as possible, such as: 29 | - Steps to reproduce the issue 30 | - The expected result 31 | - The actual result 32 | - Version of `cye2e` being used 33 | - Any other relevant information, such as system configurations 34 | 35 | ### Suggesting Enhancements 36 | 37 | We welcome ideas to improve the package! When suggesting an enhancement: 38 | 39 | - **Explain the current state of the problem** and why your enhancement would help. 40 | - Provide details about how the enhancement would work. 41 | - Add potential use cases and examples, if possible. 42 | 43 | ### Submitting Code Changes 44 | 45 | 1. Fork the repository. 46 | 2. Create a new branch (from `main` or `develop`) for your changes: 47 | ``` 48 | git checkout -b feature/my-feature 49 | ``` 50 | 3. Make your changes, following the [Style Guide](#style-guide). 51 | 4. Commit your changes: 52 | ``` 53 | git commit -m "Add a concise description of the changes" 54 | ``` 55 | 5. Push to your fork: 56 | ``` 57 | git push origin feature/my-feature 58 | ``` 59 | 6. Submit a pull request (PR) to the main repository and describe your changes in detail. 60 | 61 | Please keep the scope of each PR focused and atomic. If you plan on making significant changes, it's best to open an issue or start a discussion first. 62 | 63 | ## Setting up the Development Environment 64 | 65 | To contribute to `cye2e`, follow these steps to set up your local environment: 66 | 67 | 1. Clone the repository: 68 | ``` 69 | git clone https://github.com/your-username/cye2e.git 70 | ``` 71 | 2. Navigate to the project directory: 72 | ``` 73 | cd cye2e 74 | ``` 75 | 3. Install dependencies: 76 | ``` 77 | npm install 78 | ``` 79 | 4. Run tests to ensure everything works as expected: 80 | ``` 81 | npm test 82 | ``` 83 | 84 | ## Pull Request Guidelines 85 | - Keep your PR focused; avoid including unrelated changes. 86 | - Provide a detailed description of the changes in your PR. 87 | - Update relevant documentation, if applicable. 88 | 89 | ## Style Guide 90 | 91 | Follow these guidelines to maintain code quality: 92 | 93 | - **Code Style**: Follow the coding style used in the project. Use a linter to maintain consistency (`npm run lint`). 94 | - **Commit Messages**: Use concise and clear commit messages, following [Conventional Commits](https://www.conventionalcommits.org/), e.g., `feat: add feature x`. 95 | - **Testing**: Ensure all features have corresponding tests and that all tests pass before submitting a PR. 96 | 97 | ## License 98 | 99 | By contributing, you agree that your contributions will be licensed under the [MIT License](./LICENSE). 100 | -------------------------------------------------------------------------------- /src/templates/prompter.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import inquirer from "inquirer"; 4 | 5 | export async function collectInfo() { 6 | 7 | const version = "2.1.2"; 8 | 9 | // Check command-line arguments for --version or --help 10 | const args = process.argv.slice(2); 11 | 12 | if (args.includes("--version") || args.includes("-V")) { 13 | console.log(version); 14 | process.exit(0); 15 | } 16 | 17 | if (args.includes("--help") || args.includes("-h")) { 18 | console.log(` 19 | Usage: cye2e 20 | 21 | Options: 22 | -V, --version output the current version 23 | -h, --help display help for command 24 | `); 25 | process.exit(0); 26 | } 27 | 28 | // console.log( 29 | // "\u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F}" 30 | // ); 31 | // console.log("\n"); 32 | // console.log("\u{1F31F} Cypress E2E Helper Bot \u{1F31F}"); 33 | // console.log("\n"); 34 | // console.log( 35 | // "\u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F} \u{1F31F}" 36 | // ); 37 | 38 | console.log('\n') 39 | console.log('\n') 40 | console.log(' ██████╗██╗ ██╗███████╗██████╗ ███████╗') 41 | console.log('██╔════╝╚██╗ ██╔╝██╔════╝╚════██╗██╔════╝') 42 | console.log('██║ ╚████╔╝ █████╗ █████╔╝█████╗ ') 43 | console.log('██║ ╚██╔╝ ██╔══╝ ██╔═══╝ ██╔══╝ ') 44 | console.log('╚██████╗ ██║ ███████╗███████╗███████╗') 45 | console.log(' ╚═════╝ ╚═╝ ╚══════╝╚══════╝╚══════╝') 46 | console.log('\n') 47 | console.log('\n') 48 | 49 | const answers = await inquirer.prompt([ 50 | { 51 | type: "list", 52 | name: "configLanguage", 53 | message: "Which configuration language do you want to use?", 54 | choices: ["JavaScript", "TypeScript"], 55 | default: "JavaScript", 56 | }, 57 | { 58 | type: "confirm", 59 | name: "lintSetup", 60 | message: "Do you want to setup Eslint?", 61 | default: false, 62 | }, 63 | { 64 | type: "input", 65 | name: "baseUrl", 66 | message: "What is the base URL for your tests?", 67 | default: "https://example.cypress.io", 68 | }, 69 | { 70 | type: "confirm", 71 | name: "testDesign", 72 | message: "Do you want to setup BDD?", 73 | default: false, 74 | }, 75 | { 76 | type: "confirm", 77 | name: "reportChoice", 78 | message: "Do you want to setup a reporter?", 79 | default: false, 80 | }, 81 | { 82 | type: "confirm", 83 | name: "pipelineConfig", 84 | message: "Do you want to setup a pipeline?", 85 | default: false, 86 | }, 87 | { 88 | type: "confirm", 89 | name: "safariSupport", 90 | message: "Do you want to setup Safari support?", 91 | default: false, 92 | }, 93 | { 94 | type: "confirm", 95 | name: "ignoreFile", 96 | message: "Do you want to a .gitignore file?", 97 | default: false, 98 | }, 99 | { 100 | type: "confirm", 101 | name: "installDependencies", 102 | message: "Do you want to run npm install after creating the files?", 103 | default: false, 104 | }, 105 | ]); 106 | 107 | if (answers.testDesign) { 108 | const bundlerAnswer = await inquirer.prompt([ 109 | { 110 | type: "list", 111 | name: "bundler", 112 | message: "Which bundler do you prefer?", 113 | choices: ["esbuild", "webpack"], 114 | default: "esbuild", 115 | }, 116 | ]); 117 | answers.bundler = bundlerAnswer.bundler; 118 | } 119 | 120 | if (answers.reportChoice) { 121 | const reporterAnswer = await inquirer.prompt([ 122 | { 123 | type: "list", 124 | name: "reporter", 125 | message: "Which reporter do you prefer?", 126 | choices: answers.testDesign 127 | ? ["badeball", "multipleCucumber"] 128 | : ["mochawesome", "allure"], 129 | default: answers.testDesign ? "badeball" : "mochawesome", 130 | }, 131 | ]); 132 | answers.reporter = reporterAnswer.reporter; 133 | } 134 | 135 | if (answers.pipelineConfig) { 136 | const pipelineAnswer = await inquirer.prompt([ 137 | { 138 | type: "list", 139 | name: "versionControl", 140 | message: "Which version control tool do you prefer?", 141 | choices: ["gitlab", "github", "bitbucket"], 142 | default: "gitlab", 143 | }, 144 | ]); 145 | answers.versionControl = pipelineAnswer.versionControl; 146 | } 147 | return answers; 148 | } 149 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | . 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /src/utils/cypressSetup.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import fs from 'fs-extra'; 4 | import path from 'path'; 5 | 6 | export async function createConfigurationFile(answers, configFilePath) { 7 | const cypressDirs = [ 8 | path.join(process.cwd(), 'cypress', 'e2e'), 9 | path.join(process.cwd(), 'cypress', 'fixtures'), 10 | path.join(process.cwd(), 'cypress', 'support') 11 | ]; 12 | 13 | for (const dir of cypressDirs) { 14 | await fs.ensureDir(dir); 15 | } 16 | 17 | // Create example spec file based on BDD selection 18 | if (!answers.testDesign) { 19 | const exampleSpecPath = path.join(process.cwd(), 'cypress', 'e2e', 'example.cy.' + (answers.configLanguage === 'JavaScript' ? 'js' : 'ts')); 20 | const exampleSpecContent = ` 21 | describe('Example Test', () => { 22 | it('visits the base URL', () => { 23 | cy.visit('/'); 24 | }); 25 | }); 26 | `; 27 | await fs.writeFile(exampleSpecPath, exampleSpecContent); 28 | } 29 | 30 | // Create example fixture file 31 | const exampleFixturePath = path.join(process.cwd(), 'cypress', 'fixtures', 'example.json'); 32 | const exampleFixtureContent = { 33 | "exampleKey": "exampleValue" 34 | }; 35 | await fs.writeJson(exampleFixturePath, exampleFixtureContent, { spaces: 2 }); 36 | 37 | // Create support files based on BDD selection 38 | const configFileName = answers.configLanguage === 'JavaScript' ? 'cypress.config.js' : 'cypress.config.ts'; 39 | configFilePath = path.join(process.cwd(), configFileName); 40 | const supportDir = path.join(process.cwd(), 'cypress', 'support'); 41 | const supportE2EPath = path.join(supportDir, 'e2e.' + (answers.configLanguage === 'JavaScript' ? 'js' : 'ts')); 42 | const supportCommandsPath = path.join(supportDir, 'commands.' + (answers.configLanguage === 'JavaScript' ? 'js' : 'ts')); 43 | let supportE2EContent; 44 | let supportCommandsContent; 45 | 46 | if (!answers.testDesign && answers.reportChoice) { 47 | switch (answers.reporter) { 48 | case 'mochawesome': 49 | supportE2EContent = ` 50 | // Import commands.js using ES2015 syntax: 51 | import './commands'; 52 | import 'cypress-mochawesome-reporter/register'; 53 | ` 54 | break 55 | case 'allure': 56 | supportE2EContent = ` 57 | // Import commands.js using ES2015 syntax: 58 | import './commands'; 59 | import 'allure-cypress/commands'; 60 | ` 61 | } 62 | } else { 63 | supportE2EContent = ` 64 | // Import commands.js using ES2015 syntax: 65 | import './commands'; 66 | `; 67 | 68 | } 69 | if (answers.configLanguage!='TypeScript'){ 70 | 71 | supportCommandsContent = ` 72 | // *********************************************** 73 | // Visit https://on.cypress.io/custom-commands to 74 | // learn more about custom commands. 75 | // *********************************************** 76 | // 77 | // 78 | // -- This is a parent command -- 79 | // Cypress.Commands.add('login', (email, password) => { ... }) 80 | // 81 | // 82 | // -- This is a child command -- 83 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) 84 | // 85 | // 86 | // -- This is a dual command -- 87 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) 88 | // 89 | // 90 | // -- This will overwrite an existing command -- 91 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })`; 92 | 93 | } else{ 94 | 95 | supportCommandsContent = ` 96 | // *********************************************** 97 | // Visit https://on.cypress.io/custom-commands to 98 | // learn more about custom commands. 99 | // *********************************************** 100 | // 101 | // 102 | // -- This is a parent command -- 103 | // Cypress.Commands.add('login', (email, password) => { ... }) 104 | // 105 | // 106 | // -- This is a child command -- 107 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) 108 | // 109 | // 110 | // -- This is a dual command -- 111 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) 112 | // 113 | // 114 | // -- This will overwrite an existing command -- 115 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) 116 | // declare global { 117 | // namespace Cypress { 118 | // interface Chainable { 119 | // login(email: string, password: string): Chainable 120 | // drag(subject: string, options?: Partial): Chainable 121 | // dismiss(subject: string, options?: Partial): Chainable 122 | // visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable 123 | // } 124 | // } 125 | // } 126 | // `; 127 | } 128 | await fs.writeFile(supportE2EPath, supportE2EContent); 129 | await fs.writeFile(supportCommandsPath, supportCommandsContent); 130 | 131 | // Create BDD specific files if BDD is selected 132 | if (answers.testDesign) { 133 | const bddTestDir = path.join(process.cwd(), 'cypress', 'e2e', 'tests'); 134 | await fs.ensureDir(bddTestDir); 135 | 136 | const stepsSpecPath = path.join(bddTestDir, 'steps.spec.cy.' + (answers.configLanguage === 'JavaScript' ? 'js' : 'ts')); 137 | const stepsSpecContent = ` 138 | import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'; 139 | 140 | Given(/^I am on the home page$/, () => { 141 | cy.visit('/'); 142 | }); 143 | 144 | When(/^I click on doc link$/, () => { 145 | return true; 146 | }); 147 | 148 | Then(/^I should see cypress doc$/, () => { 149 | return true; 150 | }); 151 | `; 152 | await fs.writeFile(stepsSpecPath, stepsSpecContent); 153 | 154 | const featurePath = path.join('cypress', 'e2e', 'tests.feature'); 155 | const featureContent = ` 156 | Feature: Sample Test 157 | 158 | Scenario: Check site is available 159 | Given I am on the home page 160 | When I click on doc link 161 | Then I should see cypress doc 162 | `; 163 | await fs.writeFile(featurePath, featureContent); 164 | } 165 | // Create report generetor based on BDD selected and multiCucumber report selected 166 | 167 | const reportGenDir = path.join(process.cwd(), 'reportGen.js'); 168 | 169 | if (answers.reportChoice && answers.reporter === 'multipleCucumber') { 170 | const multipleCucumberGeneratorConfig = ` 171 | const report = require("multiple-cucumber-html-reporter"); 172 | 173 | report.generate({ 174 | jsonDir: "./reports/json/", 175 | reportPath: "./reports/html/cucumber-report/", 176 | }); 177 | `; 178 | 179 | await fs.writeFile(reportGenDir, multipleCucumberGeneratorConfig); 180 | } 181 | 182 | 183 | 184 | // Create tsconfig.json if TypeScript is selected 185 | if (answers.configLanguage === 'TypeScript') { 186 | const tsConfigFilePath = path.join(process.cwd(), 'cypress', 'tsconfig.json'); 187 | const tsConfigContent = ` 188 | { 189 | "compilerOptions": { 190 | "esModuleInterop": true, 191 | "module": "nodenext", 192 | "target": "es5", 193 | "lib": [ 194 | "es5", 195 | "dom" 196 | ], 197 | "types": [ 198 | "cypress", 199 | "node" 200 | ] 201 | }, 202 | "include": [ 203 | "**/*.ts" 204 | ] 205 | } 206 | `; 207 | await fs.writeFile(tsConfigFilePath, tsConfigContent); 208 | } 209 | console.log(`Configuration file created at ${configFilePath}`); 210 | } 211 | -------------------------------------------------------------------------------- /src/utils/npmDependencies.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import fs from 'fs-extra'; 4 | import path from 'path'; 5 | 6 | export async function createPackageJsonFile(answers) { 7 | const packageJsonPath = path.join(process.cwd(), 'package.json'); 8 | 9 | const packageJsonContent = { 10 | "name": "cypress-project", 11 | "version": "1.0.0", 12 | "description": "A Cypress project configured automatically", 13 | "main": "index.js", 14 | "scripts": { 15 | "test": "npx cypress run" 16 | }, 17 | "devDependencies": { 18 | "cypress": "latest" 19 | } 20 | 21 | }; 22 | 23 | if (answers.testDesign) { 24 | packageJsonContent.devDependencies["@badeball/cypress-cucumber-preprocessor"] = "latest"; 25 | 26 | if (answers.bundler === 'browserify') { 27 | packageJsonContent.devDependencies["@cypress/browserify-preprocessor"] = "latest"; 28 | } else if (answers.bundler === 'esbuild') { 29 | packageJsonContent.devDependencies["@bahmutov/cypress-esbuild-preprocessor"] = "latest"; 30 | } else if (answers.bundler === 'webpack') { 31 | packageJsonContent.devDependencies["@cypress/webpack-preprocessor"] = "latest"; 32 | packageJsonContent.devDependencies["webpack"] = "latest"; // Adding webpack itself as a dependency 33 | } 34 | } 35 | 36 | if (answers.testDesign && answers.reportChoice) { 37 | // let packageJsonObject = JSON.parse(packageJsonContent); 38 | packageJsonContent["cypress-cucumber-preprocessor"] = { 39 | "json": { 40 | "enabled": true, 41 | "output": "reports/json/results.json" 42 | } 43 | }; 44 | await fs.writeFile(packageJsonPath, JSON.stringify(packageJsonContent, null, 2)); 45 | 46 | switch (answers.reporter) { 47 | case 'badeball': 48 | packageJsonContent["cypress-cucumber-preprocessor"]["html"] = { 49 | "enabled": true, 50 | "output": "reports/html/results.html" 51 | } 52 | break 53 | case 'multipleCucumber': 54 | packageJsonContent.devDependencies["multiple-cucumber-html-reporter"] = "latest"; 55 | 56 | } 57 | 58 | 59 | } else if (answers.reportChoice) { 60 | switch (answers.reporter) { 61 | case 'mochawesome': 62 | packageJsonContent.devDependencies["cypress-mochawesome-reporter"] = "^3.8.2"; 63 | break 64 | case 'allure': 65 | packageJsonContent.devDependencies["allure-commandline"] = "^2.29.0"; 66 | packageJsonContent.devDependencies["allure-cypress"] = "^2.15.1"; 67 | 68 | } 69 | } 70 | 71 | // Add typescript as a dependency if TypeScript is selected 72 | if (answers.configLanguage === 'TypeScript') { 73 | packageJsonContent.devDependencies["typescript"] = "latest"; 74 | if (answers.bundler === 'webpack') { 75 | packageJsonContent.devDependencies["ts-loader"] = "latest"; 76 | } 77 | } 78 | 79 | // Add safari browser support and eslint to BDD and reporter 80 | if (answers.lintSetup){ 81 | packageJsonContent.devDependencies["eslint"] = "latest"; 82 | packageJsonContent.devDependencies["eslint-plugin-cypress"] = "latest"; 83 | if(answers.safariSupport){ 84 | packageJsonContent.devDependencies["playwright-webkit"] = "latest"; 85 | console.log('For Linux users run: npx playwright install-deps webkit'); 86 | if(answers.testDesign){ 87 | packageJsonContent.devDependencies["@badeball/cypress-cucumber-preprocessor"] = "latest"; 88 | 89 | switch(answers.bundler){ 90 | case 'webpack': 91 | packageJsonContent.devDependencies["@cypress/webpack-preprocessor"] = "latest"; 92 | packageJsonContent.devDependencies["webpack"] = "latest"; 93 | break; 94 | case 'esbuild': 95 | packageJsonContent.devDependencies["@bahmutov/cypress-esbuild-preprocessor"] = "latest"; 96 | break; 97 | case 'browserify': 98 | packageJsonContent.devDependencies["@cypress/browserify-preprocessor"] = "latest"; 99 | 100 | } 101 | } else if (answers.testDesign && answers.reportChoice) { 102 | // let packageJsonObject = JSON.parse(packageJsonContent); 103 | packageJsonContent["cypress-cucumber-preprocessor"] = { 104 | "json": { 105 | "enabled": true, 106 | "output": "reports/json/results.json" 107 | } 108 | }; 109 | await fs.writeFile(packageJsonPath, JSON.stringify(packageJsonContent, null, 2)); 110 | 111 | switch (answers.reporter) { 112 | case 'badeball': 113 | packageJsonContent["cypress-cucumber-preprocessor"]["html"] = { 114 | "enabled": true, 115 | "output": "reports/html/results.html" 116 | } 117 | break 118 | case 'multipleCucumber': 119 | packageJsonContent.devDependencies["multiple-cucumber-html-reporter"] = "latest"; 120 | 121 | } 122 | 123 | 124 | }else if (answers.reportChoice) { 125 | switch (answers.reporter) { 126 | case 'mochawesome': 127 | packageJsonContent.devDependencies["cypress-mochawesome-reporter"] = "^3.8.2"; 128 | break 129 | case 'allure': 130 | packageJsonContent.devDependencies["allure-commandline"] = "^2.29.0"; 131 | packageJsonContent.devDependencies["allure-cypress"] = "^2.15.1"; 132 | 133 | } 134 | } 135 | } 136 | 137 | } else { 138 | if(answers.safariSupport){ 139 | packageJsonContent.devDependencies["playwright-webkit"] = "latest"; 140 | console.log('For Linux users run: npx playwright install-deps webkit'); 141 | if(answers.testDesign){ 142 | packageJsonContent.devDependencies["@badeball/cypress-cucumber-preprocessor"] = "latest"; 143 | 144 | switch(answers.bundler){ 145 | case 'webpack': 146 | packageJsonContent.devDependencies["@cypress/webpack-preprocessor"] = "latest"; 147 | packageJsonContent.devDependencies["webpack"] = "latest"; 148 | break; 149 | case 'esbuild': 150 | packageJsonContent.devDependencies["@bahmutov/cypress-esbuild-preprocessor"] = "latest"; 151 | break; 152 | case 'browserify': 153 | packageJsonContent.devDependencies["@cypress/browserify-preprocessor"] = "latest"; 154 | 155 | } 156 | } else if (answers.testDesign && answers.reportChoice) { 157 | // let packageJsonObject = JSON.parse(packageJsonContent); 158 | packageJsonContent["cypress-cucumber-preprocessor"] = { 159 | "json": { 160 | "enabled": true, 161 | "output": "reports/json/results.json" 162 | } 163 | }; 164 | await fs.writeFile(packageJsonPath, JSON.stringify(packageJsonContent, null, 2)); 165 | 166 | switch (answers.reporter) { 167 | case 'badeball': 168 | packageJsonContent["cypress-cucumber-preprocessor"]["html"] = { 169 | "enabled": true, 170 | "output": "reports/html/results.html" 171 | } 172 | break 173 | case 'multipleCucumber': 174 | packageJsonContent.devDependencies["multiple-cucumber-html-reporter"] = "latest"; 175 | 176 | } 177 | 178 | 179 | }else if (answers.reportChoice) { 180 | switch (answers.reporter) { 181 | case 'mochawesome': 182 | packageJsonContent.devDependencies["cypress-mochawesome-reporter"] = "^3.8.2"; 183 | break 184 | case 'allure': 185 | packageJsonContent.devDependencies["allure-commandline"] = "^2.29.0"; 186 | packageJsonContent.devDependencies["allure-cypress"] = "^2.15.1"; 187 | 188 | } 189 | } 190 | } 191 | 192 | } 193 | // Write package.json 194 | await fs.writeJson(packageJsonPath, packageJsonContent, { spaces: 2 }); 195 | 196 | console.log('Created package.json'); 197 | } 198 | -------------------------------------------------------------------------------- /src/utils/config.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import fs from 'fs-extra'; 4 | import path from 'path'; 5 | 6 | export async function createConfigFile(answers) { 7 | const configFileName = answers.configLanguage === 'JavaScript' ? 'cypress.config.js' : 'cypress.config.ts'; 8 | const configFilePath = path.join(process.cwd(), configFileName); 9 | const eslintFilePath = path.join(process.cwd(), 'eslint.config.js'); 10 | let configContent; 11 | 12 | const reporterConfig = { 13 | mochawesome: ` 14 | const { defineConfig } = require('cypress'); 15 | module.exports = defineConfig({ 16 | reporter: 'cypress-mochawesome-reporter', 17 | e2e: { 18 | baseUrl: '${answers.baseUrl}', 19 | setupNodeEvents(on, config) { 20 | require('cypress-mochawesome-reporter/plugin')(on); 21 | } 22 | } 23 | }); 24 | `, 25 | allure: ` 26 | const { defineConfig } = require('cypress'); 27 | const { allureCypress } = require("allure-cypress/reporter"); 28 | module.exports = defineConfig({ 29 | e2e: { 30 | baseUrl: '${answers.baseUrl}', 31 | setupNodeEvents(on, config) { 32 | allureCypress(on); 33 | } 34 | } 35 | }); 36 | ` 37 | }; 38 | 39 | const bundlerConfig = { 40 | browserify: answers.configLanguage === 'JavaScript' ? ` 41 | const { defineConfig } = require("cypress"); 42 | const browserify = require("@cypress/browserify-preprocessor"); 43 | const { addCucumberPreprocessorPlugin } = require("@badeball/cypress-cucumber-preprocessor"); 44 | const { preprendTransformerToOptions } = require("@badeball/cypress-cucumber-preprocessor/browserify"); 45 | 46 | async function setupNodeEvents(on, config) { 47 | await addCucumberPreprocessorPlugin(on, config); 48 | 49 | on( 50 | "file:preprocessor", 51 | browserify(preprendTransformerToOptions(config, browserify.defaultOptions)) 52 | ); 53 | 54 | return config; 55 | } 56 | 57 | module.exports = defineConfig({ 58 | e2e: { 59 | baseUrl: '${answers.baseUrl}', 60 | specPattern: '**/*.feature', 61 | setupNodeEvents, 62 | }, 63 | }); 64 | ` : ` 65 | import { defineConfig } from "cypress"; 66 | import browserify from "@cypress/browserify-preprocessor"; 67 | import { addCucumberPreprocessorPlugin } from "@badeball/cypress-cucumber-preprocessor"; 68 | import { preprendTransformerToOptions } from "@badeball/cypress-cucumber-preprocessor/browserify"; 69 | 70 | async function setupNodeEvents( 71 | on: Cypress.PluginEvents, 72 | config: Cypress.PluginConfigOptions, 73 | ): Promise { 74 | 75 | await addCucumberPreprocessorPlugin(on, config); 76 | 77 | on( 78 | "file:preprocessor", 79 | browserify({ 80 | ...preprendTransformerToOptions(config, browserify.defaultOptions), 81 | typescript: require.resolve("typescript"), 82 | }), 83 | ); 84 | 85 | 86 | return config; 87 | } 88 | 89 | export default defineConfig({ 90 | e2e: { 91 | baseUrl: '${answers.baseUrl}', 92 | specPattern: '**/*.feature', 93 | setupNodeEvents, 94 | }, 95 | }); 96 | `, 97 | esbuild: answers.configLanguage === 'JavaScript' ? ` 98 | const { defineConfig } = require("cypress"); 99 | const createBundler = require("@bahmutov/cypress-esbuild-preprocessor"); 100 | const { 101 | addCucumberPreprocessorPlugin, 102 | } = require("@badeball/cypress-cucumber-preprocessor"); 103 | const { 104 | createEsbuildPlugin, 105 | } = require("@badeball/cypress-cucumber-preprocessor/esbuild"); 106 | 107 | async function setupNodeEvents(on, config) { 108 | await addCucumberPreprocessorPlugin(on, config); 109 | 110 | on( 111 | "file:preprocessor", 112 | createBundler({ 113 | plugins: [createEsbuildPlugin(config)], 114 | }) 115 | ); 116 | 117 | return config; 118 | } 119 | 120 | module.exports = defineConfig({ 121 | e2e: { 122 | baseUrl: '${answers.baseUrl}', 123 | specPattern: '**/*.feature', 124 | setupNodeEvents, 125 | } 126 | }); 127 | ` : ` 128 | import { defineConfig } from "cypress"; 129 | import createBundler from "@bahmutov/cypress-esbuild-preprocessor"; 130 | import { addCucumberPreprocessorPlugin } from "@badeball/cypress-cucumber-preprocessor"; 131 | import { createEsbuildPlugin } from "@badeball/cypress-cucumber-preprocessor/esbuild"; 132 | 133 | async function setupNodeEvents( 134 | on: Cypress.PluginEvents, 135 | config: Cypress.PluginConfigOptions 136 | ): Promise { 137 | await addCucumberPreprocessorPlugin(on, config); 138 | 139 | on( 140 | "file:preprocessor", 141 | createBundler({ 142 | plugins: [createEsbuildPlugin(config)], 143 | }) 144 | ); 145 | 146 | return config; 147 | } 148 | 149 | export default defineConfig({ 150 | e2e: { 151 | baseUrl: '${answers.baseUrl}', 152 | specPattern: '**/*.feature', 153 | setupNodeEvents, 154 | }, 155 | }); 156 | `, 157 | webpack: answers.configLanguage === 'JavaScript' ? ` 158 | const { defineConfig } = require("cypress"); 159 | const webpack = require("@cypress/webpack-preprocessor"); 160 | const { 161 | addCucumberPreprocessorPlugin, 162 | } = require("@badeball/cypress-cucumber-preprocessor"); 163 | 164 | async function setupNodeEvents(on, config) { 165 | await addCucumberPreprocessorPlugin(on, config); 166 | 167 | on( 168 | "file:preprocessor", 169 | webpack({ 170 | webpackOptions: { 171 | resolve: { 172 | extensions: [".ts", ".js"], 173 | }, 174 | module: { 175 | rules: [ 176 | { 177 | test: /\.feature$/, 178 | use: [ 179 | { 180 | loader: "@badeball/cypress-cucumber-preprocessor/webpack", 181 | options: config, 182 | }, 183 | ], 184 | }, 185 | ], 186 | }, 187 | }, 188 | }) 189 | ); 190 | 191 | return config; 192 | } 193 | 194 | module.exports = defineConfig({ 195 | e2e: { 196 | baseUrl: '${answers.baseUrl}', 197 | specPattern: '**/*.feature', 198 | setupNodeEvents, 199 | }, 200 | }); 201 | ` : ` 202 | import { defineConfig } from "cypress"; 203 | import webpack from "@cypress/webpack-preprocessor"; 204 | import { addCucumberPreprocessorPlugin } from "@badeball/cypress-cucumber-preprocessor"; 205 | 206 | async function setupNodeEvents( 207 | on: Cypress.PluginEvents, 208 | config: Cypress.PluginConfigOptions 209 | ): Promise { 210 | await addCucumberPreprocessorPlugin(on, config); 211 | 212 | on( 213 | "file:preprocessor", 214 | webpack({ 215 | webpackOptions: { 216 | resolve: { 217 | extensions: [".ts", ".js"], 218 | }, 219 | module: { 220 | rules: [ 221 | { 222 | test: /\.ts$/, 223 | exclude: [/node_modules/], 224 | use: [ 225 | { 226 | loader: "ts-loader", 227 | }, 228 | ], 229 | }, 230 | { 231 | test: /\.feature$/, 232 | use: [ 233 | { 234 | loader: "@badeball/cypress-cucumber-preprocessor/webpack", 235 | options: config, 236 | }, 237 | ], 238 | }, 239 | ], 240 | }, 241 | }, 242 | }) 243 | ); 244 | 245 | return config; 246 | } 247 | 248 | export default defineConfig({ 249 | e2e: { 250 | baseUrl: '${answers.baseUrl}', 251 | specPattern: '**/*.feature', 252 | setupNodeEvents, 253 | } 254 | }); 255 | ` 256 | }; 257 | 258 | 259 | const reporterSafariConfig = { 260 | mochawesome: ` 261 | const { defineConfig } = require('cypress'); 262 | module.exports = defineConfig({ 263 | reporter: 'cypress-mochawesome-reporter', 264 | e2e: { 265 | baseUrl: '${answers.baseUrl}', 266 | experimentalWebKitSupport: true, 267 | setupNodeEvents(on, config) { 268 | require('cypress-mochawesome-reporter/plugin')(on); 269 | } 270 | } 271 | }); 272 | `, 273 | allure: ` 274 | const { defineConfig } = require('cypress'); 275 | const { allureCypress } = require("allure-cypress/reporter"); 276 | module.exports = defineConfig({ 277 | e2e: { 278 | baseUrl: '${answers.baseUrl}', 279 | experimentalWebKitSupport: true, 280 | setupNodeEvents(on, config) { 281 | allureCypress(on); 282 | } 283 | } 284 | }); 285 | ` 286 | }; 287 | 288 | const bundlerSafariConfig = { 289 | browserify: answers.configLanguage === 'JavaScript' ? ` 290 | const { defineConfig } = require("cypress"); 291 | const browserify = require("@cypress/browserify-preprocessor"); 292 | const { addCucumberPreprocessorPlugin } = require("@badeball/cypress-cucumber-preprocessor"); 293 | const { preprendTransformerToOptions } = require("@badeball/cypress-cucumber-preprocessor/browserify"); 294 | 295 | async function setupNodeEvents(on, config) { 296 | await addCucumberPreprocessorPlugin(on, config); 297 | 298 | on( 299 | "file:preprocessor", 300 | browserify(preprendTransformerToOptions(config, browserify.defaultOptions)) 301 | ); 302 | 303 | return config; 304 | } 305 | 306 | module.exports = defineConfig({ 307 | e2e: { 308 | baseUrl: '${answers.baseUrl}', 309 | experimentalWebKitSupport: true, 310 | specPattern: '**/*.feature', 311 | setupNodeEvents, 312 | }, 313 | }); 314 | ` : ` 315 | import { defineConfig } from "cypress"; 316 | import browserify from "@cypress/browserify-preprocessor"; 317 | import { addCucumberPreprocessorPlugin } from "@badeball/cypress-cucumber-preprocessor"; 318 | import { preprendTransformerToOptions } from "@badeball/cypress-cucumber-preprocessor/browserify"; 319 | 320 | async function setupNodeEvents( 321 | on: Cypress.PluginEvents, 322 | config: Cypress.PluginConfigOptions, 323 | ): Promise { 324 | 325 | await addCucumberPreprocessorPlugin(on, config); 326 | 327 | on( 328 | "file:preprocessor", 329 | browserify({ 330 | ...preprendTransformerToOptions(config, browserify.defaultOptions), 331 | typescript: require.resolve("typescript"), 332 | }), 333 | ); 334 | 335 | 336 | return config; 337 | } 338 | 339 | export default defineConfig({ 340 | e2e: { 341 | baseUrl: '${answers.baseUrl}', 342 | experimentalWebKitSupport: true, 343 | specPattern: '**/*.feature', 344 | setupNodeEvents, 345 | }, 346 | }); 347 | `, 348 | esbuild: answers.configLanguage === 'JavaScript' ? ` 349 | const { defineConfig } = require("cypress"); 350 | const createBundler = require("@bahmutov/cypress-esbuild-preprocessor"); 351 | const { 352 | addCucumberPreprocessorPlugin, 353 | } = require("@badeball/cypress-cucumber-preprocessor"); 354 | const { 355 | createEsbuildPlugin, 356 | } = require("@badeball/cypress-cucumber-preprocessor/esbuild"); 357 | 358 | async function setupNodeEvents(on, config) { 359 | await addCucumberPreprocessorPlugin(on, config); 360 | 361 | on( 362 | "file:preprocessor", 363 | createBundler({ 364 | plugins: [createEsbuildPlugin(config)], 365 | }) 366 | ); 367 | 368 | return config; 369 | } 370 | 371 | module.exports = defineConfig({ 372 | e2e: { 373 | baseUrl: '${answers.baseUrl}', 374 | experimentalWebKitSupport: true, 375 | specPattern: '**/*.feature', 376 | setupNodeEvents, 377 | } 378 | }); 379 | ` : ` 380 | import { defineConfig } from "cypress"; 381 | import createBundler from "@bahmutov/cypress-esbuild-preprocessor"; 382 | import { addCucumberPreprocessorPlugin } from "@badeball/cypress-cucumber-preprocessor"; 383 | import { createEsbuildPlugin } from "@badeball/cypress-cucumber-preprocessor/esbuild"; 384 | 385 | async function setupNodeEvents( 386 | on: Cypress.PluginEvents, 387 | config: Cypress.PluginConfigOptions 388 | ): Promise { 389 | await addCucumberPreprocessorPlugin(on, config); 390 | 391 | on( 392 | "file:preprocessor", 393 | createBundler({ 394 | plugins: [createEsbuildPlugin(config)], 395 | }) 396 | ); 397 | 398 | return config; 399 | } 400 | 401 | export default defineConfig({ 402 | e2e: { 403 | baseUrl: '${answers.baseUrl}', 404 | experimentalWebKitSupport: true, 405 | specPattern: '**/*.feature', 406 | setupNodeEvents, 407 | }, 408 | }); 409 | `, 410 | webpack: answers.configLanguage === 'JavaScript' ? ` 411 | const { defineConfig } = require("cypress"); 412 | const webpack = require("@cypress/webpack-preprocessor"); 413 | const { 414 | addCucumberPreprocessorPlugin, 415 | } = require("@badeball/cypress-cucumber-preprocessor"); 416 | 417 | async function setupNodeEvents(on, config) { 418 | await addCucumberPreprocessorPlugin(on, config); 419 | 420 | on( 421 | "file:preprocessor", 422 | webpack({ 423 | webpackOptions: { 424 | resolve: { 425 | extensions: [".ts", ".js"], 426 | }, 427 | module: { 428 | rules: [ 429 | { 430 | test: /\.feature$/, 431 | use: [ 432 | { 433 | loader: "@badeball/cypress-cucumber-preprocessor/webpack", 434 | options: config, 435 | }, 436 | ], 437 | }, 438 | ], 439 | }, 440 | }, 441 | }) 442 | ); 443 | 444 | return config; 445 | } 446 | 447 | module.exports = defineConfig({ 448 | e2e: { 449 | baseUrl: '${answers.baseUrl}', 450 | experimentalWebKitSupport: true, 451 | specPattern: '**/*.feature', 452 | setupNodeEvents, 453 | }, 454 | }); 455 | ` : ` 456 | import { defineConfig } from "cypress"; 457 | import webpack from "@cypress/webpack-preprocessor"; 458 | import { addCucumberPreprocessorPlugin } from "@badeball/cypress-cucumber-preprocessor"; 459 | 460 | async function setupNodeEvents( 461 | on: Cypress.PluginEvents, 462 | config: Cypress.PluginConfigOptions 463 | ): Promise { 464 | await addCucumberPreprocessorPlugin(on, config); 465 | 466 | on( 467 | "file:preprocessor", 468 | webpack({ 469 | webpackOptions: { 470 | resolve: { 471 | extensions: [".ts", ".js"], 472 | }, 473 | module: { 474 | rules: [ 475 | { 476 | test: /\.ts$/, 477 | exclude: [/node_modules/], 478 | use: [ 479 | { 480 | loader: "ts-loader", 481 | }, 482 | ], 483 | }, 484 | { 485 | test: /\.feature$/, 486 | use: [ 487 | { 488 | loader: "@badeball/cypress-cucumber-preprocessor/webpack", 489 | options: config, 490 | }, 491 | ], 492 | }, 493 | ], 494 | }, 495 | }, 496 | }) 497 | ); 498 | 499 | return config; 500 | } 501 | 502 | export default defineConfig({ 503 | e2e: { 504 | baseUrl: '${answers.baseUrl}', 505 | experimentalWebKitSupport: true, 506 | specPattern: '**/*.feature', 507 | setupNodeEvents, 508 | } 509 | }); 510 | ` 511 | }; 512 | 513 | if (answers.safariSupport) { 514 | 515 | if(answers.testDesign){ 516 | configContent = bundlerSafariConfig[answers.bundler]; 517 | }else if (answers.reportChoice){ 518 | configContent = reporterSafariConfig[answers.reporter]; 519 | }else{ 520 | configContent = answers.configLanguage === 'JavaScript' ? ` 521 | const { defineConfig } = require('cypress'); 522 | 523 | module.exports = defineConfig({ 524 | e2e: { 525 | baseUrl: '${answers.baseUrl}', 526 | experimentalWebKitSupport: true, 527 | setupNodeEvents(on, config) { 528 | // implement node event listeners here 529 | }, 530 | }, 531 | }); 532 | ` : ` 533 | import { defineConfig } from 'cypress'; 534 | 535 | export default defineConfig({ 536 | e2e: { 537 | baseUrl: '${answers.baseUrl}', 538 | experimentalWebKitSupport: true, 539 | setupNodeEvents(on, config) { 540 | // implement node event listeners here 541 | }, 542 | }, 543 | }); 544 | `; 545 | 546 | } 547 | 548 | } 549 | else { 550 | 551 | if(answers.testDesign){ 552 | configContent = bundlerConfig[answers.bundler]; 553 | }else if (answers.reportChoice){ 554 | configContent = reporterConfig[answers.reporter]; 555 | }else{ 556 | configContent = answers.configLanguage === 'JavaScript' ? ` 557 | const { defineConfig } = require('cypress'); 558 | 559 | module.exports = defineConfig({ 560 | e2e: { 561 | baseUrl: '${answers.baseUrl}', 562 | setupNodeEvents(on, config) { 563 | // implement node event listeners here 564 | }, 565 | }, 566 | }); 567 | ` : ` 568 | import { defineConfig } from 'cypress'; 569 | 570 | export default defineConfig({ 571 | e2e: { 572 | baseUrl: '${answers.baseUrl}', 573 | setupNodeEvents(on, config) { 574 | // implement node event listeners here 575 | }, 576 | }, 577 | }); 578 | `; 579 | 580 | } 581 | } 582 | 583 | await fs.outputFile(configFilePath, configContent); 584 | console.log(`Created ${configFileName}`); 585 | 586 | const lintConfig = ` 587 | import pluginCypress from 'eslint-plugin-cypress/flat' 588 | export default [ 589 | pluginCypress.configs.recommended, 590 | { 591 | rules: { 592 | 'cypress/no-unnecessary-waiting': 'warn' 593 | } 594 | } 595 | ] 596 | `; 597 | 598 | if (answers.lintSetup) { 599 | await fs.outputFile(eslintFilePath, lintConfig); 600 | console.log(`Eslint has been configured and is located at ${eslintFilePath}`); 601 | } 602 | } 603 | 604 | 605 | --------------------------------------------------------------------------------