diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index c7063fa..d145434 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,18 +1,18 @@
version: 2
updates:
- - package-ecosystem: 'npm'
- directory: '/'
+ - package-ecosystem: "npm"
+ directory: "/"
schedule:
- interval: 'weekly'
+ interval: "weekly"
groups:
babel:
patterns:
- - '@babel/*'
+ - "@babel/*"
reviewers:
- - '@ExpediaGroup/cypress-codegen-admins'
- - package-ecosystem: 'github-actions'
- directory: '/'
+ - "@ExpediaGroup/cypress-codegen-admins"
+ - package-ecosystem: "github-actions"
+ directory: "/"
schedule:
- interval: 'weekly'
+ interval: "weekly"
reviewers:
- - '@ExpediaGroup/cypress-codegen-admins'
+ - "@ExpediaGroup/cypress-codegen-admins"
diff --git a/.prettierignore b/.prettierignore
index ee89780..3235ec8 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,2 +1,3 @@
node_modules
pnpm-lock.yaml
+cypress
diff --git a/.prettierrc.json b/.prettierrc.json
deleted file mode 100644
index bdef944..0000000
--- a/.prettierrc.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "printWidth": 100,
- "tabWidth": 2,
- "useTabs": false,
- "singleQuote": true,
- "trailingComma": "none",
- "bracketSpacing": true,
- "arrowParens": "avoid"
-}
diff --git a/.releaserc.yaml b/.releaserc.yaml
index 6ee3a74..5725597 100644
--- a/.releaserc.yaml
+++ b/.releaserc.yaml
@@ -1,5 +1,5 @@
plugins:
- - - '@semantic-release/commit-analyzer'
+ - - "@semantic-release/commit-analyzer"
- preset: angular
releaseRules:
- breaking: true
@@ -12,7 +12,7 @@ plugins:
release: patch
- scope: no-release
release: false
- - '@semantic-release/release-notes-generator'
- - '@semantic-release/github'
+ - "@semantic-release/release-notes-generator"
+ - "@semantic-release/github"
branches:
- main
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 72fc849..607bd23 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -48,7 +48,7 @@ Push your changes to your branch and open a pull request against the parent repo
Upon Pull Request submission, your code will be reviewed by the maintainers. They will confirm at least the following:
-- Tests run successfully (unit, coverage, integration, style).
-- Contribution policy has been followed.
+- Tests run successfully (unit, coverage, integration, style).
+- Contribution policy has been followed.
One (human) reviewer will need to sign off on your Pull Request before it can be merged.
diff --git a/README.md b/README.md
index a9edf27..181ea41 100644
--- a/README.md
+++ b/README.md
@@ -8,11 +8,11 @@ A [Cypress](https://www.cypress.io/) plugin and CLI tool which automatically add
## Table of Contents
-- [Why Do I Need This Plugin?](#why-do-i-need-this-plugin)
-- [Installation](#installation)
-- [Usage](#usage)
-- [Example](#example)
-- [Configuration](#configuration)
+- [Why Do I Need This Plugin?](#why-do-i-need-this-plugin)
+- [Installation](#installation)
+- [Usage](#usage)
+- [Example](#example)
+- [Configuration](#configuration)
## Why Do I Need This Plugin?
@@ -33,27 +33,27 @@ Model your Cypress project exactly like [the one in this repository](https://git
1. Add the required plugin code to `cypress.config.ts` like so:
```ts
-import { cypressCodegen } from 'cypress-codegen';
-import { defineConfig } from 'cypress';
+import { cypressCodegen } from "cypress-codegen";
+import { defineConfig } from "cypress";
export default defineConfig({
- e2e: {
- setupNodeEvents(on, config) {
- cypressCodegen(on, config);
- return config;
- }
- },
-
- component: {
- setupNodeEvents(on, config) {
- cypressCodegen(on, config);
- return config;
+ e2e: {
+ setupNodeEvents(on, config) {
+ cypressCodegen(on, config);
+ return config;
+ },
+ },
+
+ component: {
+ setupNodeEvents(on, config) {
+ cypressCodegen(on, config);
+ return config;
+ },
+ devServer: {
+ framework: "react",
+ bundler: "vite",
+ },
},
- devServer: {
- framework: 'react',
- bundler: 'vite'
- }
- }
});
```
diff --git a/cypress.config.ts b/cypress.config.ts
index eeaa118..7054b27 100644
--- a/cypress.config.ts
+++ b/cypress.config.ts
@@ -1,26 +1,32 @@
-import { cypressCodegen } from 'cypress-codegen';
-import { defineConfig } from 'cypress';
+import { cypressCodegen } from "cypress-codegen";
+import { defineConfig } from "cypress";
export default defineConfig({
screenshotOnRunFailure: false,
video: false,
e2e: {
- setupNodeEvents(on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) {
+ setupNodeEvents(
+ on: Cypress.PluginEvents,
+ config: Cypress.PluginConfigOptions,
+ ) {
cypressCodegen(on, config);
return config;
- }
+ },
},
component: {
devServer: {
- framework: 'react',
- bundler: 'vite',
- viteConfig: {}
+ framework: "react",
+ bundler: "vite",
+ viteConfig: {},
},
- setupNodeEvents(on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) {
+ setupNodeEvents(
+ on: Cypress.PluginEvents,
+ config: Cypress.PluginConfigOptions,
+ ) {
cypressCodegen(on, config);
return config;
- }
- }
+ },
+ },
});
diff --git a/cypress/commands/custom-mount.tsx b/cypress/commands/custom-mount.tsx
index 5fc9046..4b71359 100644
--- a/cypress/commands/custom-mount.tsx
+++ b/cypress/commands/custom-mount.tsx
@@ -1,10 +1,10 @@
-import * as React from 'react';
+import * as React from "react";
export const customMount = (Component: React.FC) => {
cy.mount(
-
+ ,
);
};
diff --git a/cypress/commands/example.ts b/cypress/commands/example.ts
index 42e6e4d..c0a0690 100644
--- a/cypress/commands/example.ts
+++ b/cypress/commands/example.ts
@@ -12,14 +12,14 @@ limitations under the License.
*/
export function functionExample(input: string) {
- cy.log('Here is a custom command!')
- .log('And it preserves my code styling')
- .log('When I chain commands on new lines!');
+ cy.log("Here is a custom command!")
+ .log("And it preserves my code styling")
+ .log("When I chain commands on new lines!");
cy.contains(input);
}
export const arrowFunctionExample = (input: string) => {
- cy.log('Here is a custom command from an arrow function!');
+ cy.log("Here is a custom command from an arrow function!");
cy.contains(input);
};
diff --git a/cypress/commands/index.ts b/cypress/commands/index.ts
index 898b127..247b125 100644
--- a/cypress/commands/index.ts
+++ b/cypress/commands/index.ts
@@ -1,4 +1,4 @@
/** Generated by cypress-codegen **/
-export * from './example';
-export * from './custom-mount';
-export * from './nested/nested-example';
+export * from "./example";
+export * from "./custom-mount";
+export * from "./nested/nested-example";
diff --git a/cypress/commands/nested/nested-example.ts b/cypress/commands/nested/nested-example.ts
index d97a899..a881e52 100644
--- a/cypress/commands/nested/nested-example.ts
+++ b/cypress/commands/nested/nested-example.ts
@@ -12,7 +12,7 @@ limitations under the License.
*/
export const nestedExample = (input: string) => {
- cy.log('Here is a custom command in a nested directory!');
+ cy.log("Here is a custom command in a nested directory!");
cy.contains(input);
};
diff --git a/cypress/component/component-example.cy.tsx b/cypress/component/component-example.cy.tsx
index 7ae45c2..0409b70 100644
--- a/cypress/component/component-example.cy.tsx
+++ b/cypress/component/component-example.cy.tsx
@@ -11,37 +11,37 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import * as React from 'react';
-
-const componentText = 'Here is a component';
-
-describe('Example Test', () => {
- beforeEach(() => {
- cy.mount({componentText}
);
- });
-
- it('should import custom commands in component tests', () => {
- cy.functionExample(componentText);
- });
-
- it('should dynamically import custom commands from arrow functions', () => {
- cy.arrowFunctionExample(componentText);
- });
-
- it('should dynamically import nested custom commands', () => {
- cy.nestedExample(componentText);
- });
-
- it('should chain custom commands', () => {
- cy.log(componentText)
- .functionExample(componentText)
- .arrowFunctionExample(componentText)
- .nestedExample(componentText);
- });
-
- it('should support custom mount commands', () => {
- const myComponent = () => <>{'Different text'}>;
- cy.customMount(myComponent);
- cy.contains('Different text');
- });
+import * as React from "react";
+
+const componentText = "Here is a component";
+
+describe("Example Test", () => {
+ beforeEach(() => {
+ cy.mount({componentText}
);
+ });
+
+ it("should import custom commands in component tests", () => {
+ cy.functionExample(componentText);
+ });
+
+ it("should dynamically import custom commands from arrow functions", () => {
+ cy.arrowFunctionExample(componentText);
+ });
+
+ it("should dynamically import nested custom commands", () => {
+ cy.nestedExample(componentText);
+ });
+
+ it("should chain custom commands", () => {
+ cy.log(componentText)
+ .functionExample(componentText)
+ .arrowFunctionExample(componentText)
+ .nestedExample(componentText);
+ });
+
+ it("should support custom mount commands", () => {
+ const myComponent = () => <>{"Different text"}>;
+ cy.customMount(myComponent);
+ cy.contains("Different text");
+ });
});
diff --git a/cypress/e2e/e2e-example.cy.ts b/cypress/e2e/e2e-example.cy.ts
index 5d902e2..37b3dfb 100644
--- a/cypress/e2e/e2e-example.cy.ts
+++ b/cypress/e2e/e2e-example.cy.ts
@@ -11,26 +11,26 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-const expectedText = 'Kitchen Sink';
+const expectedText = "Kitchen Sink";
-describe('Example Test', () => {
+describe("Example Test", () => {
beforeEach(() => {
- cy.visit('https://example.cypress.io/');
+ cy.visit("https://example.cypress.io/");
});
- it('should dynamically import custom commands from functions', () => {
+ it("should dynamically import custom commands from functions", () => {
cy.functionExample(expectedText);
});
- it('should dynamically import custom commands from arrow functions', () => {
+ it("should dynamically import custom commands from arrow functions", () => {
cy.arrowFunctionExample(expectedText);
});
- it('should dynamically import nested custom commands', () => {
+ it("should dynamically import nested custom commands", () => {
cy.nestedExample(expectedText);
});
- it('should chain custom commands', () => {
+ it("should chain custom commands", () => {
cy.log(expectedText)
.functionExample(expectedText)
.arrowFunctionExample(expectedText)
diff --git a/cypress/support/component-index.html b/cypress/support/component-index.html
index faf3b5f..54c03d5 100644
--- a/cypress/support/component-index.html
+++ b/cypress/support/component-index.html
@@ -1,12 +1,12 @@
-
-
-
-
- Components App
-
-
-
-
+
+
+
+
+ Components App
+
+
+
+
diff --git a/cypress/support/component.ts b/cypress/support/component.ts
index 0967dfc..5153413 100644
--- a/cypress/support/component.ts
+++ b/cypress/support/component.ts
@@ -11,7 +11,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { mount } from 'cypress/react18';
+import { mount } from "cypress/react18";
// Augment the Cypress namespace to include type definitions for
// your custom command.
@@ -25,7 +25,7 @@ declare global {
}
}
-Cypress.Commands.add('mount', mount);
+Cypress.Commands.add("mount", mount);
/** Generated by cypress-codegen **/
-import('../commands').then(Cypress.Commands.addAll);
+import("../commands").then(Cypress.Commands.addAll);
diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts
index ba357b5..06d1855 100644
--- a/cypress/support/e2e.ts
+++ b/cypress/support/e2e.ts
@@ -1,2 +1,2 @@
/** Generated by cypress-codegen **/
-import('../commands').then(Cypress.Commands.addAll);
+import("../commands").then(Cypress.Commands.addAll);
diff --git a/packages/cypress-codegen/.eslintrc.json b/packages/cypress-codegen/.eslintrc.json
index 668607c..f680bf9 100644
--- a/packages/cypress-codegen/.eslintrc.json
+++ b/packages/cypress-codegen/.eslintrc.json
@@ -47,8 +47,7 @@
"github/no-then": "off",
"i18n-text/no-en": "off",
"import/no-unresolved": "off",
- "filenames/match-regex": [2, "(^[a-z-]+$)|(^[a-z-]+\\.test$)"],
- "quotes": ["error", "single"]
+ "filenames/match-regex": [2, "(^[a-z-]+$)|(^[a-z-]+\\.test$)"]
},
"env": {
"node": true,
diff --git a/packages/cypress-codegen/package.json b/packages/cypress-codegen/package.json
index 13bd053..bd29477 100644
--- a/packages/cypress-codegen/package.json
+++ b/packages/cypress-codegen/package.json
@@ -29,7 +29,7 @@
"chalk": "4.1.2",
"commander": "11.1.0",
"glob": "10.3.10",
- "prettier": "3.0.3"
+ "prettier": "3.1.1"
},
"peerDependencies": {
"cypress": ">=12"
diff --git a/packages/cypress-codegen/reset.d.ts b/packages/cypress-codegen/reset.d.ts
index c5f48f7..0615bc9 100644
--- a/packages/cypress-codegen/reset.d.ts
+++ b/packages/cypress-codegen/reset.d.ts
@@ -1,2 +1,2 @@
// https://github.com/total-typescript/ts-reset
-import '@total-typescript/ts-reset';
+import "@total-typescript/ts-reset";
diff --git a/packages/cypress-codegen/src/cli.ts b/packages/cypress-codegen/src/cli.ts
index 24d6826..884e704 100755
--- a/packages/cypress-codegen/src/cli.ts
+++ b/packages/cypress-codegen/src/cli.ts
@@ -1,27 +1,34 @@
#!/usr/bin/env node
/* eslint-disable no-console */
-import * as chalk from 'chalk';
-import { program, Option } from 'commander';
-import { codegen } from './codegen';
+import * as chalk from "chalk";
+import { program, Option } from "commander";
+import { codegen } from "./codegen";
program
.addOption(
- new Option('--testingType ', 'Overrides the default Cypress support file.')
- .choices(['component', 'e2e'])
- .default('e2e')
+ new Option(
+ "--testingType ",
+ "Overrides the default Cypress support file.",
+ )
+ .choices(["component", "e2e"])
+ .default("e2e"),
)
.parse(process.argv);
const { testingType } = program.opts();
-console.log(chalk.yellowBright(`Generating custom command types for ${testingType} tests...`));
+console.log(
+ chalk.yellowBright(
+ `Generating custom command types for ${testingType} tests...`,
+ ),
+);
codegen({ testingType })
.then(() => {
- console.log(chalk.bgGreen('Codegen complete!'));
+ console.log(chalk.bgGreen("Codegen complete!"));
})
- .catch(error => {
- console.error(chalk.bgRed('Codegen failed!'));
+ .catch((error) => {
+ console.error(chalk.bgRed("Codegen failed!"));
console.error(error);
});
diff --git a/packages/cypress-codegen/src/codegen.ts b/packages/cypress-codegen/src/codegen.ts
index db54dcc..9d641da 100644
--- a/packages/cypress-codegen/src/codegen.ts
+++ b/packages/cypress-codegen/src/codegen.ts
@@ -1,13 +1,16 @@
-import { globSync } from 'glob';
-import { resolveConfig } from 'prettier';
-import { generateContentWithExports } from './generate-content-with-exports';
-import { generateContentsWithInterface } from './generate-contents-with-interface';
-import { generateContentWithImports } from './generate-content-with-imports';
-import { writeFileSync } from 'fs';
-import { resolve } from 'path';
+import { globSync } from "glob";
+import { resolveConfig } from "prettier";
+import { generateContentWithExports } from "./generate-content-with-exports";
+import { generateContentsWithInterface } from "./generate-contents-with-interface";
+import { generateContentWithImports } from "./generate-content-with-imports";
+import { writeFileSync } from "fs";
+import { resolve } from "path";
-export const cypressCodegen = (on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) => {
- on('before:browser:launch', async (browser, launchOptions) => {
+export const cypressCodegen = (
+ on: Cypress.PluginEvents,
+ config: Cypress.PluginConfigOptions,
+) => {
+ on("before:browser:launch", async (browser, launchOptions) => {
await codegen(config);
return launchOptions;
@@ -17,22 +20,35 @@ export const cypressCodegen = (on: Cypress.PluginEvents, config: Cypress.PluginC
};
export const codegen = async (config: Partial) => {
- const indexTsFile = 'cypress/commands/index.ts';
- const filePaths = globSync('cypress/commands/**/*', { nodir: true, ignore: indexTsFile });
+ const indexTsFile = "cypress/commands/index.ts";
+ const filePaths = globSync("cypress/commands/**/*", {
+ nodir: true,
+ ignore: indexTsFile,
+ });
const prettierConfig = (await resolveConfig(process.cwd())) ?? {};
- const commandsIndexPath = 'cypress/commands/index.ts';
- const exportFileContents = await generateContentWithExports(filePaths, prettierConfig);
+ const commandsIndexPath = "cypress/commands/index.ts";
+ const exportFileContents = await generateContentWithExports(
+ filePaths,
+ prettierConfig,
+ );
writeFileSync(resolve(commandsIndexPath), exportFileContents);
- const supportFile = config.supportFile || `cypress/support/${config.testingType}.ts`;
- const fileContentsWithImports = await generateContentWithImports(supportFile, prettierConfig);
+ const supportFile =
+ config.supportFile || `cypress/support/${config.testingType}.ts`;
+ const fileContentsWithImports = await generateContentWithImports(
+ supportFile,
+ prettierConfig,
+ );
writeFileSync(resolve(supportFile), fileContentsWithImports);
await Promise.all(
- filePaths.map(async filePath => {
- const fileContentsWithTypes = await generateContentsWithInterface(filePath, prettierConfig);
+ filePaths.map(async (filePath) => {
+ const fileContentsWithTypes = await generateContentsWithInterface(
+ filePath,
+ prettierConfig,
+ );
writeFileSync(resolve(filePath), fileContentsWithTypes);
- })
+ }),
);
};
diff --git a/packages/cypress-codegen/src/generate-content-with-exports.ts b/packages/cypress-codegen/src/generate-content-with-exports.ts
index d213764..19e0311 100644
--- a/packages/cypress-codegen/src/generate-content-with-exports.ts
+++ b/packages/cypress-codegen/src/generate-content-with-exports.ts
@@ -11,23 +11,33 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import * as t from '@babel/types';
-import generate from '@babel/generator';
-import { format, Options } from 'prettier';
-import { join, parse, relative } from 'path';
+import * as t from "@babel/types";
+import generate from "@babel/generator";
+import { format, Options } from "prettier";
+import { join, parse, relative } from "path";
-export const generateContentWithExports = async (filePaths: string[], prettierConfig: Options) => {
- const exportStatements = filePaths.map(filePath => {
+export const generateContentWithExports = async (
+ filePaths: string[],
+ prettierConfig: Options,
+) => {
+ const exportStatements = filePaths.map((filePath) => {
const { dir, name } = parse(filePath);
const pathWithoutExtension = join(dir, name);
- const relativePath = `./${relative('cypress/commands', pathWithoutExtension)}`;
+ const relativePath = `./${relative(
+ "cypress/commands",
+ pathWithoutExtension,
+ )}`;
return t.exportAllDeclaration(t.stringLiteral(relativePath));
});
- t.addComment(exportStatements[0], 'leading', '* Generated by cypress-codegen *');
+ t.addComment(
+ exportStatements[0],
+ "leading",
+ "* Generated by cypress-codegen *",
+ );
const { code: newCode } = generate(t.program(exportStatements));
const resultingCode = `${newCode}\n`;
return await format(resultingCode, {
- parser: 'babel-ts',
- ...prettierConfig
+ parser: "babel-ts",
+ ...prettierConfig,
});
};
diff --git a/packages/cypress-codegen/src/generate-content-with-imports.ts b/packages/cypress-codegen/src/generate-content-with-imports.ts
index 4a6d142..22622fb 100644
--- a/packages/cypress-codegen/src/generate-content-with-imports.ts
+++ b/packages/cypress-codegen/src/generate-content-with-imports.ts
@@ -11,47 +11,55 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { parse } from '@babel/parser';
-import * as t from '@babel/types';
-import generate from '@babel/generator';
-import { readFileSync } from 'fs';
-import { resolve } from 'path';
-import { format, Options } from 'prettier';
+import { parse } from "@babel/parser";
+import * as t from "@babel/types";
+import generate from "@babel/generator";
+import { readFileSync } from "fs";
+import { resolve } from "path";
+import { format, Options } from "prettier";
-export const generateContentWithImports = async (filePath: string, prettierConfig: Options) => {
+export const generateContentWithImports = async (
+ filePath: string,
+ prettierConfig: Options,
+) => {
const contents = readFileSync(resolve(filePath)).toString();
- const ast = parse(contents, { sourceType: 'module', plugins: ['typescript'] });
+ const ast = parse(contents, {
+ sourceType: "module",
+ plugins: ["typescript"],
+ });
const currentNodes = ast.program.body;
- const importsExist = contents.includes('* Generated by cypress-codegen *');
+ const importsExist = contents.includes("* Generated by cypress-codegen *");
if (importsExist) {
return contents;
}
- const { code: existingCode } = generate(t.program(currentNodes), { retainLines: true });
+ const { code: existingCode } = generate(t.program(currentNodes), {
+ retainLines: true,
+ });
const newImportStatement = generateImportStatement();
const { code: newCode } = generate(t.program(newImportStatement));
const resultingCode = `${existingCode}\n\n${newCode}\n`;
return await format(resultingCode, {
- parser: 'babel-ts',
- ...prettierConfig
+ parser: "babel-ts",
+ ...prettierConfig,
});
};
const generateImportStatement = () => {
- const importExpression = t.callExpression(t.identifier('import'), [
- t.stringLiteral('../commands')
+ const importExpression = t.callExpression(t.identifier("import"), [
+ t.stringLiteral("../commands"),
]);
const cypressExpression = t.memberExpression(
- t.memberExpression(t.identifier('Cypress'), t.identifier('Commands')),
- t.identifier('addAll')
+ t.memberExpression(t.identifier("Cypress"), t.identifier("Commands")),
+ t.identifier("addAll"),
);
const fullExpression = t.callExpression(
- t.memberExpression(importExpression, t.identifier('then')),
- [cypressExpression]
+ t.memberExpression(importExpression, t.identifier("then")),
+ [cypressExpression],
);
const importStatement = t.expressionStatement(fullExpression);
- t.addComment(importStatement, 'leading', '* Generated by cypress-codegen *');
+ t.addComment(importStatement, "leading", "* Generated by cypress-codegen *");
return [importStatement];
};
diff --git a/packages/cypress-codegen/src/generate-contents-with-interface.ts b/packages/cypress-codegen/src/generate-contents-with-interface.ts
index f25adf7..2c300ca 100644
--- a/packages/cypress-codegen/src/generate-contents-with-interface.ts
+++ b/packages/cypress-codegen/src/generate-contents-with-interface.ts
@@ -11,32 +11,39 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { parse } from '@babel/parser';
+import { parse } from "@babel/parser";
import type {
AssignmentPattern,
ExportNamedDeclaration,
FunctionDeclaration,
FunctionExpression,
Identifier,
- VariableDeclaration
-} from '@babel/types';
-import * as t from '@babel/types';
-import generate from '@babel/generator';
-import { readFileSync } from 'fs';
-import { resolve } from 'path';
-import { format, Options } from 'prettier';
+ VariableDeclaration,
+} from "@babel/types";
+import * as t from "@babel/types";
+import generate from "@babel/generator";
+import { readFileSync } from "fs";
+import { resolve } from "path";
+import { format, Options } from "prettier";
-export const generateContentsWithInterface = async (filePath: string, prettierConfig: Options) => {
+export const generateContentsWithInterface = async (
+ filePath: string,
+ prettierConfig: Options,
+) => {
const contents = readFileSync(resolve(filePath)).toString();
- const ast = parse(contents, { sourceType: 'module', plugins: ['typescript', 'jsx'] });
+ const ast = parse(contents, {
+ sourceType: "module",
+ plugins: ["typescript", "jsx"],
+ });
const currentNodes = ast.program.body;
const customCommands = currentNodes
.filter(
- node =>
+ (node) =>
t.isExportNamedDeclaration(node) &&
- (t.isFunctionDeclaration(node.declaration) || t.isVariableDeclaration(node.declaration))
+ (t.isFunctionDeclaration(node.declaration) ||
+ t.isVariableDeclaration(node.declaration)),
)
- .map(node => {
+ .map((node) => {
const exportNamedDeclaration = node as ExportNamedDeclaration;
const declaration = exportNamedDeclaration.declaration as
| FunctionDeclaration
@@ -48,7 +55,7 @@ export const generateContentsWithInterface = async (filePath: string, prettierCo
const functionParameters = isVariableDeclaration
? (declaration.declarations[0]?.init as FunctionExpression).params
: declaration.params;
- const parameters = functionParameters.map(parameter => {
+ const parameters = functionParameters.map((parameter) => {
if (t.isAssignmentPattern(parameter)) {
return generateOptionalParameterFromInitializer(parameter);
}
@@ -56,23 +63,31 @@ export const generateContentsWithInterface = async (filePath: string, prettierCo
});
return {
functionIdentifier,
- parameters
+ parameters,
};
});
const lastNode = currentNodes[currentNodes.length - 1];
const interfaceExists =
- lastNode?.leadingComments?.[0]?.value === '* Generated by cypress-codegen *';
- const newNodes = interfaceExists ? currentNodes.slice(0, currentNodes.length - 1) : currentNodes;
- const { code: existingCode } = generate(t.program(newNodes), { retainLines: true });
- const newInterface = generateInterface(customCommands as CustomCommand[], interfaceExists);
+ lastNode?.leadingComments?.[0]?.value ===
+ "* Generated by cypress-codegen *";
+ const newNodes = interfaceExists
+ ? currentNodes.slice(0, currentNodes.length - 1)
+ : currentNodes;
+ const { code: existingCode } = generate(t.program(newNodes), {
+ retainLines: true,
+ });
+ const newInterface = generateInterface(
+ customCommands as CustomCommand[],
+ interfaceExists,
+ );
const { code: newCode } = generate(t.program(newInterface));
- const separator = interfaceExists ? '\n' : '\n\n';
+ const separator = interfaceExists ? "\n" : "\n\n";
const resultingCode = customCommands.length
? `${existingCode}${separator}${newCode}\n`
: `${existingCode}\n`;
return await format(resultingCode, {
- parser: 'babel-ts',
- ...prettierConfig
+ parser: "babel-ts",
+ ...prettierConfig,
});
};
@@ -81,45 +96,56 @@ interface CustomCommand {
parameters: Identifier[];
}
-const generateOptionalParameterFromInitializer = ({ left }: AssignmentPattern): Identifier => ({
+const generateOptionalParameterFromInitializer = ({
+ left,
+}: AssignmentPattern): Identifier => ({
...(left as Identifier),
- type: 'Identifier',
- optional: true
+ type: "Identifier",
+ optional: true,
});
-const generateInterface = (customCommands: CustomCommand[], interfaceExists: boolean) => {
+const generateInterface = (
+ customCommands: CustomCommand[],
+ interfaceExists: boolean,
+) => {
const interfaceNode = t.tsModuleDeclaration(
- t.identifier('global'),
+ t.identifier("global"),
t.tsModuleBlock([
t.tsModuleDeclaration(
- t.identifier('Cypress'),
+ t.identifier("Cypress"),
t.tsModuleBlock([
t.tsInterfaceDeclaration(
- t.identifier('Chainable'),
+ t.identifier("Chainable"),
null,
null,
t.tsInterfaceBody(
customCommands.map(({ functionIdentifier, parameters }) => {
- if (parameters.some(parameter => t.isObjectPattern(parameter))) {
- throw new Error('Object destructuring in function parameters is not supported.');
+ if (
+ parameters.some((parameter) => t.isObjectPattern(parameter))
+ ) {
+ throw new Error(
+ "Object destructuring in function parameters is not supported.",
+ );
}
return t.tsMethodSignature(
functionIdentifier,
null,
parameters,
- t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Chainable')))
+ t.tsTypeAnnotation(
+ t.tsTypeReference(t.identifier("Chainable")),
+ ),
);
- })
- )
- )
- ])
- )
- ])
+ }),
+ ),
+ ),
+ ]),
+ ),
+ ]),
);
interfaceNode.declare = true;
interfaceNode.global = true;
if (!interfaceExists) {
- t.addComment(interfaceNode, 'leading', '* Generated by cypress-codegen *');
+ t.addComment(interfaceNode, "leading", "* Generated by cypress-codegen *");
}
return [interfaceNode];
diff --git a/packages/cypress-codegen/src/index.ts b/packages/cypress-codegen/src/index.ts
index 45db24c..4ea006b 100644
--- a/packages/cypress-codegen/src/index.ts
+++ b/packages/cypress-codegen/src/index.ts
@@ -11,4 +11,4 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-export { cypressCodegen } from './codegen';
+export { cypressCodegen } from "./codegen";
diff --git a/packages/cypress-codegen/test/generate-content-with-exports.test.ts b/packages/cypress-codegen/test/generate-content-with-exports.test.ts
index ccf47e9..81d35b7 100644
--- a/packages/cypress-codegen/test/generate-content-with-exports.test.ts
+++ b/packages/cypress-codegen/test/generate-content-with-exports.test.ts
@@ -11,20 +11,20 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { generateContentWithExports } from '../src/generate-content-with-exports';
+import { generateContentWithExports } from "../src/generate-content-with-exports";
const filePaths = [
- 'cypress/commands/file/path/1.tsx',
- 'cypress/commands/file/path/2.tsx',
- 'cypress/commands/filePath/3.ts'
+ "cypress/commands/file/path/1.tsx",
+ "cypress/commands/file/path/2.tsx",
+ "cypress/commands/filePath/3.ts",
];
const prettierConfig = {
singleQuote: true,
- printWidth: 90
+ printWidth: 90,
};
-describe('generateContentWithExports', () => {
- it('should generate exports file', async () => {
+describe("generateContentWithExports", () => {
+ it("should generate exports file", async () => {
const result = await generateContentWithExports(filePaths, prettierConfig);
expect(result).toEqual(`/** Generated by cypress-codegen **/
export * from './file/path/1';
diff --git a/packages/cypress-codegen/test/generate-content-with-imports.test.ts b/packages/cypress-codegen/test/generate-content-with-imports.test.ts
index 565a131..0428cce 100644
--- a/packages/cypress-codegen/test/generate-content-with-imports.test.ts
+++ b/packages/cypress-codegen/test/generate-content-with-imports.test.ts
@@ -11,19 +11,19 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { readFileSync } from 'fs';
-import { generateContentWithImports } from '../src/generate-content-with-imports';
+import { readFileSync } from "fs";
+import { generateContentWithImports } from "../src/generate-content-with-imports";
-jest.mock('fs');
+jest.mock("fs");
-const filePath = 'filePath';
+const filePath = "filePath";
const prettierConfig = {
singleQuote: true,
- printWidth: 90
+ printWidth: 90,
};
-describe('generateContentWithImports', () => {
- it('should generate types when types do not exist', async () => {
+describe("generateContentWithImports", () => {
+ it("should generate types when types do not exist", async () => {
(readFileSync as jest.Mock).mockReturnValue(`// some comment
import { mount } from 'cypress/react18';
@@ -66,7 +66,7 @@ import('../commands').then(Cypress.Commands.addAll);
`);
});
- it('should do nothing when types exist', async () => {
+ it("should do nothing when types exist", async () => {
(readFileSync as jest.Mock).mockReturnValue(`// some comment
import { mount } from 'cypress/react18';
diff --git a/packages/cypress-codegen/test/generate-contents-with-interface.ts b/packages/cypress-codegen/test/generate-contents-with-interface.ts
index 13a7df5..5917eb7 100644
--- a/packages/cypress-codegen/test/generate-contents-with-interface.ts
+++ b/packages/cypress-codegen/test/generate-contents-with-interface.ts
@@ -11,20 +11,20 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { generateContentsWithInterface } from '../src/generate-contents-with-interface';
+import { generateContentsWithInterface } from "../src/generate-contents-with-interface";
-import { readFileSync } from 'fs';
+import { readFileSync } from "fs";
-jest.mock('fs');
+jest.mock("fs");
-const filePath = 'filePath';
+const filePath = "filePath";
const prettierConfig = {
singleQuote: true,
- printWidth: 90
+ printWidth: 90,
};
-describe('generateContentsWithInterface', () => {
- it('should generate types when types do not exist', async () => {
+describe("generateContentsWithInterface", () => {
+ it("should generate types when types do not exist", async () => {
(readFileSync as jest.Mock).mockReturnValue(`// some comment
export function functionExampleOneInput(input1: string) {
@@ -47,7 +47,10 @@ export const arrowFunctionExample = (input1: string) => {
cy.log('Here is a custom command from an arrow function!').log(input);
};
`);
- const result = await generateContentsWithInterface(filePath, prettierConfig);
+ const result = await generateContentsWithInterface(
+ filePath,
+ prettierConfig,
+ );
expect(result).toEqual(`// some comment
export function functionExampleOneInput(input1: string) {
@@ -85,7 +88,7 @@ declare global {
`);
});
- it('should generate types when types exist', async () => {
+ it("should generate types when types exist", async () => {
(readFileSync as jest.Mock).mockReturnValue(`// some comment
export function functionExampleOneInput(input1: string) {
@@ -118,7 +121,10 @@ declare global {
}
}
`);
- const result = await generateContentsWithInterface(filePath, prettierConfig);
+ const result = await generateContentsWithInterface(
+ filePath,
+ prettierConfig,
+ );
expect(result).toEqual(`// some comment
export function functionExampleOneInput(input1: string) {
@@ -156,7 +162,7 @@ declare global {
`);
});
- it('should preserve formatting', async () => {
+ it("should preserve formatting", async () => {
(readFileSync as jest.Mock).mockReturnValue(`// some comment
export function functionExampleOneInput(input1: string) {
@@ -181,7 +187,10 @@ export const arrowFunctionExample = (input1: string) => {
cy.log('Here is a custom command from an arrow function!').log(input);
};
`);
- const result = await generateContentsWithInterface(filePath, prettierConfig);
+ const result = await generateContentsWithInterface(
+ filePath,
+ prettierConfig,
+ );
expect(result).toEqual(`// some comment
export function functionExampleOneInput(input1: string) {
@@ -221,14 +230,17 @@ declare global {
`);
});
- it('should handle generic types properly', async () => {
+ it("should handle generic types properly", async () => {
(readFileSync as jest.Mock).mockReturnValue(`// some comment
export function functionExampleGenericType(input1: string) {
cy.log('Here is a generic type!');
}
`);
- const result = await generateContentsWithInterface(filePath, prettierConfig);
+ const result = await generateContentsWithInterface(
+ filePath,
+ prettierConfig,
+ );
expect(result).toEqual(`// some comment
export function functionExampleGenericType(input1: string) {
@@ -246,21 +258,26 @@ declare global {
`);
});
- it('should throw error for object-destructured input', async () => {
+ it("should throw error for object-destructured input", async () => {
(readFileSync as jest.Mock).mockReturnValue(`
export const objectDestructureExample = ({ input1, input2 }: { input1: string; input2: string }) => {
cy.log(input1);
cy.log(input2);
};
`);
- await expect(generateContentsWithInterface(filePath, prettierConfig)).rejects.toThrowError();
+ await expect(
+ generateContentsWithInterface(filePath, prettierConfig),
+ ).rejects.toThrowError();
});
- it('should handle file with only exports', async () => {
+ it("should handle file with only exports", async () => {
(readFileSync as jest.Mock).mockReturnValue(`export * from './some-file';
export * from './some-other-file';
`);
- const result = await generateContentsWithInterface(filePath, prettierConfig);
+ const result = await generateContentsWithInterface(
+ filePath,
+ prettierConfig,
+ );
expect(result).toEqual(`export * from './some-file';
export * from './some-other-file';
`);
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f9b3887..0324f36 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -46,7 +46,7 @@ importers:
version: 27.2.3(@typescript-eslint/eslint-plugin@6.13.2)(eslint@8.26.0)(typescript@5.3.3)
eslint-plugin-prettier:
specifier: 5.0.1
- version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.26.0)(prettier@3.0.3)
+ version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.26.0)(prettier@3.1.1)
husky:
specifier: 8.0.3
version: 8.0.3
@@ -96,8 +96,8 @@ importers:
specifier: 10.3.10
version: 10.3.10
prettier:
- specifier: 3.0.3
- version: 3.0.3
+ specifier: 3.1.1
+ version: 3.1.1
devDependencies:
'@swc/jest':
specifier: 0.2.29
@@ -3371,10 +3371,10 @@ packages:
eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.4.0)(eslint@8.26.0)
eslint-plugin-jsx-a11y: 6.7.1(eslint@8.26.0)
eslint-plugin-no-only-tests: 3.1.0
- eslint-plugin-prettier: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.26.0)(prettier@3.0.3)
+ eslint-plugin-prettier: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.26.0)(prettier@3.1.1)
eslint-rule-documentation: 1.0.23
jsx-ast-utils: 3.3.5
- prettier: 3.0.3
+ prettier: 3.1.1
svg-element-attributes: 1.3.1
transitivePeerDependencies:
- '@types/eslint'
@@ -3513,7 +3513,7 @@ packages:
engines: {node: '>=5.0.0'}
dev: true
- /eslint-plugin-prettier@5.0.1(eslint-config-prettier@9.0.0)(eslint@8.26.0)(prettier@3.0.3):
+ /eslint-plugin-prettier@5.0.1(eslint-config-prettier@9.0.0)(eslint@8.26.0)(prettier@3.1.1):
resolution: {integrity: sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
@@ -3529,7 +3529,7 @@ packages:
dependencies:
eslint: 8.26.0
eslint-config-prettier: 9.0.0(eslint@8.26.0)
- prettier: 3.0.3
+ prettier: 3.1.1
prettier-linter-helpers: 1.0.0
synckit: 0.8.5
dev: true
@@ -6040,8 +6040,8 @@ packages:
fast-diff: 1.3.0
dev: true
- /prettier@3.0.3:
- resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==}
+ /prettier@3.1.1:
+ resolution: {integrity: sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==}
engines: {node: '>=14'}
hasBin: true