include CLI TS types in a way to avoid clashing with Jest (#7352)

This commit is contained in:
Gleb Bahmutov
2020-05-15 17:31:22 -04:00
committed by GitHub
parent 5a4e339789
commit a2c0bc3e3e
23 changed files with 325 additions and 59 deletions
+48 -2
View File
@@ -364,9 +364,10 @@ jobs:
command: ls -la types
working_directory: cli
- run:
command: yarn lerna exec --scope cypress "yarn dtslint"
command: ls -la chai
working_directory: cli/types
- run:
command: yarn type-check --ignore-progress
command: yarn lerna exec --scope cypress "yarn dtslint"
- store-npm-logs
build-system-unit-tests:
@@ -1032,6 +1033,47 @@ jobs:
working_directory: test-binary
command: $(npm bin)/cypress info
test-types-cypress-and-jest:
parameters:
executor:
description: Executor name to use
type: executor
default: cy-doc
wd:
description: Working directory, should be OUTSIDE cypress monorepo folder
type: string
default: /root/test-cypress-and-jest
<<: *defaults
steps:
- attach_workspace:
at: ~/
# make sure we have cypress.zip received
- run: ls -l
- run: ls -l cypress.zip cypress.tgz
- run: mkdir << parameters.wd >>
- run: node --version
- run: npm --version
- run:
name: Create new NPM package ⚗️
working_directory: << parameters.wd >>
command: npm init -y
- run:
name: Install dependencies 📦
working_directory: << parameters.wd >>
environment:
CYPRESS_INSTALL_BINARY: /root/cypress/cypress.zip
# let's install Cypress, Jest and any other package that might conflict
# https://github.com/cypress-io/cypress/issues/6690
command: |
npm install /root/cypress/cypress.tgz \
typescript jest @types/jest enzyme @types/enzyme
- run:
name: Test types clash ⚔️
working_directory: << parameters.wd >>
command: |
echo "console.log('hello world')" > hello.ts
npx tsc hello.ts --noEmit
# install NPM + binary zip and run against staging API
"test-binary-against-staging":
<<: *defaults
@@ -1354,6 +1396,10 @@ linux-workflow: &linux-workflow
requires:
- build-binary
- build-npm-package
- test-types-cypress-and-jest:
requires:
- build-binary
- build-npm-package
- post-pre-release-install-comment:
context: test-runner:commit-status-checks
filters:
+10 -10
View File
@@ -23,16 +23,6 @@
"@cypress/listr-verbose-renderer": "0.4.1",
"@cypress/request": "2.88.5",
"@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",
@@ -72,6 +62,16 @@
"@babel/preset-env": "7.9.5",
"@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",
"chai": "3.5.0",
"chai-as-promised": "7.1.1",
"chai-string": "1.5.0",
+65 -23
View File
@@ -1,28 +1,70 @@
const fs = require('../lib/fs')
const path = require('path')
#!/usr/bin/env node
// @ts-check
/* eslint-disable no-console */
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')
})
// 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)
/**
* 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.
* Replaces "reference types=<name>" comment with "reference path=..." line.
* @param {string} typeName - like "chai" or "jquery"
* @param {string} relativeTypesFilePath - relative path to .d.ts file like "../chai/index.d.ts"
* @param {string} filename - the source file to change
*/
const includeTypes = [
'blob-util',
'bluebird',
'lodash',
'mocha',
'minimatch',
'sinon',
'sinon-chai',
'chai',
'chai-jquery',
'jquery',
]
function makeReferenceTypesCommentRelative (typeName, relativeTypesFilePath, filename) {
console.log('in file %s changing reference for types %s to relative path %s',
filename, typeName, relativeTypesFilePath)
includeTypes.forEach((t) => {
const dir = path.join(__dirname, '../types', t)
const referenceTypes = `<reference types="${typeName}" />`
const relativeTypes = `<reference path="${relativeTypesFilePath}" />`
if (fs.existsSync(dir)) {
fs.removeSync(dir)
}
})
shell.sed(
'-i',
referenceTypes,
relativeTypes,
filename,
)
}
// fix paths to Chai, jQuery and other types to be relative
makeReferenceTypesCommentRelative('chai', '../chai/index.d.ts',
join('types', 'chai-jquery', 'index.d.ts'))
makeReferenceTypesCommentRelative('jquery', '../jquery/index.d.ts',
join('types', 'chai-jquery', 'index.d.ts'))
const sinonChaiFilename = join('types', 'sinon-chai', 'index.d.ts')
makeReferenceTypesCommentRelative('chai', '../chai/index.d.ts', sinonChaiFilename)
// also use relative import via path for sinon-chai
// there is reference comment line we need to fix to be relative
makeReferenceTypesCommentRelative('sinon', '../sinon/index.d.ts', sinonChaiFilename)
// and an import sinon line to be changed to relative path
shell.sed('-i', 'from \'sinon\';', 'from \'../sinon\';', sinonChaiFilename)
+8
View File
@@ -1,5 +1,7 @@
#!/usr/bin/env node
const { includeTypes } = require('./utils')
const { join } = require('path')
const shell = require('shelljs')
shell.set('-v') // verbose
@@ -13,6 +15,12 @@ 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')
+19
View File
@@ -0,0 +1,19 @@
/**
* 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 }
+13
View File
@@ -0,0 +1,13 @@
// 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
}
+11
View File
@@ -0,0 +1,11 @@
// 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
}
+10
View File
@@ -0,0 +1,10 @@
// 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
/// <reference path="./chai/index.d.ts" />
declare namespace Chai {
interface Include {
html(html: string): Assertion
text(text: string): Assertion
value(text: string): Assertion
}
}
+96
View File
@@ -0,0 +1,96 @@
// 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
}
+7
View File
@@ -0,0 +1,7 @@
import moment = require('moment')
export = Moment
export as namespace Moment
declare namespace Moment {
type MomentStatic = typeof moment
}
+12 -9
View File
@@ -7,15 +7,17 @@
// TypeScript Version: 3.0
// Updated by the Cypress team: https://www.cypress.io/about/
/// <reference types="blob-util" />
/// <reference types="lodash" />
/// <reference types="sinon" />
/// <reference types="sinon-chai" />
/// <reference types="mocha" />
/// <reference types="jquery" />
/// <reference types="chai" />
/// <reference types="chai-jquery" />
/// <reference types="bluebird" />
/// <reference path="./cy-blob-util.d.ts" />
/// <reference path="./cy-bluebird.d.ts" />
/// <reference path="./cy-moment.d.ts" />
/// <reference path="./cy-minimatch.d.ts" />
/// <reference path="./cy-chai.d.ts" />
/// <reference path="./lodash/index.d.ts" />
/// <reference path="./sinon/index.d.ts" />
/// <reference path="./sinon-chai/index.d.ts" />
/// <reference path="./mocha/index.d.ts" />
/// <reference path="./jquery/index.d.ts" />
/// <reference path="./chai-jquery/index.d.ts" />
// jQuery includes dependency "sizzle" that provides types
// so we include it too in "node_modules/sizzle".
@@ -29,6 +31,7 @@
type EventEmitter2 = import("eventemitter2").EventEmitter2
type Bluebird<R> = import("bluebird")<R>
// type helpers
type Nullable<T> = T | null
interface EventEmitter extends EventEmitter2 {
-3
View File
@@ -88,8 +88,6 @@
"@fellow/eslint-plugin-coffee": "0.4.13",
"@percy/cypress": "2.3.0",
"@types/bluebird": "3.5.29",
"@types/chai": "4.2.7",
"@types/chai-enzyme": "0.6.7",
"@types/classnames": "2.2.9",
"@types/debug": "4.1.5",
"@types/enzyme": "3.9.1",
@@ -100,7 +98,6 @@
"@types/lodash": "4.14.149",
"@types/markdown-it": "0.0.9",
"@types/mini-css-extract-plugin": "0.8.0",
"@types/mocha": "5.2.7",
"@types/node": "12.12.21",
"@types/prismjs": "1.16.0",
"@types/ramda": "0.25.47",
+8
View File
@@ -0,0 +1,8 @@
/// <reference path="../../cli/types/cy-blob-util.d.ts" />
/// <reference path="../../cli/types/cy-bluebird.d.ts" />
/// <reference path="../../cli/types/cy-moment.d.ts" />
/// <reference path="../../cli/types/cy-minimatch.d.ts" />
/// <reference path="../../cli/types/cypress.d.ts" />
/// <reference path="../../cli/types/cypress-global-vars.d.ts" />
/// <reference path="../../cli/types/cypress-type-helpers.d.ts" />
@@ -1,4 +1,3 @@
/// <reference types="cypress" />
import React from 'react'
import Experiments from './experiments'
import Collapse, { Panel } from 'rc-collapse'
@@ -1,4 +1,3 @@
/// <reference types="cypress" />
import React from 'react'
import ProjectId from './project-id'
import { mount } from 'cypress-react-unit-test'
@@ -1,4 +1,3 @@
/// <reference types="cypress" />
// prevents "regeneratorRuntime is not defined" error
import 'regenerator-runtime/runtime'
import React from 'react'
+1 -1
View File
@@ -1,4 +1,4 @@
/// <reference path="../../cli/types/index.d.ts" />
/// <reference path="../../cli/types/cypress.d.ts" />
/// <reference path="../ts/index.d.ts" />
export const $Cypress: Cypress.Cypress
@@ -1,5 +1,3 @@
/// <reference types="cypress" />
import { EventEmitter } from 'events'
describe('controls', function () {
@@ -1,5 +1,3 @@
/// <reference types="cypress" />
import sinon, { SinonStub, SinonSpy } from 'sinon'
import { EventEmitter } from 'events'
@@ -1,5 +1,3 @@
/// <reference types="cypress" />
import { EventEmitter } from 'events'
describe('controls', function () {
@@ -1,5 +1,3 @@
/// <reference types="cypress" />
import { EventEmitter } from 'events'
describe('controls', function () {
+9
View File
@@ -0,0 +1,9 @@
/// <reference path="../../cli/types/cy-blob-util.d.ts" />
/// <reference path="../../cli/types/cy-bluebird.d.ts" />
/// <reference path="../../cli/types/cy-moment.d.ts" />
/// <reference path="../../cli/types/cy-minimatch.d.ts" />
/// <reference path="../../cli/types/cypress.d.ts" />
/// <reference path="../../cli/types/cypress-global-vars.d.ts" />
/// <reference path="../../cli/types/cypress-type-helpers.d.ts" />
/// <reference path="../../cli/types/cypress-expect.d.ts" />
+8
View File
@@ -0,0 +1,8 @@
/// <reference path="../../cli/types/cy-blob-util.d.ts" />
/// <reference path="../../cli/types/cy-bluebird.d.ts" />
/// <reference path="../../cli/types/cy-moment.d.ts" />
/// <reference path="../../cli/types/cy-minimatch.d.ts" />
/// <reference path="../../cli/types/cypress.d.ts" />
/// <reference path="../../cli/types/cypress-global-vars.d.ts" />
/// <reference path="../../cli/types/cypress-type-helpers.d.ts" />