diff --git a/circle.yml b/circle.yml index 2cda70281362..6c4545dff840 100644 --- a/circle.yml +++ b/circle.yml @@ -318,11 +318,10 @@ jobs: - run: command: ls -la types working_directory: cli - - run: - command: ls -la chai - working_directory: cli/types - run: command: yarn lerna exec --scope cypress "yarn dtslint" + - run: + command: yarn type-check --ignore-progress - store-npm-logs "server-unit-tests": diff --git a/cli/package.json b/cli/package.json index a0ea40aa905c..b9275049473b 100644 --- a/cli/package.json +++ b/cli/package.json @@ -22,6 +22,16 @@ "dependencies": { "@cypress/listr-verbose-renderer": "0.4.1", "@cypress/xvfb": "1.2.4", + "@types/blob-util": "1.3.3", + "@types/bluebird": "3.5.29", + "@types/chai": "4.2.7", + "@types/chai-jquery": "1.1.40", + "@types/jquery": "3.3.31", + "@types/lodash": "4.14.149", + "@types/minimatch": "3.0.3", + "@types/mocha": "5.2.7", + "@types/sinon": "7.5.1", + "@types/sinon-chai": "3.2.3", "@types/sizzle": "2.3.2", "arch": "2.1.1", "bluebird": "3.7.2", @@ -60,16 +70,6 @@ "devDependencies": { "@cypress/sinon-chai": "1.1.0", "@packages/root": "*", - "@types/blob-util": "1.3.3", - "@types/bluebird": "3.5.29", - "@types/chai": "4.2.7", - "@types/chai-jquery": "1.1.40", - "@types/jquery": "3.3.31", - "@types/lodash": "4.14.149", - "@types/minimatch": "3.0.3", - "@types/mocha": "5.2.7", - "@types/sinon": "7.5.1", - "@types/sinon-chai": "3.2.3", "babel-cli": "6.26.0", "babel-preset-es2015": "6.24.1", "chai": "3.5.0", diff --git a/cli/scripts/post-install.js b/cli/scripts/post-install.js index 3115d45c332f..a4f46e8a5bdb 100644 --- a/cli/scripts/post-install.js +++ b/cli/scripts/post-install.js @@ -1,64 +1,28 @@ -#!/usr/bin/env node - -const { includeTypes } = require('./utils') -const shell = require('shelljs') -const { join } = require('path') -const resolvePkg = require('resolve-pkg') - -shell.set('-v') // verbose -shell.set('-e') // any error is fatal - -// We include the TypeScript definitions for the bundled 3rd party tools -// thus we need to copy them from "dev" dependencies into our types folder -// and we need to sometimes tweak these types files to use relative paths -// This ensures that globals like Cypress.$, Cypress._ etc are property typed -// yet we do not install "@types/.." packages with "npm install cypress" -// because they can conflict with user's own libraries - -includeTypes.forEach((folder) => { - const source = resolvePkg(`@types/${folder}`, { cwd: join(__dirname, '..', '..') }) - - shell.cp('-R', source, 'types') +const fs = require('../lib/fs') +const path = require('path') + +/** + * https://github.com/cypress-io/cypress/pull/5780 + * Folder names in "node_modules/@types" that were copied to cli/types to generate index.d.ts. + * They cause type errors in type checker. So, they should be removed. + */ +const includeTypes = [ + 'blob-util', + 'bluebird', + 'lodash', + 'mocha', + 'minimatch', + 'sinon', + 'sinon-chai', + 'chai', + 'chai-jquery', + 'jquery', +] + +includeTypes.forEach((t) => { + const dir = path.join(__dirname, '../types', t) + + if (fs.existsSync(dir)) { + fs.removeSync(dir) + } }) - -// jQuery v3.3.x includes "dist" folder that just references back to itself -// causing dtslint to think there are double definitions. Remove that folder. -const typesJqueryDistFolder = join('types', 'jquery', 'dist') - -shell.rm('-rf', typesJqueryDistFolder) - -// fix paths to Chai, jQuery and other types to be relative -shell.sed( - '-i', - '', - '', - join('types', 'chai-jquery', 'index.d.ts'), -) - -shell.sed( - '-i', - '', - '', - join('types', 'chai-jquery', 'index.d.ts'), -) - -const sinonChaiFilename = join('types', 'sinon-chai', 'index.d.ts') - -shell.sed( - '-i', - '', - '', - sinonChaiFilename, -) - -// also use relative import via path for sinon-chai -// there is reference comment line we need to fix to be relative -shell.sed( - '-i', - '', - '', - sinonChaiFilename, -) - -// and an import sinon line to be changed to relative path -shell.sed('-i', 'from \'sinon\';', 'from \'../sinon\';', sinonChaiFilename) diff --git a/cli/scripts/start-build.js b/cli/scripts/start-build.js index b9263973e5f0..7040e4a9d5bc 100755 --- a/cli/scripts/start-build.js +++ b/cli/scripts/start-build.js @@ -1,7 +1,5 @@ #!/usr/bin/env node -const { includeTypes } = require('./utils') -const { join } = require('path') const shell = require('shelljs') shell.set('-v') // verbose @@ -15,12 +13,6 @@ shell.cp('NPM_README.md', 'build/README.md') shell.cp('.release.json', 'build/.release.json') // copies our typescript definitions shell.cp('-R', 'types/*.ts', 'build/types/') -// copies 3rd party typescript definitions -includeTypes.forEach((folder) => { - const source = join('types', folder) - - shell.cp('-R', source, 'build/types') -}) shell.exec('babel lib -d build/lib') shell.exec('babel index.js -o build/index.js') diff --git a/cli/scripts/utils.js b/cli/scripts/utils.js deleted file mode 100644 index 8c215081d438..000000000000 --- a/cli/scripts/utils.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Folder names in "node_modules/@types" that we should include - * when we bundle Cypress NPM package. These folder have ".d.ts" - * definition files that we will need to include with our NPM package. - */ -const includeTypes = [ - 'blob-util', - 'bluebird', - 'lodash', - 'mocha', - 'minimatch', - 'sinon', - 'sinon-chai', - 'chai', - 'chai-jquery', - 'jquery', -] - -module.exports = { includeTypes } diff --git a/cli/types/cy-blob-util.d.ts b/cli/types/cy-blob-util.d.ts deleted file mode 100644 index a70481fa30fc..000000000000 --- a/cli/types/cy-blob-util.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Shim definition to export a namespace. Cypress is actually a global module -// so import/export isn't allowed there. We import here and define a global module -// so that Cypress can get and use the Blob type - -// tslint:disable-next-line:no-implicit-dependencies -import * as blobUtil from './blob-util' - -export = BlobUtil -export as namespace BlobUtil - -declare namespace BlobUtil { - type BlobUtilStatic = typeof blobUtil -} diff --git a/cli/types/cy-bluebird.d.ts b/cli/types/cy-bluebird.d.ts deleted file mode 100644 index c729bd79c026..000000000000 --- a/cli/types/cy-bluebird.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Shim definition to export a namespace. Cypress is actually a global module -// so import/export isn't allowed there. We import here and define a global module -// so that Cypress can get and use the Blob type -import BluebirdStatic = require('./bluebird') - -export = Bluebird -export as namespace Bluebird - -declare namespace Bluebird { - type BluebirdStatic = typeof BluebirdStatic -} diff --git a/cli/types/cy-chai.d.ts b/cli/types/cy-chai.d.ts deleted file mode 100644 index 8cd40e8e3668..000000000000 --- a/cli/types/cy-chai.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Shim definition to export a namespace. Cypress is actually a global module -// so import/export isn't allowed there. We import here and define a global module -/// -declare namespace Chai { - interface Include { - html(html: string): Assertion - text(text: string): Assertion - value(text: string): Assertion - } -} diff --git a/cli/types/cy-minimatch.d.ts b/cli/types/cy-minimatch.d.ts deleted file mode 100644 index f94e54e3d92b..000000000000 --- a/cli/types/cy-minimatch.d.ts +++ /dev/null @@ -1,96 +0,0 @@ -// I was trying to avoid relying on "import" of actual module from "minimatch" -// because it would not work in test project, and the only reliable way -// to get around type errors finally was to copy the minimal minimatch function -// definition from "minimatch/index.d.ts" here and just keep it in our code - -export = Minimatch -export as namespace Minimatch - -interface MinimatchOptions { - /** - * Dump a ton of stuff to stderr. - * - * @default false - */ - debug?: boolean - - /** - * Do not expand {a,b} and {1..3} brace sets. - * - * @default false - */ - nobrace?: boolean - - /** - * Disable ** matching against multiple folder names. - * - * @default false - */ - noglobstar?: boolean - - /** - * Allow patterns to match filenames starting with a period, - * even if the pattern does not explicitly have a period in that spot. - * - * @default false - */ - dot?: boolean - - /** - * Disable "extglob" style patterns like +(a|b). - * - * @default false - */ - noext?: boolean - - /** - * Perform a case-insensitive match. - * - * @default false - */ - nocase?: boolean - - /** - * When a match is not found by minimatch.match, - * return a list containing the pattern itself if this option is set. - * Otherwise, an empty list is returned if there are no matches. - * - * @default false - */ - nonull?: boolean - - /** - * If set, then patterns without slashes will be matched against - * the basename of the path if it contains slashes. - * - * @default false - */ - matchBase?: boolean - - /** - * Suppress the behavior of treating # - * at the start of a pattern as a comment. - * - * @default false - */ - nocomment?: boolean - - /** - * Suppress the behavior of treating a leading ! character as negation. - * - * @default false - */ - nonegate?: boolean - - /** - * Returns from negate expressions the same as if they were not negated. - * (Ie, true on a hit, false on a miss.) - * - * @default false - */ - flipNegate?: boolean -} - -declare namespace Minimatch { - function minimatch(target: string, pattern: string, options?: MinimatchOptions): boolean -} diff --git a/cli/types/cy-moment.d.ts b/cli/types/cy-moment.d.ts deleted file mode 100644 index d68f10b9b574..000000000000 --- a/cli/types/cy-moment.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import moment = require('moment') -export = Moment -export as namespace Moment - -declare namespace Moment { - type MomentStatic = typeof moment -} diff --git a/cli/types/index.d.ts b/cli/types/index.d.ts index be7e25dda7de..abe6855a4dca 100644 --- a/cli/types/index.d.ts +++ b/cli/types/index.d.ts @@ -4,47 +4,52 @@ // Mike Woudenberg // Robbert van Markus // Nicholas Boll -// TypeScript Version: 2.9 +// TypeScript Version: 3.0 // Updated by the Cypress team: https://www.cypress.io/about/ -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// +/// +/// +/// +/// +/// +/// +/// +/// +/// // jQuery includes dependency "sizzle" that provides types // so we include it too in "node_modules/sizzle". // This way jQuery can load it using 'reference types="sizzle"' directive -// "moment" types are with "node_modules/moment" -/// - // load ambient declaration for "cypress" NPM module // hmm, how to load it better? /// // Cypress, cy, Log inherits EventEmitter. type EventEmitter2 = import("eventemitter2").EventEmitter2 +type Bluebird = import("bluebird") type Nullable = T | null interface EventEmitter extends EventEmitter2 { proxyTo: (cy: Cypress.cy) => null emitMap: (eventName: string, args: any[]) => Array<(...args: any[]) => any> - emitThen: (eventName: string, args: any[]) => Bluebird.BluebirdStatic + emitThen: (eventName: string, args: any[]) => Bluebird } // Cypress adds chai expect and assert to global declare const expect: Chai.ExpectStatic declare const assert: Chai.AssertStatic +// Cypress extension of chai +declare namespace Chai { + interface Include { + html(html: string): Assertion + text(text: string): Assertion + value(text: string): Assertion + } +} + declare namespace Cypress { type FileContents = string | any[] | object type HistoryDirection = "back" | "forward" @@ -182,13 +187,13 @@ declare namespace Cypress { * @example * Cypress.Blob.method() */ - Blob: BlobUtil.BlobUtilStatic + Blob: typeof import('blob-util') /** * Cypress automatically includes minimatch and exposes it as Cypress.minimatch. * * @see https://on.cypress.io/minimatch */ - minimatch: typeof Minimatch.minimatch + minimatch: typeof import('minimatch') /** * Cypress automatically includes moment.js and exposes it as Cypress.moment. * @@ -197,7 +202,7 @@ declare namespace Cypress { * @example * const todaysDate = Cypress.moment().format("MMM DD, YYYY") */ - moment: Moment.MomentStatic + moment: typeof import('moment') /** * Cypress automatically includes Bluebird and exposes it as Cypress.Promise. * @@ -206,7 +211,7 @@ declare namespace Cypress { * @example * new Cypress.Promise((resolve, reject) => { ... }) */ - Promise: Bluebird.BluebirdStatic + Promise: typeof import('bluebird') /** * Cypress includes Sinon.js library used in `cy.spy` and `cy.stub`. * diff --git a/package.json b/package.json index 02faf80080d4..04f50eea10b5 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "test-unit": "lerna exec yarn test-unit --ignore \"'@packages/{coffee,desktop-gui,driver,root,static,web-config}'\"", "pretest-watch": "yarn ensure-deps", "test-watch": "lerna exec yarn test-watch --ignore \"'@packages/{coffee,desktop-gui,driver,root,static,web-config}'\"", + "type-check": "node scripts/type_check", "verify:mocha:results": "node ./scripts/verify_mocha_results", "prewatch": "yarn ensure-deps", "watch": "lerna exec yarn watch --parallel --stream" @@ -88,6 +89,8 @@ "@types/chai-enzyme": "0.6.7", "@types/classnames": "2.2.9", "@types/debug": "4.1.5", + "@types/enzyme": "3.9.1", + "@types/enzyme-adapter-react-16": "1.0.5", "@types/execa": "0.9.0", "@types/fs-extra": "8.0.1", "@types/glob": "7.1.1", @@ -96,7 +99,8 @@ "@types/mini-css-extract-plugin": "0.8.0", "@types/mocha": "5.2.7", "@types/node": "12.12.21", - "@types/ramda": "0.26.38", + "@types/ramda": "0.25.47", + "@types/react": "16.9.23", "@types/react-dom": "16.9.4", "@types/request-promise": "4.1.45", "@types/sinon-chai": "3.2.3", @@ -121,6 +125,7 @@ "decaffeinate": "6.0.9", "del": "3.0.0", "electron-builder": "20.39.0", + "enzyme-adapter-react-16": "1.12.1", "eslint": "6.8.0", "eslint-plugin-cypress": "2.10.3", "eslint-plugin-json-format": "2.0.0", @@ -150,6 +155,7 @@ "lazy-ass": "1.6.0", "lerna": "3.18.3", "lint-staged": "9.4.1", + "listr": "0.14.3", "lodash": "4.17.15", "make-empty-github-commit": "1.2.0", "mocha": "3.5.3", diff --git a/packages/driver/src/cy/keyboard.ts b/packages/driver/src/cy/keyboard.ts index 820bff45b99c..6f951fb07de6 100644 --- a/packages/driver/src/cy/keyboard.ts +++ b/packages/driver/src/cy/keyboard.ts @@ -7,6 +7,8 @@ import { USKeyboard } from '../cypress/UsKeyboardLayout' import * as $dom from '../dom' import * as $document from '../dom/document' import * as $elements from '../dom/elements' +// eslint-disable-next-line no-duplicate-imports +import { HTMLTextLikeElement, HTMLTextLikeInputElement } from '../dom/elements' import * as $selection from '../dom/selection' import $window from '../dom/window' @@ -583,6 +585,7 @@ const keyToModifierMap = { } export interface typeOptions { + id: string $el: JQuery chars: string force?: boolean @@ -601,7 +604,6 @@ export interface typeOptions { onNoMatchingSpecialChars?: Function onBeforeSpecialCharAction?: Function prevValue?: string - id?: string } export class Keyboard { @@ -735,7 +737,7 @@ export class Keyboard { // simulatedDefaultOnly keys will not send any events, and cannot be canceled if (key.simulatedDefaultOnly) { - key.simulatedDefault!(activeEl, key, options) + key.simulatedDefault!(activeEl as HTMLTextLikeElement, key, options) return null } @@ -1124,7 +1126,7 @@ export class Keyboard { return } - return simulatedDefault(el, key, options) + return simulatedDefault(el as HTMLTextLikeElement, key, options) } } diff --git a/packages/driver/src/dom/elements.ts b/packages/driver/src/dom/elements.ts index 8a95218af30b..b53fbbfa3d6f 100644 --- a/packages/driver/src/dom/elements.ts +++ b/packages/driver/src/dom/elements.ts @@ -644,7 +644,7 @@ const isAttached = function ($el) { // is technically bound to a different document // but c'mon const isIn = (el) => { - return $.contains(doc, el) + return $.contains(doc as any, el) } // make sure the document is currently diff --git a/packages/reporter/package.json b/packages/reporter/package.json index cb45a9fa38c3..3114e7ff358f 100644 --- a/packages/reporter/package.json +++ b/packages/reporter/package.json @@ -21,7 +21,6 @@ "@packages/socket": "*", "@packages/web-config": "*", "@types/chai-enzyme": "0.6.7", - "@types/enzyme": "3.10.4", "chai": "3.5.0", "chai-enzyme": "1.0.0-beta.1", "classnames": "2.2.6", diff --git a/packages/reporter/src/commands/command.tsx b/packages/reporter/src/commands/command.tsx index f638446b589e..f11084c16d1a 100644 --- a/packages/reporter/src/commands/command.tsx +++ b/packages/reporter/src/commands/command.tsx @@ -98,12 +98,16 @@ const Aliases = observer(({ model, aliasesWithDuplicates }: AliasesProps) => { ) }) -const Message = observer(({ model }) => ( +interface MessageProps { + model: CommandModel +} + +const Message = observer(({ model }: MessageProps) => ( )) diff --git a/packages/reporter/src/global.d.ts b/packages/reporter/src/global.d.ts new file mode 100644 index 000000000000..442d8a8132b7 --- /dev/null +++ b/packages/reporter/src/global.d.ts @@ -0,0 +1 @@ +declare const expect: Chai.ExpectStatic diff --git a/packages/reporter/src/header/header.spec.tsx b/packages/reporter/src/header/header.spec.tsx index ce0b2575c0ae..3c415f7b1482 100644 --- a/packages/reporter/src/header/header.spec.tsx +++ b/packages/reporter/src/header/header.spec.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { ReactElement } from 'react' import { shallow } from 'enzyme' import sinon, { SinonSpy } from 'sinon' @@ -24,7 +24,7 @@ describe('
', () => { it('renders a tooltip around focus tests button', () => { const title = shallow(
) .find('Tooltip') - .prop('title') + .prop('title') const component = shallow(title) diff --git a/packages/reporter/src/hooks/hook-model.spec.ts b/packages/reporter/src/hooks/hook-model.spec.ts index fda9b2154bb8..7d9ebb070427 100644 --- a/packages/reporter/src/hooks/hook-model.spec.ts +++ b/packages/reporter/src/hooks/hook-model.spec.ts @@ -1,4 +1,5 @@ import sinon from 'sinon' + import Hook from './hook-model' import CommandModel from '../commands/command-model' diff --git a/packages/reporter/src/lib/scroller.ts b/packages/reporter/src/lib/scroller.ts index cdca715fd7d1..0440faae704b 100644 --- a/packages/reporter/src/lib/scroller.ts +++ b/packages/reporter/src/lib/scroller.ts @@ -129,7 +129,7 @@ export class Scroller { this._container = null this._userScroll = true this._userScrollCount = 0 - clearTimeout(this._countUserScrollsTimeout) + clearTimeout(this._countUserScrollsTimeout as TimeoutID) this._countUserScrollsTimeout = undefined } } diff --git a/packages/reporter/src/runnables/runnables-store.ts b/packages/reporter/src/runnables/runnables-store.ts index 01cff455568a..8b88e2f4eed8 100644 --- a/packages/reporter/src/runnables/runnables-store.ts +++ b/packages/reporter/src/runnables/runnables-store.ts @@ -26,6 +26,8 @@ interface Props { export type LogProps = AgentProps | CommandProps | RouteProps +export type RunnableArray = Array + type Log = AgentModel | CommandModel | RouteModel export interface RootRunnable { @@ -38,7 +40,7 @@ type TestOrSuite = T extends TestProps ? TestProps : SuiteProps class RunnablesStore { @observable isReady = defaults.isReady - @observable runnables: Array = [] + @observable runnables: RunnableArray = [] hasTests: boolean = false hasSingleTest: boolean = false diff --git a/packages/reporter/src/runnables/runnables.spec.tsx b/packages/reporter/src/runnables/runnables.spec.tsx index c9b7c4eb0984..c117c1a72c78 100644 --- a/packages/reporter/src/runnables/runnables.spec.tsx +++ b/packages/reporter/src/runnables/runnables.spec.tsx @@ -128,7 +128,7 @@ describe('', () => { context('', () => { it('renders a runnable for each runnable in model', () => { - const component = shallow() + const component = shallow() expect(component.find('Runnable').length).to.equal(2) }) diff --git a/packages/reporter/src/runnables/runnables.tsx b/packages/reporter/src/runnables/runnables.tsx index bc508eb7fb92..c21f0bf167b0 100644 --- a/packages/reporter/src/runnables/runnables.tsx +++ b/packages/reporter/src/runnables/runnables.tsx @@ -5,7 +5,7 @@ import React, { Component } from 'react' import AnError, { Error } from '../errors/an-error' import Runnable from './runnable-and-suite' -import { RunnablesStore } from './runnables-store' +import { RunnablesStore, RunnableArray } from './runnables-store' import { Scroller } from '../lib/scroller' import { AppState } from '../lib/app-state' @@ -16,7 +16,11 @@ const noTestsError = (specPath: string) => ({ message: 'We could not detect any tests in the above file. Write some tests and re-run.', }) -const RunnablesList = observer(({ runnables }) => ( +interface RunnablesListProps { + runnables: RunnableArray +} + +const RunnablesList = observer(({ runnables }: RunnablesListProps) => (
    {_.map(runnables, (runnable) => )} diff --git a/packages/reporter/tsconfig.json b/packages/reporter/tsconfig.json index 7b265c136b17..91ca16afbdd2 100644 --- a/packages/reporter/tsconfig.json +++ b/packages/reporter/tsconfig.json @@ -9,6 +9,7 @@ */ "allowJs": true, "jsx": "react", + "outDir": "dist", "noImplicitAny": true, "noImplicitThis": true, "preserveWatchOutput": true, @@ -45,12 +46,6 @@ // "baseUrl": "../", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": ["../driver/src"], /* List of root folders whose combined content represents the structure of the project at runtime. */ - "typeRoots": [ - "../driver/node_modules", - "../../cli/types/index.d.ts", - "../driver/src", - "./node_modules" - ], /* List of folders to include type definitions from. */ // "types": [], /* Type declaration files to be included in compilation. */ "allowSyntheticDefaultImports": true, "esModuleInterop": true, diff --git a/packages/runner/package.json b/packages/runner/package.json index ce43cf1ed8c9..a61d0e5e373a 100644 --- a/packages/runner/package.json +++ b/packages/runner/package.json @@ -21,8 +21,6 @@ "@packages/reporter": "*", "@packages/socket": "*", "@packages/web-config": "*", - "@types/enzyme": "3.10.4", - "@types/react": "16.9.21", "ansi-to-html": "0.6.14", "bluebird": "3.5.0", "chai": "4.2.0", diff --git a/packages/runner/tsconfig.json b/packages/runner/tsconfig.json index 6e3efcf1d5cc..0cee70cbaa64 100644 --- a/packages/runner/tsconfig.json +++ b/packages/runner/tsconfig.json @@ -9,6 +9,7 @@ */ "allowJs": true, "jsx": "react", + "outDir": "dist", "noImplicitAny": false, "noImplicitThis": false, "preserveWatchOutput": true, @@ -45,12 +46,6 @@ // "baseUrl": "../", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": ["../driver/src"], /* List of root folders whose combined content represents the structure of the project at runtime. */ - "typeRoots": [ - "../driver/node_modules", - "../../cli", - "../driver/src", - "./node_modules", - ], /* List of folders to include type definitions from. */ // "types": [], /* Type declaration files to be included in compilation. */ "allowSyntheticDefaultImports": true, "esModuleInterop": true, diff --git a/packages/ui-components/tsconfig.json b/packages/ui-components/tsconfig.json index 046d5dca1994..4987f019216e 100644 --- a/packages/ui-components/tsconfig.json +++ b/packages/ui-components/tsconfig.json @@ -45,12 +45,6 @@ // "baseUrl": "../", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": ["../driver/src"], /* List of root folders whose combined content represents the structure of the project at runtime. */ - "typeRoots": [ - "../driver/node_modules", - "../../cli/types/index.d.ts", - "../driver/src", - "./node_modules" - ], /* List of folders to include type definitions from. */ // "types": [], /* Type declaration files to be included in compilation. */ "allowSyntheticDefaultImports": true, "esModuleInterop": true, diff --git a/packages/web-config/node-jsdom-setup.ts b/packages/web-config/node-jsdom-setup.ts index cbe9ae758ca3..87de82d75b14 100644 --- a/packages/web-config/node-jsdom-setup.ts +++ b/packages/web-config/node-jsdom-setup.ts @@ -1,6 +1,9 @@ import mockRequire from 'mock-require' import { JSDOM } from 'jsdom' import * as ansiEscapes from 'ansi-escapes' +import enzyme from 'enzyme' +import EnzymeAdapter from 'enzyme-adapter-react-16' +import ChaiEnzyme from 'chai-enzyme' declare global { module NodeJS { @@ -10,12 +13,21 @@ declare global { } } +interface RegisterDeps { + enzyme: typeof enzyme + EnzymeAdapter: typeof EnzymeAdapter + chaiEnzyme: typeof ChaiEnzyme + requireOverride: (...args: any[]) => any +} + +type TimeoutID = number + export const register = ({ enzyme, EnzymeAdapter, chaiEnzyme, requireOverride, -}) => { +}: RegisterDeps) => { const jsdom = new JSDOM('') const { window } = jsdom @@ -24,28 +36,31 @@ export const register = ({ // const chaiEnzyme = require('chai-enzyme') global.window = window - global.document = window.document - window.Selection = { prototype: { isCollapsed: {} } } + global.document = window.document; + + // DOMWindow doesn't have Selection yet. + (window as any).Selection = { prototype: { isCollapsed: {} } } + global.navigator = { userAgent: 'node.js', } - global.requestAnimationFrame = function (callback) { + global.requestAnimationFrame = function (callback: ((...args: any[]) => void)) { return setTimeout(callback, 0) } - global.cancelAnimationFrame = function (id) { + global.cancelAnimationFrame = function (id: TimeoutID) { clearTimeout(id) } - Object.keys(window.document.defaultView).forEach((property) => { + Object.keys(window.document.defaultView as Record).forEach((property) => { if ( property === 'localStorage' || property === 'sessionStorage' || typeof global[property] !== 'undefined' ) return - global[property] = window.document.defaultView[property] + global[property] = (window.document.defaultView as Record)[property] }) // enzyme, and therefore chai-enzyme, needs to be required after @@ -63,7 +78,7 @@ export const register = ({ const overrideRequire = () => { const _load = Module._load - Module._load = function (...args) { + Module._load = function (...args: any[]) { let browserPkg = args if (requireOverride) { @@ -107,7 +122,7 @@ after(() => { process.stdout.write(ansiEscapes.cursorShow) }) -export const returnMockRequire = (name, modExport = {}) => { +export const returnMockRequire = (name: string, modExport: object = {}) => { mockRequire(name, modExport) return require(name) diff --git a/packages/web-config/package.json b/packages/web-config/package.json index b859122d040c..9cf7e1a91952 100644 --- a/packages/web-config/package.json +++ b/packages/web-config/package.json @@ -13,6 +13,8 @@ "@packages/coffee": "*", "@types/copy-webpack-plugin": "5.0.0", "@types/html-webpack-plugin": "3.2.1", + "@types/jsdom": "^12.2.4", + "@types/mock-require": "^2.0.0", "@types/webpack": "4.41.0", "ansi-escapes": "4.3.0", "autoprefixer": "9.7.4", diff --git a/scripts/type_check.js b/scripts/type_check.js new file mode 100644 index 000000000000..409f83eb4859 --- /dev/null +++ b/scripts/type_check.js @@ -0,0 +1,93 @@ +const fs = require('fs') +const path = require('path') +const execa = require('execa') +const Listr = require('listr') +const commander = require('commander') + +const program = new commander.Command() + +program.usage('[options]') + +program +.option('-p, --project ', 'projects to check types (separated by commas)') +.option('--skip-lib-check', 'skip type checking of all declaration files (*.d.ts)') +.option('--ignore-progress', 'do not show progress') +.action((...args) => { + const projects = [] + const packageRoot = path.join(__dirname, '../packages') + const getPackagePath = (name) => { + if (name !== 'cli') { + return path.join(packageRoot, name) + } + + throw new Error(`type-check command doesn't check cli types. Use "npm run dtslint" in "cli" directory instead.`) + } + const addProject = (name) => { + return projects.push({ + name, + path: getPackagePath(name), + }) + } + + if (program.project) { + program.project.split(',').forEach((p) => addProject(p)) + } else { + fs.readdirSync(packageRoot).forEach((file) => { + const packagePath = getPackagePath(file) + + if (fs.lstatSync(packagePath).isDirectory() && fs.existsSync(path.join(packagePath, 'tsconfig.json'))) { + addProject(file) + } + }) + } + + const options = ['--noEmit', '--pretty'] + + if (program.skipLibCheck) { + options.push('--skipLibCheck') + } + + const tasks = new Listr(projects.map((proj) => { + return { + title: proj.name, + task: () => { + const cwd = proj.path + const tsc = require.resolve('typescript/bin/tsc') + + return execa(tsc, options, { + cwd, + }).catch((err) => { + throw { + name: proj.name, + err, + } + }) + }, + } + }), { + concurrent: 4, + exitOnError: false, + renderer: program.ignoreProgress ? 'silent' : 'default', + }) + + tasks.run() + .then(() => { + log('') + log('Type check passed successfully.') + }) + .catch((err) => { + process.exitCode = 1 + + err.errors.forEach((e) => { + log('') + log(`${e.name} failed\n${e.err.stdout}`) + }) + }) +}) + +const log = (msg) => { + // eslint-disable-next-line no-console + console.log(msg) +} + +program.parse(process.argv) diff --git a/yarn.lock b/yarn.lock index be144d54844b..14ebb1ee76b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3477,6 +3477,13 @@ resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd" integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ== +"@types/enzyme-adapter-react-16@1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.5.tgz#1bf30a166f49be69eeda4b81e3f24113c8b4e9d5" + integrity sha512-K7HLFTkBDN5RyRmU90JuYt8OWEY2iKUn43SDWEoBOXd/PowUWjLZ3Q6qMBiQuZeFYK/TOstaZxsnI0fXoAfLpg== + dependencies: + "@types/enzyme" "*" + "@types/enzyme@*": version "3.10.5" resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.10.5.tgz#fe7eeba3550369eed20e7fb565bfb74eec44f1f0" @@ -3485,10 +3492,10 @@ "@types/cheerio" "*" "@types/react" "*" -"@types/enzyme@3.10.4": - version "3.10.4" - resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.10.4.tgz#dd4961042381a7c0f6637ce25fec3f773ce489dd" - integrity sha512-P5XpxcIt9KK8QUH4al4ttfJfIHg6xmN9ZjyUzRSzAsmDYwRXLI05ng/flZOPXrEXmp8ZYiN8/tEXYK5KSOQk3w== +"@types/enzyme@3.9.1": + version "3.9.1" + resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.9.1.tgz#3a0ce07e30066dbc26cd3474c8e680af2d249e26" + integrity sha512-CasnOP73BFE3/5JvGkod+oQtGOD1+CVWz9BV2iAqDFJ+sofL5gTiizSr8ZM3lpDY27ptC8yjAdrUCdv8diKKqw== dependencies: "@types/cheerio" "*" "@types/react" "*" @@ -3607,6 +3614,15 @@ dependencies: "@types/sizzle" "*" +"@types/jsdom@^12.2.4": + version "12.2.4" + resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-12.2.4.tgz#845cd4d43f95b8406d9b724ec30c03edadcd9528" + integrity sha512-q+De3S/Ri6U9uPx89YA1XuC+QIBgndIfvBaaJG0pRT8Oqa75k4Mr7G9CRZjIvlbLGIukO/31DFGFJYlQBmXf/A== + dependencies: + "@types/node" "*" + "@types/tough-cookie" "*" + parse5 "^4.0.0" + "@types/json-schema@^7.0.3": version "7.0.4" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" @@ -3661,6 +3677,13 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== +"@types/mock-require@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/mock-require/-/mock-require-2.0.0.tgz#57a4f0db0b4b6274f610a2d2c20beb3c842181e1" + integrity sha512-nOgjoE5bBiDeiA+z41i95makyHUSMWQMOPocP+J67Pqx/68HAXaeWN1NFtrAYYV6LrISIZZ8vKHm/a50k0f6Sg== + dependencies: + "@types/node" "*" + "@types/node@*", "@types/node@>= 8": version "13.9.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.9.1.tgz#96f606f8cd67fb018847d9b61e93997dabdefc72" @@ -3711,13 +3734,6 @@ resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.25.47.tgz#904f2ee46149af42902fe7dc01867e32798e8b37" integrity sha512-+ffSU83+PR4/cZtNTkUcFkg70sK4GePle7p5h05bQ37ycPumOx/TBpU52bt36GKDlds6tCqXheqPvgC52MMLug== -"@types/ramda@0.26.38": - version "0.26.38" - resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.26.38.tgz#9d19bb910bb15fc9a213402092e160cbbb5acc9b" - integrity sha512-legQx15y72vedr5fkVTb5xZaI/OXMzJgZYbMxVL5r269sOg7fZIeitEOumcevMPOMZdqH4cMoL35VuU13TLvVA== - dependencies: - ts-toolbelt "^4.12.0" - "@types/range-parser@*": version "1.2.3" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" @@ -3730,7 +3746,7 @@ dependencies: "@types/react" "*" -"@types/react@*": +"@types/react@*", "@types/react@16.9.23": version "16.9.23" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.23.tgz#1a66c6d468ba11a8943ad958a8cb3e737568271c" integrity sha512-SsGVT4E7L2wLN3tPYLiF20hmZTPGuzaayVunfgXzUn1x4uHVsKH6QDJQ/TdpHqwsTLd4CwrmQ2vOgxN7gE24gw== @@ -3738,14 +3754,6 @@ "@types/prop-types" "*" csstype "^2.2.0" -"@types/react@16.9.21": - version "16.9.21" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.21.tgz#99e274e2ecfab6bb93920e918341daa3198b348d" - integrity sha512-xpmenCMeBwJRct8vmIfczlgdOXWIWASoOM857kxKfHlVQvDltRh7IFRVfGws79iO2jkNPXOeWREyKoClzhBaQA== - dependencies: - "@types/prop-types" "*" - csstype "^2.2.0" - "@types/relateurl@*": version "0.2.28" resolved "https://registry.yarnpkg.com/@types/relateurl/-/relateurl-0.2.28.tgz#6bda7db8653fa62643f5ee69e9f69c11a392e3a6" @@ -10032,6 +10040,19 @@ env-variable@0.0.x: resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.6.tgz#74ab20b3786c545b62b4a4813ab8cf22726c9808" integrity sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg== +enzyme-adapter-react-16@1.12.1: + version "1.12.1" + resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.12.1.tgz#6a2d74c80559d35ac0a91ca162fa45f4186290cf" + integrity sha512-GB61gvY97XvrA6qljExGY+lgI6BBwz+ASLaRKct9VQ3ozu0EraqcNn3CcrUckSGIqFGa1+CxO5gj5is5t3lwrw== + dependencies: + enzyme-adapter-utils "^1.11.0" + object.assign "^4.1.0" + object.values "^1.1.0" + prop-types "^15.7.2" + react-is "^16.8.6" + react-test-renderer "^16.0.0-0" + semver "^5.6.0" + enzyme-adapter-react-16@1.15.2: version "1.15.2" resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.2.tgz#b16db2f0ea424d58a808f9df86ab6212895a4501" @@ -10047,7 +10068,7 @@ enzyme-adapter-react-16@1.15.2: react-test-renderer "^16.0.0-0" semver "^5.7.0" -enzyme-adapter-utils@^1.13.0: +enzyme-adapter-utils@^1.11.0, enzyme-adapter-utils@^1.13.0: version "1.13.0" resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.13.0.tgz#01c885dde2114b4690bf741f8dc94cee3060eb78" integrity sha512-YuEtfQp76Lj5TG1NvtP2eGJnFKogk/zT70fyYHXK2j3v6CtuHqc8YmgH/vaiBfL8K1SgVVbQXtTcgQZFwzTVyQ== @@ -17995,7 +18016,7 @@ object.reduce@^1.0.0: for-own "^1.0.0" make-iterator "^1.0.0" -object.values@^1.1.1: +object.values@^1.1.0, object.values@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== @@ -18531,7 +18552,7 @@ parse-url@^5.0.0: parse-path "^4.0.0" protocols "^1.4.0" -parse5@4.0.0: +parse5@4.0.0, parse5@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== @@ -23284,11 +23305,6 @@ ts-node@8.3.0: source-map-support "^0.5.6" yn "^3.0.0" -ts-toolbelt@^4.12.0: - version "4.14.6" - resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-4.14.6.tgz#9a232f62276caeee4fa9e81e0c4bffa047de0765" - integrity sha512-SONcnRd93+LuYGfn/CZg5A5qhCODohZslAVZKHHu5bnwUxoXLqd2k2VIdwRUXYfKnY+UCeNbI2pTPz+Dno6Mpg== - tslib@^1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.11.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"