diff --git a/cli/.eslintignore b/cli/.eslintignore deleted file mode 100644 index cf4ed93c4c9..00000000000 --- a/cli/.eslintignore +++ /dev/null @@ -1,17 +0,0 @@ -**/__snapshots__ -/build - -# do not lint package.json, it incorrect re-orders the `exports` -# https://github.com/cypress-io/cypress/pull/26630 -package.json - -# cli/types is linted by tslint/dtslint -/types - -# these are all copied from dist'd builds from the individual libs -/angular -/react -/vue -/svelte -/mount-utils -tsconfig.esm.json \ No newline at end of file diff --git a/cli/.eslintrc.json b/cli/.eslintrc.json deleted file mode 100644 index c3cecddc84c..00000000000 --- a/cli/.eslintrc.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "rules": { - "no-restricted-syntax": [ - "error", - { - "selector": "CallExpression[callee.name='arch']", - "message": "Do not use `arch()` to detect the user's machine architecture. Use util.getRealArch() instead." - }, - { - "selector": "CallExpression[callee.object.name='os'][callee.property.name='arch']", - "message": "Do not use `os.arch()` to detect the user's machine architecture. Use util.getRealArch() instead." - }, - { - "selector": "MemberExpression[object.name='process'][property.name='arch']", - "message": "Do not use `process.arch` to detect the user's machine architecture. Use util.getRealArch() instead." - } - ] - } -} diff --git a/cli/eslint.config.ts b/cli/eslint.config.ts new file mode 100644 index 00000000000..3ebd9ebd4c3 --- /dev/null +++ b/cli/eslint.config.ts @@ -0,0 +1,48 @@ +import { baseConfig, cliOverrides } from '@packages/eslint-config' + +export default [ + ...baseConfig, + ...cliOverrides, + { + languageOptions: { + parserOptions: { + tsconfigRootDir: __dirname, + }, + }, + }, + { + rules: { + '@stylistic/comma-dangle': 'warn', + '@stylistic/comma-spacing': 'warn', + '@stylistic/type-generic-spacing': 'warn', + '@stylistic/quotes': 'warn', + '@stylistic/arrow-parens': 'warn', + '@stylistic/no-multi-spaces': 'warn', + 'padding-line-between-statements': 'warn', + '@stylistic/space-unary-ops': 'warn', + '@stylistic/member-delimiter-style': 'warn', + '@stylistic/object-curly-spacing': 'warn', + '@stylistic/semi': 'warn', + '@stylistic/space-in-parens': 'warn', + '@stylistic/space-infix-ops': 'warn', + '@stylistic/template-tag-spacing': 'warn', + 'no-var': 'warn', + '@stylistic/space-before-function-paren': ['warn', 'always'], + }, + }, + { + ignores: [ + '**/__snapshots__', + '**/build/**/*', + 'package.json', + '**/angular/**/*', + '**/react/**/*', + '**/vue/**/*', + '**/svelte/**/*', + '**/mount-utils/**/*', + '**/types/{bluebird,chai,chai-jquery,jquery,lodash,minimatch,mocha,sinon,sinon-chai}/**/*', + '.mocharc.js', + '**/*.js', + ], + }, +] diff --git a/cli/package.json b/cli/package.json index 704eda7dcb5..ff03ba14409 100644 --- a/cli/package.json +++ b/cli/package.json @@ -4,11 +4,11 @@ "private": true, "main": "dist/index.js", "scripts": { - "build-cli": "tsc && tsc -p tsconfig.esm.json && tsx ./scripts/build.ts && tsx ./scripts/post-build.ts", + "build-cli": "tsc -p tsconfig.build.json && tsc -p tsconfig.esm.json && tsx ./scripts/build.ts && tsx ./scripts/post-build.ts", "clean": "tsx ./scripts/clean.ts", "dtslint": "dtslint types", "postinstall": "patch-package && tsx ./scripts/post-install.ts", - "lint": "eslint --ext .ts,.tsx,.json,.vue .", + "lint": "eslint", "prebuild": "yarn postinstall && tsx ./scripts/start-build.ts", "size": "t=\"cypress-v0.0.0.tgz\"; yarn pack --filename \"${t}\"; wc -c \"${t}\"; tar tvf \"${t}\"; rm \"${t}\";", "test": "yarn test-unit", @@ -70,6 +70,7 @@ "@cypress/sinon-chai": "2.9.1", "@cypress/svelte": "0.0.0-development", "@cypress/vue": "0.0.0-development", + "@packages/eslint-config": "0.0.0-development", "@packages/root": "0.0.0-development", "@types/bluebird": "3.5.33", "@types/chai": "4.2.15", @@ -83,7 +84,9 @@ "cross-env": "7.0.3", "dependency-check": "4.1.0", "dtslint": "4.2.1", + "eslint": "^9.31.0", "execa-wrap": "1.4.0", + "jiti": "^2.4.2", "mock-fs": "5.4.0", "nock": "13.2.9", "resolve-pkg": "2.0.0", @@ -151,9 +154,13 @@ "workspaces": { "nohoist": [ "@types/*", + "eslint-plugin-expect-type", "tsx" ] }, + "lint-staged": { + "**/*.{js,jsx,ts,tsx,json,vue}": "eslint --fix" + }, "nx": { "targets": { "build-cli": { diff --git a/cli/scripts/build.ts b/cli/scripts/build.ts index 08cf2572984..fd570afb165 100644 --- a/cli/scripts/build.ts +++ b/cli/scripts/build.ts @@ -74,10 +74,9 @@ export default makeUserPackageFile if (require.main === module) { makeUserPackageFile(process.env.BRANCH) .catch((err: any) => { - /* eslint-disable no-console */ console.error('Could not write user package file') console.error(err) - /* eslint-enable no-console */ + process.exit(-1) }) } diff --git a/cli/scripts/post-install.ts b/cli/scripts/post-install.ts index 3bc6cfd2675..908cfc8aa3c 100644 --- a/cli/scripts/post-install.ts +++ b/cli/scripts/post-install.ts @@ -1,7 +1,7 @@ #!/usr/bin/env node // @ts-check -/* eslint-disable no-console */ + import fs from 'fs-extra' import { includeTypes } from './utils' import shell from 'shelljs' diff --git a/cli/scripts/start-build.ts b/cli/scripts/start-build.ts index 49deac262bd..75bb59a29ad 100644 --- a/cli/scripts/start-build.ts +++ b/cli/scripts/start-build.ts @@ -23,7 +23,7 @@ includeTypes.forEach((folder: string) => { }) // build the project and copy the build files over to the build directory -shell.exec('tsc -p tsconfig.json') +shell.exec('tsc -p tsconfig.build.json') shell.exec('tsc -p tsconfig.esm.json') shell.mkdir('-p', 'build/dist') diff --git a/cli/scripts/tsconfig.json b/cli/scripts/tsconfig.json new file mode 100644 index 00000000000..14d4d6ad9a4 --- /dev/null +++ b/cli/scripts/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "node", + ], + "exactOptionalPropertyTypes": true, + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true, + "esModuleInterop": true + }, + "include": [ + "**/*.ts" + ] +} diff --git a/cli/test/.eslintrc.json b/cli/test/.eslintrc.json deleted file mode 100644 index 722558a6746..00000000000 --- a/cli/test/.eslintrc.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "globals": { - "lib": true, - "sinon": true - }, - "extends": [ - "plugin:@cypress/dev/tests" - ] -} diff --git a/cli/test/tsconfig.json b/cli/test/tsconfig.json index 3e23339de99..39485e88c93 100644 --- a/cli/test/tsconfig.json +++ b/cli/test/tsconfig.json @@ -5,6 +5,9 @@ "noImplicitAny": false, "types": [ "mocha", "chai", "sinon" - ] - } + ], + }, + "include": [ + "**/*.ts" + ] } diff --git a/cli/tsconfig.build.json b/cli/tsconfig.build.json new file mode 100644 index 00000000000..f609bc4533e --- /dev/null +++ b/cli/tsconfig.build.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./lib", + "outDir": "./dist", + "target": "es2016", + "noEmit": false + }, + "exclude": [ + "test/**/*", + "*.ts" + ] +} \ No newline at end of file diff --git a/cli/tsconfig.esm.json b/cli/tsconfig.esm.json index f61f05ad2cc..cae3571ba59 100644 --- a/cli/tsconfig.esm.json +++ b/cli/tsconfig.esm.json @@ -1,18 +1,12 @@ { + "extends": "./tsconfig.build.json", "compilerOptions": { - "rootDir": "./lib", - "outDir": "./dist", "target": "ES2022", "module": "ES2022", "moduleResolution": "node", - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "strict": true, - "skipLibCheck": true, - "noImplicitAny": false + "types": ["node"] }, "include": [ "lib/**/*.mts" ] -} +} \ No newline at end of file diff --git a/cli/tsconfig.json b/cli/tsconfig.json index 375f3a4612e..f950bb6d9b9 100644 --- a/cli/tsconfig.json +++ b/cli/tsconfig.json @@ -1,17 +1,39 @@ { "compilerOptions": { - "rootDir": "./lib", + "rootDir": "./", "outDir": "./dist", - "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - "module": "commonjs", /* Specify what module code is generated. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + "target": "ES2022", + "module": "commonjs", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, - "strict": true, /* Enable all strict type-checking options. */ - "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "strict": true, + "skipLibCheck": true, "noImplicitAny": false, + "noEmit": true, + "types": [ + "mocha" + ] }, "include": [ "lib/**/*.ts", + "test/**/*.ts", + "*.ts" + ], + "exclude": [ + "types/bluebird", + "types/chai", + "types/chai-jquery", + "types/jquery", + "types/lodash", + "types/minimatch", + "types/mocha", + "types/sinon", + "types/sinon-chai", + "react", + "vue", + "angular", + "svelte", + "mount-utils", ] } diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index 68c09274f1e..15f4fa668f9 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -1691,7 +1691,7 @@ declare namespace Cypress { * cy.get('h1').should('equal', 'Example Domain') * }) */ - origin(urlOrDomain: string, fn: () => void): Chainable + origin(urlOrDomain: string, fn: () => void): Chainable /** * Enables running Cypress commands in a secondary origin. @@ -1702,7 +1702,7 @@ declare namespace Cypress { * expect(foo).to.equal('foo') * }) */ - origin(urlOrDomain: string, options: { + origin(urlOrDomain: string, options: { args: T }, fn: (args: T) => void): Chainable diff --git a/cli/types/tests/cypress-tests.ts b/cli/types/tests/cypress-tests.ts index 3e11d848a5f..3702f516dc9 100644 --- a/cli/types/tests/cypress-tests.ts +++ b/cli/types/tests/cypress-tests.ts @@ -1,6 +1,6 @@ namespace CypressLodashTests { Cypress._ // $ExpectType LoDashStatic - Cypress._.each([1], item => { + Cypress._.each([1], (item) => { item // $ExpectType number }) } @@ -36,7 +36,7 @@ namespace CypressConfigTests { Cypress.config('baseUrl', '.') // $ExpectType void Cypress.config({ e2e: { baseUrl: '.' } }) // $ExpectError Cypress.config({ e2e: { baseUrl: null } }) // $ExpectError - Cypress.config({ e2e: { baseUrl: '.', } }) // $ExpectError + Cypress.config({ e2e: { baseUrl: '.' } }) // $ExpectError Cypress.config({ component: { baseUrl: '.', devServer: () => ({} as any) } }) // $ExpectError Cypress.config({ e2e: { indexHtmlFile: 'index.html' } }) // $ExpectError Cypress.config({ testIsolation: false }) // $ExpectError @@ -51,20 +51,20 @@ namespace CypressEnvTests { Cypress.env('foo', 'bar') Cypress.env().foo Cypress.env({ - foo: 'bar' + foo: 'bar', }) } namespace CypressStopTests { - Cypress.stop() // $ExpectType void - Cypress.stop('foo') // $ExpectError + Cypress.stop() // $ExpectType void + Cypress.stop('foo') // $ExpectError } namespace CypressIsCyTests { Cypress.isCy(cy) // $ExpectType boolean Cypress.isCy(undefined) // $ExpectType boolean - const chainer = cy.wrap("foo").then(function() { + const chainer = cy.wrap('foo').then(function () { if (Cypress.isCy(chainer)) { chainer // $ExpectType Chainable } @@ -82,28 +82,32 @@ namespace CypressCommandsTests { Cypress.Commands.add('newCommand', (arg) => { // $ExpectType string arg + return }) Cypress.Commands.add('newCommand', (arg) => { // $ExpectType string arg }) - Cypress.Commands.add('newCommand', function(arg) { + Cypress.Commands.add('newCommand', function (arg) { this // $ExpectType Context arg // $ExpectType string }) Cypress.Commands.add('newCommand', { prevSubject: true }, (subject, arg) => { subject // $ExpectType any arg // $ExpectType string + return }) Cypress.Commands.add('newCommand', { prevSubject: false }, (arg: string) => { arg // $ExpectType string + return }) Cypress.Commands.add('newCommand', { prevSubject: 'optional' }, (subject, arg) => { subject // $ExpectType unknown arg // $ExpectType string + return }) Cypress.Commands.add('newCommand', { prevSubject: 'optional' }, (subject, arg) => { @@ -138,6 +142,7 @@ namespace CypressCommandsTests { } else { subject // $ExpectType JQueryWithSelector } + arg // $ExpectType string }) Cypress.Commands.add('newCommand', { prevSubject: ['window', 'document', 'optional', 'element'] }, (subject, arg) => { @@ -150,22 +155,25 @@ namespace CypressCommandsTests { } else { subject // $ExpectType void } + arg // $ExpectType string }) Cypress.Commands.add('newCommand', (arg) => { // $ExpectType string arg + return cy.wrap(new Promise((resolve) => { resolve(5) })) }) Cypress.Commands.addAll({ - newCommand(arg) { + newCommand (arg) { // $ExpectType any arg this // $ExpectType Context + return }, - newCommand2(arg, arg2) { + newCommand2 (arg, arg2) { // $ExpectType any arg // $ExpectType any @@ -174,6 +182,7 @@ namespace CypressCommandsTests { newCommand3: (arg) => { // $ExpectType any arg + return }, newCommand4: (arg) => { @@ -185,12 +194,14 @@ namespace CypressCommandsTests { newCommand: (subject, arg) => { subject // $ExpectType any arg // $ExpectType any + return }, }) Cypress.Commands.addAll({ prevSubject: false }, { newCommand: (arg) => { arg // $ExpectType any + return }, }) @@ -198,6 +209,7 @@ namespace CypressCommandsTests { newCommand: (subject, arg) => { subject // $ExpectType unknown arg // $ExpectType any + return }, newCommand2: (subject, arg) => { @@ -227,13 +239,13 @@ namespace CypressCommandsTests { newCommand: (subject, arg) => { subject // $ExpectType JQueryWithSelector arg // $ExpectType any - } + }, }) Cypress.Commands.addAll({ prevSubject: ['element'] }, { newCommand: (subject, arg) => { subject // $ExpectType JQueryWithSelector arg // $ExpectType any - } + }, }) Cypress.Commands.addAll({ prevSubject: ['element', 'document', 'window'] }, { newCommand: (subject, arg) => { @@ -244,8 +256,9 @@ namespace CypressCommandsTests { } else { subject // $ExpectType JQueryWithSelector } + arg // $ExpectType any - } + }, }) Cypress.Commands.addAll({ prevSubject: ['window', 'document', 'optional', 'element'] }, { newCommand: (subject, arg) => { @@ -258,15 +271,17 @@ namespace CypressCommandsTests { } else { subject // $ExpectType void } + arg // $ExpectType any - } + }, }) Cypress.Commands.addAll({ newCommand: (arg) => { // $ExpectType any arg + return cy.wrap(new Promise((resolve) => { resolve(5) })) - } + }, }) Cypress.Commands.overwrite('newCommand', (originalFn, arg) => { @@ -274,7 +289,7 @@ namespace CypressCommandsTests { originalFn // $ExpectedType Chainable['newCommand'] originalFn(arg) // $ExpectType Chainable }) - Cypress.Commands.overwrite('newCommand', function(originalFn, arg) { + Cypress.Commands.overwrite('newCommand', function (originalFn, arg) { this // $ExpectType Context arg // $ExpectType string originalFn // $ExpectedType Chainable['newCommand'] @@ -303,9 +318,10 @@ namespace CypressCommandsTests { options // $ExpectType Partial | undefined }) - Cypress.Commands.addQuery('newQuery', function(arg) { + Cypress.Commands.addQuery('newQuery', function (arg) { this // $ExpectType Command arg // $ExpectType string + return () => 3 }) } @@ -349,7 +365,7 @@ namespace CypressLogsTest { } namespace CypressLocalStorageTest { - Cypress.LocalStorage.clear = function(keys) { + Cypress.LocalStorage.clear = function (keys) { keys // $ExpectType string[] | undefined } } @@ -393,7 +409,7 @@ namespace CypressInvokeTests { // (see https://github.com/cypress-io/cypress/issues/4022) // call methods on arbitrary objects with reasonable return types - cy.wrap({ fn: () => ({ a: 1 }) }).invoke("fn") // $ExpectType Chainable<{ a: number; }> + cy.wrap({ fn: () => ({ a: 1 }) }).invoke('fn') // $ExpectType Chainable<{ a: number; }> // call methods on dom elements with reasonable return types cy.get('.trigger-input-range').invoke('val', 25) // $ExpectType Chainable @@ -411,7 +427,7 @@ cy.wrap({ foo: ['bar', 'baz'] }) .each((s: string) => { s // $ExpectType string }) - .then(s => { + .then((s) => { s // $ExpectType string[] }) @@ -434,45 +450,51 @@ describe('then', () => { // * then(fn: (this: ObjectLike, currentSubject: Subject) => S): Chainable // * then(fn: (this: ObjectLike, currentSubject: Subject) => S): ThenReturn // For our purpose, it doesn't matter. - const result = cy.get('foo').then(el => el.attr('foo')) + const result = cy.get('foo').then((el) => el.attr('foo')) + result // $ExpectType Chainable> | Chainable> - const result2 = cy.get('foo').then(el => `${el}`) + const result2 = cy.get('foo').then((el) => `${el}`) + result2 // $ExpectType Chainable - const result3 = cy.get('foo').then({ timeout: 1234 }, el => el.attr('foo')) + const result3 = cy.get('foo').then({ timeout: 1234 }, (el) => el.attr('foo')) + result3 // $ExpectType Chainable> | Chainable> - const result4 = cy.get('foo').then({ timeout: 1234 }, el => `${el}`) + const result4 = cy.get('foo').then({ timeout: 1234 }, (el) => `${el}`) + result4 // $ExpectType Chainable }) it('should have the correct type signature', () => { cy.wrap({ foo: 'bar' }) - .then(s => { + .then((s) => { s // $ExpectType { foo: string; } + return s }) - .then(s => { + .then((s) => { s // $ExpectType { foo: string; } }) - .then(s => s.foo) - .then(s => { + .then((s) => s.foo) + .then((s) => { s // $ExpectType string }) }) it('should have the correct type signature with options', () => { cy.wrap({ foo: 'bar' }) - .then({ timeout: 5000 }, s => { + .then({ timeout: 5000 }, (s) => { s // $ExpectType { foo: string; } + return s }) - .then({ timeout: 5000 }, s => { + .then({ timeout: 5000 }, (s) => { s // $ExpectType { foo: string; } }) - .then({ timeout: 5000 }, s => s.foo) - .then({ timeout: 5000 }, s => { + .then({ timeout: 5000 }, (s) => s.foo) + .then({ timeout: 5000 }, (s) => { s // $ExpectType string }) }) @@ -481,6 +503,7 @@ describe('then', () => { cy.get('div') .then(($div) => { $div // $ExpectType JQuery + return $div[0] }) .then(($div) => { @@ -490,6 +513,7 @@ describe('then', () => { cy.get('div') .then(($div) => { $div // $ExpectType JQuery + return [$div[0]] }) .then(($div) => { @@ -499,6 +523,7 @@ describe('then', () => { cy.get('p') .then(($p) => { $p // $ExpectType JQuery + return $p[0] }) .then({ timeout: 3000 }, ($p) => { @@ -510,7 +535,7 @@ describe('then', () => { it('any as default', () => { cy.get('body') .then(() => ({} as any)) - .then(v => { + .then((v) => { v // $ExpectType any }) }) @@ -526,19 +551,19 @@ cy.wait(1234) // $ExpectType Chainable cy.wrap('foo').wait(1234) // $ExpectType Chainable cy.wrap([{ foo: 'bar' }, { foo: 'baz' }]) - .then(subject => { + .then((subject) => { subject // $ExpectType { foo: string; }[] }) .then(([first, second]) => { first // $ExpectType { foo: string; } }) - .then(subject => { + .then((subject) => { subject // $ExpectType { foo: string; }[] }) .then(([first, second]) => { return first.foo + second.foo }) - .then(subject => { + .then((subject) => { subject // $ExpectType string }) @@ -558,30 +583,32 @@ cy.spy().withArgs('').log(false).as('foo') cy.get('something').as('foo', { type: 'static' }) -cy.wrap('foo').then(subject => { +cy.wrap('foo').then((subject) => { subject // $ExpectType string + return cy.wrap(subject) -}).then(subject => { +}).then((subject) => { subject // $ExpectType string }) -cy.wrap('foo').then(subject => { +cy.wrap('foo').then((subject) => { subject // $ExpectType string + return Cypress.Promise.resolve(subject) -}).then(subject => { +}).then((subject) => { subject // $ExpectType string }) -cy.get('body').within(body => { +cy.get('body').within((body) => { body // $ExpectType JQuery }) -cy.get('body').within({ log: false }, body => { +cy.get('body').within({ log: false }, (body) => { body // $ExpectType JQuery }) cy.get('body').within(() => { - cy.get('body', { withinSubject: null }).then(body => { + cy.get('body', { withinSubject: null }).then((body) => { body // $ExpectType JQuery }) }) @@ -591,7 +618,7 @@ cy .then(() => { return cy.wrap(undefined) }) - .then(subject => { + .then((subject) => { subject // $ExpectType undefined }) @@ -604,11 +631,11 @@ namespace CypressAUTWindowTests { win // $ExpectType AUTWindow }) - cy.visit('https://google.com').then(win => { + cy.visit('https://google.com').then((win) => { win // $ExpectType AUTWindow }) - cy.window().then(win => { + cy.window().then((win) => { win // $ExpectType AUTWindow }) } @@ -666,6 +693,7 @@ namespace CypressFilterTests { .filter((index: number, element: HTMLDivElement) => { index // $ExpectType number element // $ExpectType HTMLDivElement + return true }) } @@ -679,11 +707,11 @@ namespace CypressScreenshotTests { cy.screenshot({ log: false }) cy.screenshot({ log: true, - blackout: [] + blackout: [], }) cy.screenshot('example', { log: true, - blackout: [] + blackout: [], }) cy.get('#id').screenshot('example-name', { log: false }) cy.get('#id').screenshot().then((result) => { @@ -700,14 +728,14 @@ namespace CypressTriggerTests { .trigger('click') // .trigger(eventName) .trigger('click', 'center') // .trigger(eventName, position) .trigger('click', { // .trigger(eventName, options) - arbitraryProperty: 0 + arbitraryProperty: 0, }) .trigger('click', 0, 0) // .trigger(eventName, x, y) .trigger('click', 'center', { // .trigger(eventName, position, options) - arbitraryProperty: 0 + arbitraryProperty: 0, }) .trigger('click', 0, 0, { // .trigger(eventName, x, y, options) - arbitraryProperty: 0 + arbitraryProperty: 0, }) } @@ -715,25 +743,25 @@ namespace CypressClockTests { // timestamp cy.clock(new Date(2019, 3, 2).getTime(), ['Date']) // timestamp shortcut - cy.clock(+ new Date(), ['Date']) + cy.clock(+new Date(), ['Date']) // Date object cy.clock(new Date(2019, 3, 2)) // restoring the clock - cy.clock().then(clock => { + cy.clock().then((clock) => { clock.restore() }) // restoring the clock shortcut cy.clock().invoke('restore') // setting system time with no argument - cy.clock().then(clock => { + cy.clock().then((clock) => { clock.setSystemTime() }) // setting system time with timestamp - cy.clock().then(clock => { + cy.clock().then((clock) => { clock.setSystemTime(1000) }) // setting system time with date object - cy.clock().then(clock => { + cy.clock().then((clock) => { clock.setSystemTime(new Date(2019, 3, 2)) }) // setting system time with no argument and shortcut @@ -873,24 +901,24 @@ namespace CypressTestConfigOverridesTests { taskTimeout: 6000, viewportHeight: 200, viewportWidth: 200, - waitForAnimations: false + waitForAnimations: false, }, () => { }) it('test', { - browser: { name: 'firefox' } + browser: { name: 'firefox' }, }, () => { }) it('test', { - browser: [{ name: 'firefox' }, { name: 'chrome' }] + browser: [{ name: 'firefox' }, { name: 'chrome' }], }, () => { }) it('test', { browser: 'firefox', - keystrokeDelay: 0 + keystrokeDelay: 0, }, () => { }) it('test', { browser: { foo: 'bar' }, // $ExpectError }, () => { }) it('test', { retries: null, - keystrokeDelay: 0 + keystrokeDelay: 0, }, () => { }) it('test', { retries: 3, @@ -899,16 +927,16 @@ namespace CypressTestConfigOverridesTests { it('test', { retries: { runMode: 3, - openMode: null - } + openMode: null, + }, }, () => { }) it('test', { retries: { runMode: 3, - } + }, }, () => { }) it('test', { - retries: { run: 3 } // $ExpectError + retries: { run: 3 }, // $ExpectError }, () => { }) it('test', { testIsolation: false, // $ExpectError @@ -926,7 +954,7 @@ namespace CypressTestConfigOverridesTests { // set config on a per-suite basis describe('suite', { browser: { family: 'firefox' }, - keystrokeDelay: 0 + keystrokeDelay: 0, }, () => { }) describe('suite', { @@ -937,8 +965,7 @@ namespace CypressTestConfigOverridesTests { describe('suite', { browser: { family: 'firefox' }, - keystrokeDelay: false // $ExpectError - foo: 'foo' // $ExpectError + keystrokeDelay: false, // $ExpectError }, () => { }) describe.only('suite', {}, () => { }) @@ -946,6 +973,14 @@ namespace CypressTestConfigOverridesTests { xdescribe('suite', {}, () => { }) } +// for whatever reason, this is a false negative if placed in +// the CypressTestConfigOverridesTests namespace + +describe('suite', { + browser: { family: 'firefox' }, + foo: 'bar', // $ExpectError +}, () => { }) + namespace CypressShadowTests { cy .get('.foo') @@ -977,14 +1012,14 @@ namespace CypressSessionsTests { cy.session({ name: 'bob' }, () => { }) cy.session('user', () => { }, {}) cy.session('user', () => { }, { - validate: () => { } + validate: () => { }, }) cy.session() // $ExpectError cy.session('user') // $ExpectError cy.session(null) // $ExpectError cy.session('user', () => { }, { - validate: { foo: true } // $ExpectError + validate: { foo: true }, // $ExpectError }) } @@ -996,16 +1031,16 @@ namespace CypressCurrentTest { namespace CypressKeyboardTests { Cypress.Keyboard.defaults({ - keystrokeDelay: 0 + keystrokeDelay: 0, }) Cypress.Keyboard.defaults({ - keystrokeDelay: 500 + keystrokeDelay: 500, }) Cypress.Keyboard.defaults({ - keystrokeDelay: false // $ExpectError + keystrokeDelay: false, // $ExpectError }) Cypress.Keyboard.defaults({ - delay: 500 // $ExpectError + delay: 500, // $ExpectError }) } @@ -1169,34 +1204,34 @@ namespace CypressLocalStorageTests { namespace CypressRetriesSpec { Cypress.config('retries', { openMode: 0, - runMode: 1 + runMode: 1, }) Cypress.config('retries', { openMode: false, runMode: false, - experimentalStrategy: "detect-flake-and-pass-on-threshold", + experimentalStrategy: 'detect-flake-and-pass-on-threshold', experimentalOptions: { maxRetries: 2, - passesRequired: 2 - } + passesRequired: 2, + }, }) Cypress.config('retries', { openMode: false, runMode: false, - experimentalStrategy: "detect-flake-but-always-fail", + experimentalStrategy: 'detect-flake-but-always-fail', experimentalOptions: { maxRetries: 2, - stopIfAnyPassed: true - } + stopIfAnyPassed: true, + }, }) - Cypress.config('retries', { openMode: false, runMode: true, experimentalStrategy: "detect-flake-and-pass-on-threshold", experimentalOptions: { maxRetries: 2 } }) // $ExpectError - Cypress.config('retries', { openMode: false, runMode: true, experimentalStrategy: "detect-flake-but-always-fail", experimentalOptions: { maxRetries: 2 } }) // $ExpectError + Cypress.config('retries', { openMode: false, runMode: true, experimentalStrategy: 'detect-flake-and-pass-on-threshold', experimentalOptions: { maxRetries: 2 } }) // $ExpectError + Cypress.config('retries', { openMode: false, runMode: true, experimentalStrategy: 'detect-flake-but-always-fail', experimentalOptions: { maxRetries: 2 } }) // $ExpectError - Cypress.config('retries', { openMode: false, runMode: true, experimentalStrategy: "detect-flake-and-pass-on-threshold", experimentalOptions: { passesRequired: 2 } }) // $ExpectError - Cypress.config('retries', { openMode: false, runMode: true, experimentalStrategy: "detect-flake-but-always-fail", experimentalOptions: { stopIfAnyPassed: true } }) // $ExpectError + Cypress.config('retries', { openMode: false, runMode: true, experimentalStrategy: 'detect-flake-and-pass-on-threshold', experimentalOptions: { passesRequired: 2 } }) // $ExpectError + Cypress.config('retries', { openMode: false, runMode: true, experimentalStrategy: 'detect-flake-but-always-fail', experimentalOptions: { stopIfAnyPassed: true } }) // $ExpectError } namespace CypressTraversalTests { diff --git a/cli/types/tslint.json b/cli/types/tslint.json index 5e53c4842cf..3e8be2d6ff7 100644 --- a/cli/types/tslint.json +++ b/cli/types/tslint.json @@ -26,7 +26,8 @@ // in its own file for simplicity "no-single-declare-module": false, // This is detecting necessary qualifiers as unnecessary - "no-unnecessary-qualifier": false + "no-unnecessary-qualifier": false, + "space-before-function-paren": ["warn", "always"] }, "linterOptions": { "exclude": [ @@ -46,4 +47,4 @@ "./net-stubbing.d.ts" ] } -} +} \ No newline at end of file diff --git a/guides/eslint-migration.md b/guides/eslint-migration.md index 019fab3ecd3..2ac405b048f 100644 --- a/guides/eslint-migration.md +++ b/guides/eslint-migration.md @@ -45,6 +45,7 @@ - [ ] packages/app ### Batch 4c: Core packages (part 3) +- [x] cli - [ ] packages/config - [ ] packages/root - [ ] packages/resolve-dist diff --git a/packages/eslint-config/src/index.ts b/packages/eslint-config/src/index.ts index fecd7a2370f..9bfc98f697e 100644 --- a/packages/eslint-config/src/index.ts +++ b/packages/eslint-config/src/index.ts @@ -1,3 +1,15 @@ export * from './baseConfig' export * from './cliOverrides' + +import * as globalImport from 'globals' + +export const globals = { + ...globalImport, + specHelper: { + sinon: 'readonly', + expect: 'readonly', + lib: 'readonly', + global: false, + }, +} diff --git a/yarn.lock b/yarn.lock index 1f6f0ac2040..db037f4011f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8742,11 +8742,16 @@ "@typescript-eslint/types" "8.37.0" "@typescript-eslint/visitor-keys" "8.37.0" -"@typescript-eslint/tsconfig-utils@8.37.0", "@typescript-eslint/tsconfig-utils@^8.37.0": +"@typescript-eslint/tsconfig-utils@8.37.0": version "8.37.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.37.0.tgz#47a2760d265c6125f8e7864bc5c8537cad2bd053" integrity sha512-1/YHvAVTimMM9mmlPvTec9NP4bobA1RkDbMydxG8omqwJJLEW/Iy2C4adsAESIXU3WGLXFHSZUU+C9EoFWl4Zg== +"@typescript-eslint/tsconfig-utils@^8.37.0": + version "8.41.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.41.0.tgz#134dee36eb16cdd78095a20bca0516d10b5dda75" + integrity sha512-TDhxYFPUYRFxFhuU5hTIJk+auzM/wKvWgoNYOPcOf6i4ReYlOoYN8q1dV5kOTjNQNJgzWN3TUUQMtlLOcUgdUw== + "@typescript-eslint/type-utils@7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.2.0.tgz#7be5c30e9b4d49971b79095a1181324ef6089a19" @@ -8773,11 +8778,16 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.2.0.tgz#0feb685f16de320e8520f13cca30779c8b7c403f" integrity sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA== -"@typescript-eslint/types@8.37.0", "@typescript-eslint/types@^8.35.0", "@typescript-eslint/types@^8.37.0": +"@typescript-eslint/types@8.37.0": version "8.37.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.37.0.tgz#09517aa9625eb3c68941dde3ac8835740587b6ff" integrity sha512-ax0nv7PUF9NOVPs+lmQ7yIE7IQmAf8LGcXbMvHX5Gm+YJUYNAl340XkGnrimxZ0elXyoQJuN5sbg6C4evKA4SQ== +"@typescript-eslint/types@^8.35.0", "@typescript-eslint/types@^8.37.0": + version "8.41.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.41.0.tgz#9935afeaae65e535abcbcee95383fa649c64d16d" + integrity sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag== + "@typescript-eslint/typescript-estree@7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz#5beda2876c4137f8440c5a84b4f0370828682556"