diff --git a/.eslintrc b/.eslintrc index 0a9455e9f166..6f2cbf68ab49 100644 --- a/.eslintrc +++ b/.eslintrc @@ -59,10 +59,14 @@ "legacyDecorators": true } }, - "overrides": { - "files": ["**/*.jsx"], - "rules": { - "arrow-body-style": "off", + "overrides": [ + { + "files": [ + "**/*.jsx" + ], + "rules": { + "arrow-body-style": "off" + } } - } + ] } diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000000..91224e5de829 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +**/* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4a5165c41cd6..01e8e9292387 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,6 +33,7 @@ Thanks for taking the time to contribute! :smile: - [Branches](#branches) - [Pull Requests](#pull-requests) - [Testing](#testing) + - [Dependencies](#dependencies) - [Deployment](#deployment) ## CI status @@ -338,6 +339,10 @@ This repository is exhaustively tested by [CircleCI](https://circleci.com/gh/cyp To run local tests, consult the `README.md` of each package. +### Dependencies + +We use [RenovateBot](https://renovatebot.com/) to automatically upgrade our dependencies. The bot keeps chugging using settings in [renovate.json](renovate.json) to open PRs and if they pass merge patches. Minor and major updates require manual merge. + ## Deployment We will try to review and merge pull requests quickly. After merging we diff --git a/circle.yml b/circle.yml index c3014219fe84..1aec25322518 100644 --- a/circle.yml +++ b/circle.yml @@ -1,21 +1,38 @@ -version: 2 +version: 2.1 defaults: &defaults parallelism: 1 working_directory: ~/cypress - docker: - # the Docker image with Cypress dependencies and Chrome browser - - image: cypress/browsers:chrome64 - environment: - ## set specific timezone - TZ: "/usr/share/zoneinfo/America/New_York" - - ## store artifacts here - CIRCLE_ARTIFACTS: /tmp/artifacts - - ## set so that e2e tests are consistent - COLUMNS: 100 - LINES: 24 + parameters: + executor: + type: executor + default: cy-doc + executor: <> + environment: + ## set specific timezone + TZ: "/usr/share/zoneinfo/America/New_York" + + ## store artifacts here + CIRCLE_ARTIFACTS: /tmp/artifacts + + ## set so that e2e tests are consistent + COLUMNS: 100 + LINES: 24 + +executors: + # the Docker image with Cypress dependencies and Chrome browser + cy-doc: + docker: + - image: cypress/browsers:chrome64 + environment: + PLATFORM: linux + + # executor to run on Mac OS + mac: + macos: + xcode: "9.0.1" + environment: + PLATFORM: mac jobs: ## code checkout and NPM installs @@ -23,7 +40,6 @@ jobs: <<: *defaults steps: - checkout - - run: name: Print working folder command: echo $PWD @@ -38,52 +54,46 @@ jobs: command: npm -v - run: npm run check-node-version - ## make sure the TERM is set to 'xterm' in node + ## make sure the TERM is set to 'xterm' in node (Linux only) ## else colors (and tests) will fail ## See the following information ## * http://andykdocs.de/development/Docker/Fixing+the+Docker+TERM+variable+issue ## * https://unix.stackexchange.com/questions/43945/whats-the-difference-between-various-term-variables - - run: - name: Checking TERM and COLUMNS are set - command: | - node -e 'assert.ok(process.env.TERM === "xterm", `process.env.TERM=${process.env.TERM} and must be set to "xterm" for Docker to work`)' - node -e 'assert.ok(process.env.COLUMNS === "100", `process.env.COLUMNS=${process.env.COLUMNS} must be set to 100 for snapshots to pass`)' - node -e 'console.log("stdout.isTTY?", process.stdout.isTTY)' - node -e 'console.log("stderr.isTTY?", process.stderr.isTTY)' + - run: npm run check-terminal # need to restore a separate cache for each package.json - restore_cache: - key: v5-{{ .Branch }}-cli-deps + key: v6-{{ arch }}-{{ .Branch }}-cli-deps - restore_cache: - key: v5-{{ .Branch }}-root-deps + key: v5-{{ arch }}-{{ .Branch }}-root-deps - restore_cache: - key: v5-{{ .Branch }}-deps-coffee + key: v5-{{ arch }}-{{ .Branch }}-deps-coffee - restore_cache: - key: v5-{{ .Branch }}-deps-desktop-gui + key: v5-{{ arch }}-{{ .Branch }}-deps-desktop-gui - restore_cache: - key: v5-{{ .Branch }}-deps-driver + key: v5-{{ arch }}-{{ .Branch }}-deps-driver - restore_cache: - key: v5-{{ .Branch }}-deps-example + key: v5-{{ arch }}-{{ .Branch }}-deps-example - restore_cache: - key: v7-{{ .Branch }}-deps-electron + key: v7-{{ arch }}-{{ .Branch }}-deps-electron - restore_cache: - key: v5-{{ .Branch }}-deps-extension + key: v5-{{ arch }}-{{ .Branch }}-deps-extension - restore_cache: - key: v5-{{ .Branch }}-deps-https-proxy + key: v5-{{ arch }}-{{ .Branch }}-deps-https-proxy - restore_cache: - key: v5-{{ .Branch }}-deps-launcher + key: v5-{{ arch }}-{{ .Branch }}-deps-launcher - restore_cache: - key: v5-{{ .Branch }}-deps-reporter + key: v5-{{ arch }}-{{ .Branch }}-deps-reporter - restore_cache: - key: v5-{{ .Branch }}-deps-runner + key: v5-{{ arch }}-{{ .Branch }}-deps-runner - restore_cache: - key: v5-{{ .Branch }}-deps-server + key: v5-{{ arch }}-{{ .Branch }}-deps-server - restore_cache: - key: v5-{{ .Branch }}-deps-socket + key: v5-{{ arch }}-{{ .Branch }}-deps-socket - restore_cache: - key: v5-{{ .Branch }}-deps-static + key: v5-{{ arch }}-{{ .Branch }}-deps-static - restore_cache: - key: v5-{{ .Branch }}-deps-ts + key: v5-{{ arch }}-{{ .Branch }}-deps-ts # show what is already cached globally - run: ls $(npm -g bin) @@ -105,69 +115,69 @@ jobs: # save each node_modules folder per package - save_cache: - key: v5-{{ .Branch }}-cli-deps-{{ checksum "cli/package.json" }} + key: v6-{{ arch }}-{{ .Branch }}-cli-deps-{{ checksum "cli/package.json" }} paths: - cli/node_modules - save_cache: - key: v5-{{ .Branch }}-root-deps-{{ checksum "package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-root-deps-{{ checksum "package.json" }} paths: - node_modules - save_cache: - key: v5-{{ .Branch }}-deps-coffee-{{ checksum "packages/coffee/package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-deps-coffee-{{ checksum "packages/coffee/package.json" }} paths: - packages/coffee/node_modules - save_cache: - key: v5-{{ .Branch }}-deps-desktop-gui-{{ checksum "packages/desktop-gui/package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-deps-desktop-gui-{{ checksum "packages/desktop-gui/package.json" }} paths: - packages/desktop-gui/node_modules - save_cache: - key: v5-{{ .Branch }}-deps-driver-{{ checksum "packages/driver/package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-deps-driver-{{ checksum "packages/driver/package.json" }} paths: - packages/driver/node_modules - save_cache: - key: v5-{{ .Branch }}-deps-example-{{ checksum "packages/example/package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-deps-example-{{ checksum "packages/example/package.json" }} paths: - packages/example/node_modules - save_cache: - key: v7-{{ .Branch }}-deps-electron-{{ checksum "packages/electron/package.json" }} + key: v7-{{ arch }}-{{ .Branch }}-deps-electron-{{ checksum "packages/electron/package.json" }} paths: - packages/electron/node_modules - ~/.cache/electron - ~/.electron - save_cache: - key: v5-{{ .Branch }}-deps-extension-{{ checksum "packages/extension/package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-deps-extension-{{ checksum "packages/extension/package.json" }} paths: - packages/extension/node_modules - save_cache: - key: v5-{{ .Branch }}-deps-https-proxy-{{ checksum "packages/https-proxy/package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-deps-https-proxy-{{ checksum "packages/https-proxy/package.json" }} paths: - packages/https-proxy/node_modules - save_cache: - key: v5-{{ .Branch }}-deps-launcher-{{ checksum "packages/launcher/package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-deps-launcher-{{ checksum "packages/launcher/package.json" }} paths: - packages/launcher/node_modules - save_cache: - key: v5-{{ .Branch }}-deps-reporter-{{ checksum "packages/reporter/package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-deps-reporter-{{ checksum "packages/reporter/package.json" }} paths: - packages/reporter/node_modules - save_cache: - key: v5-{{ .Branch }}-deps-runner-{{ checksum "packages/runner/package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-deps-runner-{{ checksum "packages/runner/package.json" }} paths: - packages/runner/node_modules - save_cache: - key: v5-{{ .Branch }}-deps-server-{{ checksum "packages/server/package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-deps-server-{{ checksum "packages/server/package.json" }} paths: - packages/server/node_modules - save_cache: - key: v5-{{ .Branch }}-deps-socket-{{ checksum "packages/socket/package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-deps-socket-{{ checksum "packages/socket/package.json" }} paths: - packages/socket/node_modules - save_cache: - key: v5-{{ .Branch }}-deps-static-{{ checksum "packages/static/package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-deps-static-{{ checksum "packages/static/package.json" }} paths: - packages/static/node_modules - save_cache: - key: v5-{{ .Branch }}-deps-ts-{{ checksum "packages/ts/package.json" }} + key: v5-{{ arch }}-{{ .Branch }}-deps-ts-{{ checksum "packages/ts/package.json" }} paths: - packages/ts/node_modules @@ -175,7 +185,8 @@ jobs: ## we update stop-only # - run: npm run stop-only ## now go build all of subpackages - - run: npm run build + - run: npm run prebuild -- --serial + - run: npm run build -- --serial ## save entire folder as artifact for other jobs to run without reinstalling - persist_to_workspace: @@ -191,7 +202,7 @@ jobs: - run: npm run lint - run: npm run all lint - "unit-tests": + unit-tests: <<: *defaults parallelism: 1 steps: @@ -323,7 +334,7 @@ jobs: - store_test_results: path: /tmp/cypress - "3x-driver-integration-tests": + "driver-integration-tests-3x": <<: *defaults parallelism: 3 steps: @@ -347,7 +358,7 @@ jobs: - store_artifacts: path: /tmp/artifacts - "2x-desktop-gui-integration-tests": + "desktop-gui-integration-tests-2x": <<: *defaults parallelism: 2 steps: @@ -395,14 +406,14 @@ jobs: command: node index.js working_directory: packages/launcher - "build-binary": + build-binary: <<: *defaults steps: - attach_workspace: at: ~/ - run: $(npm bin)/print-arch - - run: npm run binary-build -- --platform linux --version $NEXT_DEV_VERSION - - run: npm run binary-zip -- --platform linux + - run: npm run binary-build -- --platform $PLATFORM --version $NEXT_DEV_VERSION + - run: npm run binary-zip -- --platform $PLATFORM - run: ls -l *.zip - run: name: upload unique binary @@ -597,12 +608,51 @@ jobs: CYPRESS_ENV=staging \ $(npm bin)/cypress run --record + "test-binary-against-kitchensink": + <<: *defaults + steps: + - attach_workspace: + at: ~/ + - attach_workspace: + at: /tmp/urls + - run: + name: Cloning kitchensink project + command: git clone --depth 1 https://github.com/cypress-io/cypress-example-kitchensink.git /tmp/kitchensink + - run: + command: npm install + working_directory: /tmp/kitchensink + - run: + name: Install Cypress + working_directory: /tmp/kitchensink + # force installing the freshly built binary + command: CYPRESS_INSTALL_BINARY=/tmp/urls/cypress.zip npm i /tmp/urls/cypress.tgz + - run: + working_directory: /tmp/kitchensink + command: npm run build + - run: + working_directory: /tmp/kitchensink + command: npm start + background: true + - run: + working_directory: /tmp/kitchensink + command: npm run e2e + + mac-os-build: + executor: mac + steps: + - run: + name: Show keychains + command: security list-keychains + - run: + name: Find code signing identity + command: security find-identity -v -p codesigning + workflows: - version: 2 - build_and_test: + linux: jobs: - build - lint: + name: Linux lint requires: - build # unit, integration and e2e tests @@ -639,10 +689,10 @@ workflows: - server-e2e-tests-8: requires: - build - - 3x-driver-integration-tests: + - driver-integration-tests-3x: requires: - build - - 2x-desktop-gui-integration-tests: + - desktop-gui-integration-tests-2x: requires: - build - run-launcher: @@ -702,3 +752,43 @@ workflows: requires: - build-npm-package - build-binary + - test-binary-against-kitchensink: + filters: + branches: + only: + - develop + requires: + - build-npm-package + - build-binary + + # disable Mac build until we can figure CircleCI v2 story + # for code signing the built binary + # https://github.com/cypress-io/cypress/issues/2958 + + # mac: + # jobs: + # - build: + # name: Mac build + # executor: mac + # - lint: + # name: Mac lint + # executor: mac + # requires: + # - Mac build + # # maybe run unit tests? + # - mac-os-build: + # filters: + # branches: + # only: + # - develop + + # - build-binary: + # name: Mac binary + # executor: mac + # filters: + # branches: + # only: + # - develop + # requires: + # - Mac build + # - mac-os-build diff --git a/cli/__snapshots__/install_spec.js b/cli/__snapshots__/install_spec.js index 27475c45c916..dc4ed9859a92 100644 --- a/cli/__snapshots__/install_spec.js +++ b/cli/__snapshots__/install_spec.js @@ -56,7 +56,7 @@ https://on.cypress.io/installing-cypress exports['installed version does not match needed version 1'] = ` -Cypress x.x.x is already installed in /cache/Cypress/1.2.3 +Cypress x.x.x is installed in /cache/Cypress/1.2.3 Installing Cypress (version: 1.2.3) @@ -73,7 +73,7 @@ https://on.cypress.io/installing-cypress exports['forcing true always installs 1'] = ` -Cypress 1.2.3 is already installed in /cache/Cypress/1.2.3 +Cypress 1.2.3 is installed in /cache/Cypress/1.2.3 Installing Cypress (version: 1.2.3) @@ -90,7 +90,7 @@ https://on.cypress.io/installing-cypress exports['warning installing as global 1'] = ` -Cypress x.x.x is already installed in /cache/Cypress/1.2.3 +Cypress x.x.x is installed in /cache/Cypress/1.2.3 Installing Cypress (version: 1.2.3) @@ -113,7 +113,7 @@ Installing Cypress (version: 1.2.3) exports['installing in ci 1'] = ` -Cypress x.x.x is already installed in /cache/Cypress/1.2.3 +Cypress x.x.x is installed in /cache/Cypress/1.2.3 Installing Cypress (version: 1.2.3) @@ -162,7 +162,7 @@ exports['silent install 1'] = ` exports['version already installed - cypress install 1'] = ` -Cypress 1.2.3 is already installed in /cache/Cypress/1.2.3 +Cypress 1.2.3 is installed in /cache/Cypress/1.2.3 Skipping installation: @@ -172,7 +172,7 @@ Skipping installation: exports['version already installed - postInstall 1'] = ` -Cypress 1.2.3 is already installed in /cache/Cypress/1.2.3 +Cypress 1.2.3 is installed in /cache/Cypress/1.2.3 ` diff --git a/cli/lib/tasks/install.js b/cli/lib/tasks/install.js index 62f778080390..4f7b74922ada 100644 --- a/cli/lib/tasks/install.js +++ b/cli/lib/tasks/install.js @@ -215,7 +215,7 @@ const start = (options = {}) => { logger.log() logger.log(stripIndent` - Cypress ${chalk.green(binaryVersion)} is already installed in ${chalk.cyan(installDir)} + Cypress ${chalk.green(binaryVersion)} is installed in ${chalk.cyan(installDir)} `) logger.log() diff --git a/cli/package.json b/cli/package.json index 0fd43bccbe0a..a80c879e433e 100644 --- a/cli/package.json +++ b/cli/package.json @@ -48,7 +48,7 @@ "@types/lodash": "4.14.87", "@types/minimatch": "3.0.3", "@types/mocha": "2.2.44", - "@types/sinon": "4.0.0", + "@types/sinon": "7.0.0", "@types/sinon-chai": "2.7.29", "bluebird": "3.5.0", "cachedir": "1.3.0", @@ -67,7 +67,7 @@ "is-installed-globally": "0.1.0", "lazy-ass": "1.6.0", "listr": "0.12.0", - "lodash": "4.17.10", + "lodash": "4.17.11", "log-symbols": "2.2.0", "minimist": "1.2.0", "moment": "2.22.2", @@ -89,14 +89,14 @@ "chai-string": "1.4.0", "clear-module": "^2.1.0", "dependency-check": "^2.8.0", - "dtslint": "0.2.0", - "execa-wrap": "1.1.0", + "dtslint": "0.4.2", + "execa-wrap": "1.4.0", "mock-fs": "4.5.0", "nock": "^9.0.9", "nyc": "13.0.0", "proxyquire": "2.0.1", "shelljs": "0.7.8", - "sinon": "5.0.7", + "sinon": "7.2.2", "snap-shot-it": "^5.0.0" }, "files": [ diff --git a/cli/test/lib/tasks/verify_spec.js b/cli/test/lib/tasks/verify_spec.js index 2af444d9e509..6bbec19a9e36 100644 --- a/cli/test/lib/tasks/verify_spec.js +++ b/cli/test/lib/tasks/verify_spec.js @@ -44,13 +44,13 @@ context('lib/tasks/verify', () => { } os.platform.returns('darwin') + os.release.returns('0.0.0') sinon.stub(util, 'getCacheDir').returns(cacheDir) sinon.stub(util, 'isCi').returns(false) sinon.stub(util, 'pkgVersion').returns(packageVersion) sinon.stub(util, 'exec') - sinon.stub(xvfb, 'start').resolves() sinon.stub(xvfb, 'stop').resolves() sinon.stub(xvfb, 'isNeeded').returns(false) @@ -70,6 +70,7 @@ context('lib/tasks/verify', () => { it('logs error and exits when no version of Cypress is installed', () => { mockfs({}) + return verify.start() .then(() => { throw new Error('should have caught error') @@ -91,6 +92,7 @@ context('lib/tasks/verify', () => { executable: mockfs.file({ mode: 0777 }), packageVersion, }) + return verify.start() .then(() => { // nothing should have been logged to stdout @@ -166,12 +168,18 @@ context('lib/tasks/verify', () => { }) return verify.start({ force: true }) - .then(() => { throw new Error('Should have thrown') }) + .then(() => { + throw new Error('Should have thrown') + }) .catch((err) => { logger.error(err) }) - .then(() => fs.pathExistsAsync(binaryStatePath)) - .then((exists) => expect(exists).to.eq(false)) + .then(() => { + return fs.pathExistsAsync(binaryStatePath) + }) + .then((exists) => { + return expect(exists).to.eq(false) + }) .then(() => { return snapshot( 'fails verifying Cypress', @@ -190,6 +198,7 @@ context('lib/tasks/verify', () => { 222 after that more text ` + util.exec.withArgs(executablePath).resolves({ stdout: stdoutWithDebugOutput, }) @@ -219,8 +228,11 @@ context('lib/tasks/verify', () => { executable: false, packageVersion, }) + return verify.start() - .then(() => { throw new Error('Should have thrown') }) + .then(() => { + throw new Error('Should have thrown') + }) .catch((err) => { stdout = Stdout.capture() logger.error(err) @@ -239,8 +251,11 @@ context('lib/tasks/verify', () => { executable: mockfs.file({ mode: 0666 }), packageVersion, }) + return verify.start() - .then(() => { throw new Error('Should have thrown') }) + .then(() => { + throw new Error('Should have thrown') + }) .catch((err) => { stdout = Stdout.capture() logger.error(err) @@ -258,6 +273,7 @@ context('lib/tasks/verify', () => { executable: mockfs.file({ mode: 0777 }), packageVersion, }) + return verify.start() .then(() => { return snapshot( @@ -273,6 +289,7 @@ context('lib/tasks/verify', () => { executable: mockfs.file({ mode: 0777 }), packageVersion: '7.8.9', }) + return verify.start() .then(() => { return snapshot( @@ -333,10 +350,13 @@ context('lib/tasks/verify', () => { }) return verify.start() - .then(() => { throw new Error('Should have thrown') }) + .then(() => { + throw new Error('Should have thrown') + }) .catch((err) => { stdout = Stdout.capture() logger.error(err) + return snapshot( 'fails with no stderr', normalize(stdout.toString()) @@ -370,8 +390,10 @@ context('lib/tasks/verify', () => { it('logs error and exits when starting xvfb fails', () => { const err = new Error('test without xvfb') + err.stack = 'xvfb? no dice' xvfb.start.rejects(err) + return verify.start() .catch((err) => { expect(xvfb.stop).to.be.calledOnce @@ -408,8 +430,11 @@ context('lib/tasks/verify', () => { it('logs error when binary not found', () => { mockfs({}) + return verify.start() - .then(() => { throw new Error('Should have thrown') }) + .then(() => { + throw new Error('Should have thrown') + }) .catch((err) => { logger.error(err) snapshot( @@ -437,6 +462,7 @@ context('lib/tasks/verify', () => { '--smoke-test', '--ping=222', ]).resolves(spawnedProcess) + return verify.start() .then(() => { expect(util.exec.firstCall.args[0]).to.equal(realEnvBinaryPath) @@ -444,20 +470,24 @@ context('lib/tasks/verify', () => { }) }) - - ;['darwin', 'linux', 'win32'].forEach((platform) => it('can log error to user', () => { - process.env.CYPRESS_RUN_BINARY = '/custom/' - os.platform.returns(platform) - return verify.start() - .then(() => { throw new Error('Should have thrown') }) - .catch((err) => { - logger.error(err) - snapshot( - `${platform}: error when invalid CYPRESS_RUN_BINARY`, - normalize(stdout.toString()) - ) + ;['darwin', 'linux', 'win32'].forEach((platform) => { + return it('can log error to user', () => { + process.env.CYPRESS_RUN_BINARY = '/custom/' + os.platform.returns(platform) + + return verify.start() + .then(() => { + throw new Error('Should have thrown') + }) + .catch((err) => { + logger.error(err) + snapshot( + `${platform}: error when invalid CYPRESS_RUN_BINARY`, + normalize(stdout.toString()) + ) + }) }) - })) + }) }) }) @@ -484,6 +514,7 @@ function createfs ({ alreadyVerified, executable, packageVersion, customDir }) { mode: 0777, }) } + return mockfs(mockFiles) } diff --git a/cli/test/spec_helper.js b/cli/test/spec_helper.js index 7c3c6ef5091b..9ae94bb1e809 100644 --- a/cli/test/spec_helper.js +++ b/cli/test/spec_helper.js @@ -89,7 +89,7 @@ beforeEach(function () { }) afterEach(function () { + mockfs.restore() process.env = _.clone(env) sinon.restore() - mockfs.restore() }) diff --git a/cli/types/index.d.ts b/cli/types/index.d.ts index e29251778c8a..a970e9b6321c 100644 --- a/cli/types/index.d.ts +++ b/cli/types/index.d.ts @@ -4,7 +4,7 @@ // Mike Woudenberg // Robbert van Markus // Nicholas Boll -// TypeScript Version: 2.5 +// TypeScript Version: 2.8 // Updated by the Cypress team: https://www.cypress.io/about/ /// @@ -623,9 +623,11 @@ declare namespace Cypress { fixture(path: string, encoding: Encodings, options?: Partial): Chainable // no log? /** - * Get the DOM element that is currently focused. + * Focus on a DOM element. * * @see https://on.cypress.io/focus + * @example + * cy.get('input').first().focus() // Focus on the first input */ focus(options?: Partial): Chainable @@ -1879,6 +1881,9 @@ declare namespace Cypress { env: object } + /** + * Full set of possible options for cy.request call + */ interface RequestOptions extends Loggable, Timeoutable { auth: object body: RequestBody @@ -1888,7 +1893,7 @@ declare namespace Cypress { gzip: boolean headers: object method: HttpMethod - qs: string + qs: object url: string } @@ -1954,6 +1959,10 @@ declare namespace Cypress { interval: number } + /** + * Setting default options for cy.server() + * @see https://on.cypress.io/server + */ interface ServerOptions { delay: number method: HttpMethod @@ -1966,7 +1975,7 @@ declare namespace Cypress { enable: boolean force404: boolean urlMatchingOptions: object - whitelist(...args: any[]): void + whitelist(xhr: Request): void } interface SetCookieOptions extends Loggable, Timeoutable { @@ -3924,10 +3933,9 @@ declare namespace Cypress { left: number } - // Diff / Omit taken from https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-311923766 + // Diff taken from https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-311923766 type Diff = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T] - // @ts-ignore TODO - remove this if possible. Seems a recent change to TypeScript broke this. Possibly https://github.com/Microsoft/TypeScript/pull/17912 - type Omit = Pick> + type Omit = Pick> } /** diff --git a/cli/types/tests/kitchen-sink.ts b/cli/types/tests/kitchen-sink.ts index b24f676b6e2d..a70992f638ef 100644 --- a/cli/types/tests/kitchen-sink.ts +++ b/cli/types/tests/kitchen-sink.ts @@ -30,6 +30,13 @@ cy.visit('https://www.acme.com/', { } }) +const serverOptions: Partial = { + delay: 100, + whitelist: () => true +} + +cy.server(serverOptions) + Cypress.spec.name // $ExpectType string Cypress.spec.relative // $ExpectType string | null Cypress.spec.absolute // $ExpectType string | null @@ -55,6 +62,15 @@ cy.request({ body: {} }) +// specify query parameters +// https://github.com/cypress-io/cypress/issues/2305 +cy.request({ + url: "http://localhost:3000/myressource", + qs: { + param: 'someValue' + } +}) + // if you want a separate variable, you need specify its type // otherwise TSC does not cast string "POST" as HttpMethod // https://github.com/cypress-io/cypress/issues/2093 diff --git a/package.json b/package.json index d8a84ea96af9..073d02942c03 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "cypress", "productName": "Cypress", - "version": "3.1.3", + "version": "3.1.4", "description": "Cypress.io end to end testing tool", "private": true, "engines": { @@ -23,7 +23,7 @@ "decaffeinate-bulk": "bulk-decaffeinate", "check-deps": "node ./scripts/check-deps.js --verbose", "check-deps-pre": "node ./scripts/check-deps.js --verbose --prescript", - "prebuild": "npm run check-deps-pre", + "prebuild": "npm run check-deps-pre && npm run all prebuild", "build": "npm run all build", "all": "node ./scripts/run.js", "test": "echo '⚠️ This root monorepo is only for local development and new contributions. There are no tests.'", @@ -52,7 +52,9 @@ "test-scripts": "mocha --reporter spec scripts/unit/*spec.js", "test-mocha": "mocha --reporter spec scripts/spec.js", "test-mocha-snapshot": "mocha scripts/mocha-snapshot-spec.js", - "check-node-version": "node scripts/check-node-version.js" + "check-node-version": "node scripts/check-node-version.js", + "check-terminal": "node scripts/check-terminal.js", + "effective:circle:config": "circleci config process circle.yml | sed /^#/d" }, "lint-staged": { "*.js": [ @@ -109,7 +111,7 @@ "konfig": "^0.2.1", "lazy-ass": "^1.6.0", "lint-staged": "^4.1.3", - "lodash": "4.17.10", + "lodash": "4.17.11", "make-empty-github-commit": "^1.2.0", "mocha": "^3.5.0", "mocha-banner": "^1.1.1", diff --git a/packages/desktop-gui/cypress/fixtures/runs.json b/packages/desktop-gui/cypress/fixtures/runs.json index a13bb38ba256..4a0d9a51867c 100644 --- a/packages/desktop-gui/cypress/fixtures/runs.json +++ b/packages/desktop-gui/cypress/fixtures/runs.json @@ -4,20 +4,22 @@ "ci": { "buildNumber": "140", "provider": "circle", + "pullRequestId": "797", + "pullRequestUrl": "https://github.com/jane-lane/jekyl_blog/pull/797", "url": "https://circleci.com/gh/jekyl/jekyl_blog/140" }, + "ciBuildId": "circle-6443", "commit": { "authorEmail": "julie@devs.com", "authorName": "Julie Pearson", "branch": "search-todos", "message": "remove listings from search results on clear", - "pullRequestId": "797", - "pullRequestUrl": "https://github.com/jane-lane/jekyl_blog/pull/797", "sha": "f4b728bfcc61a1ea23d0f1ced676719550daae27", "url": "https://github.com/jekyl/jekyl_blog/commit/f4b728bfcc61a1ea23d0f1ced676719550daae27" }, "completedAt": null, "createdAt": "2016-05-13T02:35:12.748Z", + "customCiBuildId": false, "cypressVersion": "2.1.0", "totalDuration": null, "totalFailed": 0, @@ -138,9 +140,11 @@ { "buildNumber": 1892, "ci": null, + "ciBuildId": null, "commit": null, "completedAt": "2016-05-13T02:30:26.000Z", "createdAt": "2016-12-19T14:59:59.328Z", + "customCiBuildId": false, "cypressVersion": "2.1.0", "totalDuration": 16000, "totalFailed": 14, @@ -244,20 +248,23 @@ "ci": { "buildNumber": "1780", "provider": "circle", + "pullRequestId": "797", + "pullRequestUrl": "https://github.com/jane-lane/jekyl_blog/pull/797", "url": "https://circleci.com/gh/jane-lane/webAppOnline/1780" }, + "ciBuildId": "circle-job-123", "commit": { "authorEmail": "julie@devs.com", "authorName": "Julie Pearson", "branch": "search-todos", "message": "regex remove whitespace", - "pullRequestId": "797", - "pullRequestUrl": "https://github.com/jane-lane/jekyl_blog/pull/797", + "sha": "19550dacc61a1ea23d0f1ced676719550daae27", "url": "https://github.com/jane-lane/webAppOnline/commit/19550dacc61a1ea23d0f1ced676719550daae27" }, "completedAt": "2016-05-13T02:30:26.000Z", "createdAt": "2016-03-21T02:35:12.748Z", + "customCiBuildId": true, "cypressVersion": "2.1.0", "totalDuration": 1424424, "totalFailed": 0, @@ -286,20 +293,22 @@ "ci": { "buildNumber": "140", "provider": "circle", + "pullRequestId": "797", + "pullRequestUrl": "https://github.com/jane-lane/jekyl_blog/pull/797", "url": "https://circleci.com/gh/cypress-io/cypress-core-example/140" }, + "ciBuildId": "circle-6441", "commit": { "authorEmail": "julie@devs.com", "authorName": "Julie Pearson", "branch": "search-todos", "message": "remove listings from search results on clear", - "pullRequestId": "797", - "pullRequestUrl": "https://github.com/jane-lane/jekyl_blog/pull/797", "sha": "f4b728bfcc61a1ea23d0f1ced676719550daae27", "url": "https://github.com/jekyl/jekyl_blog/commit/f4b728bfcc61a1ea23d0f1ced676719550daae27" }, "completedAt": null, "createdAt": "2016-05-13T02:14:12.748Z", + "customCiBuildId": false, "cypressVersion": "2.1.0", "totalDuration": 0, "totalFailed": 0, @@ -366,20 +375,22 @@ "ci": { "buildNumber": "720", "provider": "circle", + "pullRequestId": "797", + "pullRequestUrl": "https://github.com/jane-lane/jekyl_blog/pull/797", "url": "https://circleci.com/gh/cypress-io/cypress-core-example/140" }, + "ciBuildId": "circle-6440", "commit": { "authorEmail": "julie@devs.com", "authorName": "Julie Pearson", "branch": "search-todos", "message": "remove listings from search results on clear", - "pullRequestId": "797", - "pullRequestUrl": "https://github.com/jane-lane/jekyl_blog/pull/797", "sha": "daae27cc61a1ea23d0f1ced676719550daae27", "url": "https://github.com/jane-lane/management-app/commit/daae27cc61a1ea23d0f1ced676719550daae27" }, "completedAt": "2016-05-13T02:35:12.748Z", "createdAt": "2015-08-21T02:35:12.748Z", + "customCiBuildId": false, "cypressVersion": "2.1.0", "totalDuration": 1424424, "totalFailed": 0, diff --git a/packages/desktop-gui/package.json b/packages/desktop-gui/package.json index 59c3cc8ba36c..792bd2ca9496 100644 --- a/packages/desktop-gui/package.json +++ b/packages/desktop-gui/package.json @@ -5,7 +5,7 @@ "private": true, "scripts": { "postinstall": "echo '@packages/desktop-gui needs: npm run build'", - "prebuild": "npm run check-deps-pre", + "prebuild": "npm run check-deps-pre && rebuild-node-sass", "build": "node ./scripts/build-dev.js", "prebuild-prod": "npm run check-deps-pre", "build-prod": "node ./scripts/build-prod.js", @@ -24,21 +24,21 @@ "lib" ], "devDependencies": { - "@babel/plugin-proposal-object-rest-spread": "7.0.0", + "@babel/plugin-proposal-object-rest-spread": "7.2.0", "@cypress/icons": "0.7.0", - "@cypress/json-schemas": "5.26.0", + "@cypress/json-schemas": "5.31.2", "@cypress/react-tooltip": "^0.2.2", "@cypress/releaser": "0.1.12", "bin-up": "^1.0.0", "bluebird": "^3.4.0", - "bootstrap-sass": "3.3.5", + "bootstrap-sass": "3.4.0", "classnames": "^2.2.5", "fira": "cypress-io/fira#fb63362742eea8cdce0d90825ab9264d77719e3d", "font-awesome": "4.7", "gravatar": "^1.6.0", "human-interval": "^0.1.6", "istanbul": "^0.4.3", - "lodash": "4.17.10", + "lodash": "4.17.11", "md5": "^2.1.0", "mobx": "^3.1.11", "mobx-react": "^4.2.1", @@ -47,6 +47,7 @@ "prop-types": "^15.5.10", "rc-collapse": "^1.6.11", "react": "^15.6.1", + "rebuild-node-sass": "1.1.0", "react-bootstrap-modal": "3.0.1", "react-dom": "^15.6.1", "react-loader": "^2.4.0", diff --git a/packages/driver/.eslintrc b/packages/driver/.eslintrc new file mode 100644 index 000000000000..555c3dbbf257 --- /dev/null +++ b/packages/driver/.eslintrc @@ -0,0 +1,5 @@ +{ + "env": { + "browser": true + }, +} diff --git a/packages/driver/src/cy/commands/actions/focus.coffee b/packages/driver/src/cy/commands/actions/focus.coffee index 7a0c57bf3c69..1c79bc6f5eaa 100644 --- a/packages/driver/src/cy/commands/actions/focus.coffee +++ b/packages/driver/src/cy/commands/actions/focus.coffee @@ -3,7 +3,7 @@ Promise = require("bluebird") $dom = require("../../../dom") $utils = require("../../../cypress/utils") -$elements = require("../../../dom/elements.coffee") +$elements = require("../../../dom/elements") $actionability = require("../../actionability") module.exports = (Commands, Cypress, cy, state, config) -> diff --git a/packages/driver/src/cy/commands/xhr.coffee b/packages/driver/src/cy/commands/xhr.coffee index fe5e43a524af..b3113d146d62 100644 --- a/packages/driver/src/cy/commands/xhr.coffee +++ b/packages/driver/src/cy/commands/xhr.coffee @@ -12,10 +12,6 @@ server = null getServer = -> server ? unavailableErr() -abort = -> - if server - server.abort() - reset = -> if server server.restore() @@ -221,13 +217,6 @@ defaults = { module.exports = (Commands, Cypress, cy, state, config) -> reset() - ## if our page is going away due to - ## a form submit / anchor click then - ## we need to cancel all outstanding - ## XHR's so the command log displays - ## correctly - Cypress.on("window:unload", abort) - Cypress.on "test:before:run", -> ## reset the existing server reset() diff --git a/packages/driver/src/cypress/server.coffee b/packages/driver/src/cypress/server.coffee index 2b2f34363198..ce57d3eaf2ac 100644 --- a/packages/driver/src/cypress/server.coffee +++ b/packages/driver/src/cypress/server.coffee @@ -26,6 +26,13 @@ normalize = (val) -> nope = -> return null +## when the browser naturally cancels/aborts +## an XHR because the window is unloading +isAbortedThroughUnload = (xhr) -> + xhr.readyState is 4 and + xhr.status is 0 and + xhr.responseText is "" + warnOnStubDeprecation = (obj, type) -> if _.has(obj, "stub") $utils.warning(""" @@ -296,39 +303,56 @@ create = (options = {}) -> abort = XHR.prototype.abort srh = XHR.prototype.setRequestHeader - restoreFn = -> - ## restore the property back on the window - _.each {send: send, open: open, abort: abort, setRequestHeader: srh}, (value, key) -> - XHR.prototype[key] = value - - XHR.prototype.setRequestHeader = -> - proxy = server.getProxyFor(@) + abortXhr = (xhr) -> + proxy = server.getProxyFor(xhr) - proxy._setRequestHeader.apply(proxy, arguments) + ## if the XHR leaks into the next test + ## after we've reset our internal server + ## then this may be undefined + return if not proxy - srh.apply(@, arguments) + ## return if we're already aborted which + ## can happen if the browser already canceled + ## this xhr but we called abort later + return if xhr.aborted - XHR.prototype.abort = -> - ## if we already have a readyState of 4 - ## then do not get the abort stack or - ## set the aborted property or call onXhrAbort - ## to test this just use a regular XHR - @aborted = true + xhr.aborted = true abortStack = server.getStack() - proxy = server.getProxyFor(@) proxy.aborted = true options.onXhrAbort(proxy, abortStack) if _.isFunction(options.onAnyAbort) - route = server.getRouteForXhr(@) + route = server.getRouteForXhr(xhr) ## call the onAnyAbort function ## after we've called options.onSend options.onAnyAbort(route, proxy) + restoreFn = -> + ## restore the property back on the window + _.each {send: send, open: open, abort: abort, setRequestHeader: srh}, (value, key) -> + XHR.prototype[key] = value + + XHR.prototype.setRequestHeader = -> + ## if the XHR leaks into the next test + ## after we've reset our internal server + ## then this may be undefined + if proxy = server.getProxyFor(@) + proxy._setRequestHeader.apply(proxy, arguments) + + srh.apply(@, arguments) + + XHR.prototype.abort = -> + ## if we already have a readyState of 4 + ## then do not get the abort stack or + ## set the aborted property or call onXhrAbort + ## to test this just use a regular XHR + if @readyState isnt 4 + abortXhr(@) + abort.apply(@, arguments) XHR.prototype.open = (method, url, async = true, username, password) -> @@ -407,6 +431,9 @@ create = (options = {}) -> ## catch synchronous errors caused ## by the onreadystatechange function try + if isAbortedThroughUnload(xhr) + abortXhr(xhr) + if _.isFunction(orst = fns.onreadystatechange) orst.apply(xhr, arguments) catch err diff --git a/packages/driver/src/cypress/utils.coffee b/packages/driver/src/cypress/utils.coffee index 2ffb5c277a09..9ad1c7307f2e 100644 --- a/packages/driver/src/cypress/utils.coffee +++ b/packages/driver/src/cypress/utils.coffee @@ -43,6 +43,16 @@ module.exports = { return item + switchCase: (value, casesObj, defaultKey = "default") -> + if _.has(casesObj, value) + return _.result(casesObj, value) + + if _.has(casesObj, defaultKey) + return _.result(casesObj, defaultKey) + + keys = _.keys(casesObj) + throw new Error("The switch/case value: '#{value}' did not match any cases: #{keys.join(', ')}.") + appendErrMsg: (err, message) -> ## preserve stack ## this is the critical part diff --git a/packages/driver/test/cypress/fixtures/dom.html b/packages/driver/test/cypress/fixtures/dom.html index 693dea69cb85..68cf6112b944 100644 --- a/packages/driver/test/cypress/fixtures/dom.html +++ b/packages/driver/test/cypress/fixtures/dom.html @@ -478,6 +478,16 @@
  • baz
  • quux
  • + + + +
    diff --git a/packages/driver/test/cypress/integration/commands/actions/click_spec.coffee b/packages/driver/test/cypress/integration/commands/actions/click_spec.coffee index 208c97fad149..4b043298831f 100644 --- a/packages/driver/test/cypress/integration/commands/actions/click_spec.coffee +++ b/packages/driver/test/cypress/integration/commands/actions/click_spec.coffee @@ -420,6 +420,10 @@ describe "src/cy/commands/actions/click", -> expect(onClick).to.be.calledOnce describe "actionability", -> + + it 'can click on inline elements that wrap lines', -> + cy.get('#overflow-link').find('.wrapped').click() + it "can click elements which are hidden until scrolled within parent container", -> cy.get("#overflow-auto-container").contains("quux").click() diff --git a/packages/driver/test/cypress/integration/commands/xhr_spec.coffee b/packages/driver/test/cypress/integration/commands/xhr_spec.coffee index 732ef70f142b..9dce4a61c42c 100644 --- a/packages/driver/test/cypress/integration/commands/xhr_spec.coffee +++ b/packages/driver/test/cypress/integration/commands/xhr_spec.coffee @@ -1843,6 +1843,62 @@ describe "src/cy/commands/xhr", -> _.each xhrs, (xhr) -> expect(xhr.aborted).not.to.be.false + it "aborts xhrs that haven't been sent", -> + cy + .window() + .then (win) -> + xhr = new win.XMLHttpRequest() + xhr.open("GET", "/timeout?ms=0") + xhr.abort() + + expect(xhr.aborted).to.be.true + + it "aborts xhrs currently in flight", -> + log = null + + cy.on "log:changed", (attrs, l) => + if attrs.name is "xhr" + log = l + + cy + .window() + .then (win) -> + xhr = new win.XMLHttpRequest() + xhr.open("GET", "/timeout?ms=1000") + xhr.send() + xhr.abort() + + cy.wrap(null).should -> + expect(log.get("state")).to.eq("failed") + expect(xhr.aborted).to.be.true + + ## https://github.com/cypress-io/cypress/issues/1652 + it "does not set aborted on XHR's that have completed by have had .abort() called", -> + log = null + + cy.on "log:changed", (attrs, l) => + if attrs.name is "xhr" + log = l + + cy + .window() + .then (win) -> + new Promise (resolve) -> + xhr = new win.XMLHttpRequest() + xhr.open("GET", "/timeout?ms=0") + xhr.onload = -> + xhr.abort() + xhr.foo = "bar" + resolve(xhr) + xhr.send() + .then (xhr) -> + ## ensure this is set to prevent accidental + ## race conditions down the road if something + ## goes wrong + expect(xhr.foo).to.eq("bar") + expect(xhr.aborted).not.to.be.true + expect(log.get("state")).to.eq("passed") + context "Cypress.on(window:unload)", -> it "aborts all open XHR's", -> xhrs = [] diff --git a/packages/driver/test/cypress/integration/dom/coordinates_spec.coffee b/packages/driver/test/cypress/integration/dom/coordinates_spec.coffee index 5a3f783e858d..a974aae98541 100644 --- a/packages/driver/test/cypress/integration/dom/coordinates_spec.coffee +++ b/packages/driver/test/cypress/integration/dom/coordinates_spec.coffee @@ -32,12 +32,12 @@ describe "src/dom/coordinates", -> value: 20 }) - cy.stub(@$button.get(0), "getBoundingClientRect").returns({ + cy.stub(@$button.get(0), "getClientRects").returns([{ top: 100.9 left: 60.9 width: 50 height: 40 - }) + }]) { fromViewport, fromWindow } = Cypress.dom.getElementPositioning(@$button) @@ -154,3 +154,36 @@ describe "src/dom/coordinates", -> ## padding is added to the line-height but width includes the padding expect(obj.x).to.eq(159) expect(obj.y).to.eq(124) + + context "span spanning multiple lines", -> + it 'gets first dom rect in multiline text', -> + $ ' +
    + this is some long text with a single span that spans lines making it tricky to click +
    + ' + .appendTo $ 'body' + + $el = cy.$$("#multiple") + el = $el[0] + + cy.stub(el, 'getClientRects', -> + [ + { + top: 100 + left: 100 + width: 50 + height: 40 + }, + { + top: 200 + left: 50 + width: 10 + height: 10 + } + ] + + ).as 'getClientRects' + obj = Cypress.dom.getElementCoordinatesByPosition($el, 'center').fromViewport + + expect({x: obj.x, y: obj.y}).to.deep.eq({x:125, y:120}) diff --git a/packages/driver/test/cypress/integration/issues/761_2968_spec.js b/packages/driver/test/cypress/integration/issues/761_2968_spec.js new file mode 100644 index 000000000000..c04ab38da183 --- /dev/null +++ b/packages/driver/test/cypress/integration/issues/761_2968_spec.js @@ -0,0 +1,111 @@ +// https://github.com/cypress-io/cypress/issues/761 +describe('issue #761 - aborted XHRs from previous tests', () => { + context('aborted when complete', () => { + it('test 1 dispatches xhr, but completes in test 2', () => { + cy.window().then((win) => { + const xhr = new win.XMLHttpRequest() + + xhr.open('GET', '/timeout?ms=1000') + xhr.onload = () => { + // we are in test 2 at this point + // and should not throw + xhr.abort() + } + xhr.send() + }) + }) + + it('test 2 aborts the completed XHR', () => { + cy.wait(2000) + }) + }) + + context('aborted before complete', () => { + let xhr = null + + // TODO: we lose a reference here to the xhr in test 2 + // so it shows up as "pending" forever because we reset + // the proxied XHR's as references when the next test starts + it('test 1 dispatches xhr, but completes in test 2', () => { + cy.window().then((win) => { + xhr = new win.XMLHttpRequest() + + xhr.open('GET', '/timeout?ms=1000') + xhr.send() + }) + }) + + it('test 2 aborts the incomplete XHR which is currently in flight', () => { + // we are in test 2 at this point + // and should not throw when we + // abort the incomplete xhr + expect(xhr.aborted).not.to.be.true + + xhr.abort() + }) + }) +}) + +// this tests that XHR references are blown away +// and no longer invoked when unloading the window +// and that its unnecessary to abort them +// https://github.com/cypress-io/cypress/issues/2968 +describe('issue #2968 - unloaded xhrs do not need to be aborted', () => { + it('let the browser naturally abort requests without manual intervention on unload', () => { + let xhr + let log + + const stub = cy.stub() + + cy.on('log:changed', (attrs, l) => { + if (attrs.name === 'xhr') { + log = l + } + }) + + cy + .visit('http://localhost:3500/fixtures/generic.html') + .window() + .then((win) => { + return new Promise((resolve, reject) => { + xhr = new win.XMLHttpRequest() + + win.XMLHttpRequest.prototype.abort = stub + + xhr.open('GET', '/timeout?ms=1000') + xhr.abort = stub // this should not get called + xhr.onerror = stub // this should not fire + xhr.onload = stub // this should not fire + xhr.onreadystatechange = () => { + if (xhr.readyState === 4) { + try { + // the browser should naturally + // abort / cancel this request when + // the unload event is called which + // should cause this xhr to have + // these properties and be displayed + // correctly in the Cypress Command Log + expect(xhr.aborted).to.be.true + expect(xhr.readyState).to.eq(4) + expect(xhr.status).to.eq(0) + expect(xhr.responseText).to.eq('') + } catch (err) { + reject(err) + } + + resolve() + } + } + + xhr.send() + + win.location.href = 'about:blank' + }) + }) + .wrap(null) + .should(() => { + expect(stub).not.to.be.called + expect(log.get('state')).to.eq('failed') + }) + }) +}) diff --git a/packages/electron/package.json b/packages/electron/package.json index 01818f319a45..05433a333925 100644 --- a/packages/electron/package.json +++ b/packages/electron/package.json @@ -29,12 +29,12 @@ "mocha": "^3.0.2" }, "dependencies": { - "@cypress/icons": "^0.6.0", - "bluebird": "^3.4.1", - "debug": "^3.0.1", + "@cypress/icons": "0.6.0", + "bluebird": "3.5.3", + "debug": "3.2.6", "electron-packager": "9.0.1", - "fs-extra": "^0.30.0", - "lodash": "^4.15.0", - "minimist": "^1.2.0" + "fs-extra": "0.30.0", + "lodash": "4.17.11", + "minimist": "1.2.0" } } diff --git a/packages/example/package.json b/packages/example/package.json index 37cd68446678..cd33f362db6d 100644 --- a/packages/example/package.json +++ b/packages/example/package.json @@ -22,8 +22,8 @@ "lib" ], "dependencies": { - "bluebird": "^3.5.1", - "glob": "^7.1.2" + "bluebird": "3.5.3", + "glob": "7.1.3" }, "devDependencies": { "bin-up": "^1.1.0", diff --git a/packages/extension/package.json b/packages/extension/package.json index d49632115447..f3436a81d956 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -46,7 +46,7 @@ "vinyl-source-stream": "^1.1.0" }, "dependencies": { - "bluebird": "^3.3.5", - "lodash": "^4.11.2" + "bluebird": "3.5.3", + "lodash": "4.17.11" } } diff --git a/packages/https-proxy/package.json b/packages/https-proxy/package.json index 8c74e45cb9b2..fe744fdcef5a 100644 --- a/packages/https-proxy/package.json +++ b/packages/https-proxy/package.json @@ -33,13 +33,13 @@ "supertest-as-promised": "^3.1.0" }, "dependencies": { - "bluebird": "^3.4.0", - "debug": "^2.6.8", - "fs-extra": "^0.30.0", + "bluebird": "3.5.3", + "debug": "2.6.9", + "fs-extra": "0.30.0", "lodash": "4.17.11", - "node-forge": "^0.6.39", - "semaphore": "^1.0.5", + "node-forge": "0.6.49", + "semaphore": "1.1.0", "server-destroy-vvo": "1.0.1", - "ssl-root-cas": "^1.1.10" + "ssl-root-cas": "1.2.5" } } diff --git a/packages/launcher/package.json b/packages/launcher/package.json index ba088b3a9ffd..b6493699687b 100644 --- a/packages/launcher/package.json +++ b/packages/launcher/package.json @@ -28,7 +28,7 @@ "@cypress/releaser": "0.1.12", "@types/bluebird": "3.5.21", "@types/chai": "^3.5.2", - "@types/debug": "0.0.29", + "@types/debug": "0.0.31", "@types/execa": "^0.7.0", "@types/fs-extra": "3.0.0", "@types/lodash": "^4.14.64", @@ -46,13 +46,13 @@ "typescript": "2.9.2" }, "dependencies": { - "bluebird": "^3.5.0", - "debug": "^2.6.6", - "execa": "^0.6.3", - "fs-extra": "^3.0.0", - "lodash": "^4.11.1", - "plist": "^2.1.0", - "pluralize": "^7.0.0", - "ramda": "^0.24.1" + "bluebird": "3.5.3", + "debug": "2.6.9", + "execa": "0.6.3", + "fs-extra": "3.0.1", + "lodash": "4.17.11", + "plist": "2.1.0", + "pluralize": "7.0.0", + "ramda": "0.24.1" } } diff --git a/packages/reporter/package.json b/packages/reporter/package.json index e98b8e184e96..f17a0fcfd6ff 100644 --- a/packages/reporter/package.json +++ b/packages/reporter/package.json @@ -25,17 +25,17 @@ "dist" ], "devDependencies": { - "@babel/plugin-proposal-object-rest-spread": "7.0.0", + "@babel/plugin-proposal-object-rest-spread": "7.2.0", "@cypress/react-tooltip": "0.4.0", "@cypress/releaser": "0.1.12", "bin-up": "1.1.0", "chai": "3.5.0", "chai-enzyme": "1.0.0-beta.1", "classnames": "2.2.6", - "css-element-queries": "0.3.2", + "css-element-queries": "0.4.0", "enzyme": "3.7.0", - "enzyme-adapter-react-16": "1.6.0", - "font-awesome": "4.6.3", + "enzyme-adapter-react-16": "1.7.1", + "font-awesome": "4.7.0", "jsdom": "9.4.1", "lodash": "4.17.11", "markdown-it": "6.1.1", diff --git a/packages/runner/package.json b/packages/runner/package.json index a6f5f7f13c94..cda7717d5207 100644 --- a/packages/runner/package.json +++ b/packages/runner/package.json @@ -5,7 +5,7 @@ "private": true, "scripts": { "postinstall": "echo '@packages/runner needs: npm run build'", - "prebuild": "npm run check-deps-pre rebuild-node-sass", + "prebuild": "npm run check-deps-pre && rebuild-node-sass", "build": "node ./scripts/build-dev.js", "prebuild-prod": "npm run check-deps-pre", "build-prod": "node ./scripts/build-prod.js", @@ -24,7 +24,7 @@ "lib" ], "devDependencies": { - "@babel/plugin-proposal-object-rest-spread": "7.0.0", + "@babel/plugin-proposal-object-rest-spread": "7.2.0", "@cypress/react-tooltip": "0.4.0", "@cypress/releaser": "0.1.12", "bin-up": "1.1.0", @@ -33,8 +33,8 @@ "chai-enzyme": "1.0.0-beta.1", "classnames": "2.2.6", "enzyme": "3.7.0", - "enzyme-adapter-react-16": "1.6.0", - "font-awesome": "4.6.3", + "enzyme-adapter-react-16": "1.7.1", + "font-awesome": "4.7.0", "jsdom": "9.4.1", "lodash": "4.17.11", "mobx": "3.1.15", diff --git a/packages/server/lib/exception.coffee b/packages/server/lib/exception.coffee index a8b3f09a2e55..fde4079619de 100644 --- a/packages/server/lib/exception.coffee +++ b/packages/server/lib/exception.coffee @@ -2,6 +2,7 @@ _ = require("lodash") Promise = require("bluebird") winston = require("winston") pkg = require("@packages/root") +path = require("path") api = require("./api") user = require("./user") @@ -10,11 +11,12 @@ system = require("./util/system") ## strip everything but the file name to remove any sensitive ## data in the path -pathRe = /'?((\/|\\|[a-z]:\\)[^\s']+)+'?/ig +pathRe = /'?((\/|\\+|[a-z]:\\)[^\s']+)+'?/ig +pathSepRe = /[\/\\]+/ fileNameRe = /[^\s'/]+\.\w+:?\d*$/i stripPath = (text) -> (text or "").replace pathRe, (path) -> - fileName = _.last(path.split("/")) or "" + fileName = _.last(path.split(pathSepRe)) or "" "#{fileName}" ## POST https://api.cypress.io/exceptions diff --git a/packages/server/package.json b/packages/server/package.json index ee6e52ee515c..a54d4745a094 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -46,14 +46,14 @@ "lib" ], "devDependencies": { - "@babel/core": "7.1.0", - "@babel/plugin-proposal-class-properties": "7.1.0", - "@babel/plugin-proposal-object-rest-spread": "7.0.0", - "@babel/plugin-transform-runtime": "7.1.0", - "@babel/preset-env": "7.1.0", + "@babel/core": "7.2.2", + "@babel/plugin-proposal-class-properties": "7.2.3", + "@babel/plugin-proposal-object-rest-spread": "7.2.0", + "@babel/plugin-transform-runtime": "7.2.0", + "@babel/preset-env": "7.2.3", "@babel/preset-react": "7.0.0", - "@babel/runtime": "7.0.0", - "@cypress/json-schemas": "5.27.0", + "@babel/runtime": "7.2.0", + "@cypress/json-schemas": "5.31.2", "@cypress/sinon-chai": "^1.1.0", "babel-plugin-add-module-exports": "^1.0.0", "babelify": "10.0.0", @@ -73,6 +73,7 @@ "https-proxy-agent": "^1.0.0", "inquirer": "3.0.6", "istanbul": "^0.4.2", + "mocked-env": "1.2.4", "mockery": "^1.4.0", "nock": "9.0.22", "nodemon": "^1.8.7", @@ -97,101 +98,101 @@ }, "dependencies": { "@cypress/browserify-preprocessor": "1.1.2", - "@cypress/commit-info": "2.0.0", + "@cypress/commit-info": "2.1.1", "@cypress/icons": "0.5.4", - "@cypress/mocha-teamcity-reporter": "^1.0.0", + "@cypress/mocha-teamcity-reporter": "1.0.0", "@ffmpeg-installer/ffmpeg": "1.0.15", - "ansi_up": "^1.3.0", + "ansi_up": "1.3.0", "bluebird": "3.4.7", - "browserify": "^13.1.1", - "chai": "^1.9.2", - "chalk": "^2.4.1", - "check-more-types": "^2.24.0", + "browserify": "13.3.0", + "chai": "1.10.0", + "chalk": "2.4.1", + "check-more-types": "2.24.0", "chokidar": "1.6.0", - "cjsxify": "^0.3.0", - "clear-module": "^2.1.0", - "cli-table2": "^0.2.0", - "color-string": "^1.5.2", - "common-tags": "^1.8.0", + "cjsxify": "0.3.0", + "clear-module": "2.1.0", + "cli-table2": "0.2.0", + "color-string": "1.5.3", + "common-tags": "1.8.0", "compression": "1.7.2", - "concat-stream": "^1.5.1", - "content-type": "^1.0.2", - "cookie": "^0.2.3", - "cookie-parser": "^1.3.3", + "concat-stream": "1.6.2", + "content-type": "1.0.4", + "cookie": "0.2.4", + "cookie-parser": "1.4.3", "data-uri-to-buffer": "0.0.4", - "debug": "^2.6.8", - "dependency-tree": "^6.0.1", - "electron-context-menu": "^0.8.0", + "debug": "2.6.9", + "dependency-tree": "6.4.0", + "electron-context-menu": "0.8.0", "electron-positioner": "3.0.0", "errorhandler": "1.1.1", - "evil-dns": "^0.2.0", - "execa": "^0.8.0", + "evil-dns": "0.2.0", + "execa": "0.8.0", "express": "4.16.2", - "find-process": "^1.1.1", - "fluent-ffmpeg": "^2.1.0", + "find-process": "1.2.1", + "fluent-ffmpeg": "2.1.2", "fs-extra": "4.0.3", - "getos": "^2.8.2", + "getos": "2.8.4", "glob": "7.1.2", - "graceful-fs": "^4.1.11", - "gulp-util": "^3.0.6", + "graceful-fs": "4.1.15", + "gulp-util": "3.0.8", "hbs": "4.0.0", - "http-accept": "^0.1.6", + "http-accept": "0.1.6", "http-proxy": "1.17.0", - "http-status-codes": "^1.0.6", - "human-interval": "^0.1.5", - "image-size": "^0.5.0", + "http-status-codes": "1.3.0", + "human-interval": "0.1.6", + "image-size": "0.5.5", "is-fork-pr": "2.0.0", - "jimp": "^0.2.28", - "jsonlint": "^1.6.2", - "konfig": "^0.2.0", - "lazy-ass": "^1.6.0", - "lockfile": "^1.0.3", + "jimp": "0.2.28", + "jsonlint": "1.6.3", + "konfig": "0.2.1", + "lazy-ass": "1.6.0", + "lockfile": "1.0.4", "lodash": "4.17.4", - "log-symbols": "^2.2.0", - "md5": "^2.2.1", - "method-override": "^2.3.1", + "log-symbols": "2.2.0", + "md5": "2.2.1", + "method-override": "2.3.10", "mime": "1.2.11", - "minimatch": "^3.0.0", - "minimist": "^1.1.2", + "minimatch": "3.0.4", + "minimist": "1.2.0", "mocha": "2.4.5", "mocha-junit-reporter": "1.17.0", - "moment": "^2.14.1", + "moment": "2.23.0", "morgan": "1.3.0", - "node-machine-id": "^1.1.4", + "node-machine-id": "1.1.10", "node-uuid": "1.4.1", "node-webkit-updater": "cypress-io/node-webkit-updater#e74623726f381487f543e373e71515177a32daeb", "opn": "cypress-io/opn#2f4e9a216ca7bdb95dfae9d46d99ddf004b3cbb5", - "ospath": "^1.1.0", - "p-queue": "^1.0.0", + "ospath": "1.2.2", + "p-queue": "1.2.0", "parse-domain": "2.0.0", - "pluralize": "^3.0.0", + "pluralize": "3.1.0", "pumpify": "1.5.1", - "ramda": "^0.24.0", - "randomstring": "^1.1.5", - "replacestream": "^4.0.3", + "ramda": "0.24.1", + "randomstring": "1.1.5", + "replacestream": "4.0.3", "request": "2.88.0", "request-promise": "4.1.1", - "return-deep-diff": "^0.2.9", - "sanitize-filename": "^1.6.1", - "semver": "^5.3.0", - "send": "^0.14.1", + "return-deep-diff": "0.2.9", + "sanitize-filename": "1.6.1", + "semver": "5.6.0", + "send": "0.14.2", "server-destroy": "1.0.1", - "shell-env": "^0.3.0", - "signal-exit": "^3.0.2", - "sinon": "^5.0.0", - "string-to-stream": "^1.0.1", - "strip-ansi": "^3.0.1", - "supports-color": "^5.1.0", - "syntax-error": "^1.1.4", - "tar-fs": "^1.11.1", - "term-size": "^1.2.0", + "shell-env": "0.3.0", + "signal-exit": "3.0.2", + "sinon": "5.1.1", + "string-to-stream": "1.1.1", + "strip-ansi": "3.0.1", + "supports-color": "5.5.0", + "syntax-error": "1.4.0", + "tar-fs": "1.16.3", + "term-size": "1.2.0", "through": "2.3.6", "tough-cookie": "2.4.3", "trash": "4.0.0", - "underscore": "^1.8.3", + "underscore": "1.9.1", "underscore.string": "3.3.4", - "url-parse": "^1.1.7", - "widest-line": "^2.0.0", - "winston": "^0.9.0" + "url-parse": "1.4.4", + "widest-line": "2.0.1", + "winston": "0.9.0" } } diff --git a/packages/server/test/scripts/run.js b/packages/server/test/scripts/run.js index 5a16920e6293..c09ec45f2465 100644 --- a/packages/server/test/scripts/run.js +++ b/packages/server/test/scripts/run.js @@ -10,7 +10,7 @@ const options = minimist(process.argv.slice(2)) let run = options._[0] -if (run.includes('--inspect-brk')) { +if (run && run.includes('--inspect-brk')) { run = options._[1] } diff --git a/packages/server/test/support/fixtures/projects/e2e/cypress/integration/xhr_spec.coffee b/packages/server/test/support/fixtures/projects/e2e/cypress/integration/xhr_spec.coffee index 5165968fc0d8..822dee769ba3 100644 --- a/packages/server/test/support/fixtures/projects/e2e/cypress/integration/xhr_spec.coffee +++ b/packages/server/test/support/fixtures/projects/e2e/cypress/integration/xhr_spec.coffee @@ -100,16 +100,18 @@ describe "xhrs", -> it "aborts", -> cy - .route({ - method: "POST", - url: /users/, - response: {name: "b"}, - delay: 200 - }).as("createUser") - .get("#create").click() - .then -> - ## simulate an open request which should become - ## aborted due to window:unload event - Cypress.action("app:window:unload", {}) + .window() + .then (win) -> + cy + .route({ + method: "POST", + url: /users/, + response: {name: "b"}, + delay: 2000 + }) + .as("createUser") + .get("#create").click() + .then -> + win.location.href = '/index.html' - .wait("@createUser").its("aborted").should("be.true") + .wait("@createUser").its("aborted").should("be.true") diff --git a/packages/server/test/unit/ci_provider_spec.coffee b/packages/server/test/unit/ci_provider_spec.coffee index bb23d19906d1..f4a0e40b02ee 100644 --- a/packages/server/test/unit/ci_provider_spec.coffee +++ b/packages/server/test/unit/ci_provider_spec.coffee @@ -1,4 +1,5 @@ R = require("ramda") +mockedEnv = require("mocked-env") require("../spec_helper") ciProvider = require("#{root}lib/util/ci_provider") @@ -15,36 +16,59 @@ expectsCommitParams = (params) -> expectsCommitDefaults = (existing, expected) -> expect(ciProvider.commitDefaults(existing), "CI providers default git params").to.deep.eq(expected) -resetEnv = -> - process.env = {} - describe "lib/util/ci_provider", -> - beforeEach -> - resetEnv() + resetEnv = null + + afterEach -> + # we need to reset environment + # to avoid affecting tests in other suites + resetEnv?() it "null when unknown", -> - resetEnv() + resetEnv = mockedEnv({}, {clear: true}) expectsName(null) expectsCiParams(null) expectsCommitParams(null) + it "does not extract from commit environment variables yet", -> + # see fallback environment variables + # https://github.com/cypress-io/commit-info#fallback-environment-variables + # BUT those defaults are NOT used by "ci_provider" + # instead they are used in the "record" module + # this test just confirms that these defaults are not considered + env = { + COMMIT_INFO_BRANCH: "my-branch-221", + COMMIT_INFO_MESSAGE: "best commit ever", + COMMIT_INFO_EMAIL: "user@company.com", + COMMIT_INFO_AUTHOR: "Agent Smith", + COMMIT_INFO_SHA: "0123456", + COMMIT_INFO_REMOTE: "remote repo" + } + resetEnv = mockedEnv(env, {clear: true}) + + expectsName(null) # we don't know CI + expectsCiParams(null) # we don't know CI params + expectsCommitParams(null) # we don't know CI-specific params + it "appveyor", -> - process.env.APPVEYOR = true - - process.env.APPVEYOR_JOB_ID = "appveyorJobId2" - process.env.APPVEYOR_ACCOUNT_NAME = "appveyorAccountName" - process.env.APPVEYOR_PROJECT_SLUG = "appveyorProjectSlug" - process.env.APPVEYOR_BUILD_VERSION = "appveyorBuildVersion" - process.env.APPVEYOR_BUILD_NUMBER = "appveyorBuildNumber" - process.env.APPVEYOR_PULL_REQUEST_NUMBER = "appveyorPullRequestNumber" - process.env.APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH = "appveyorPullRequestHeadRepoBranch" - - process.env.APPVEYOR_REPO_COMMIT = "repoCommit" - process.env.APPVEYOR_REPO_COMMIT_MESSAGE = "repoCommitMessage" - process.env.APPVEYOR_REPO_BRANCH = "repoBranch" - process.env.APPVEYOR_REPO_COMMIT_AUTHOR = "repoCommitAuthor" - process.env.APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL = "repoCommitAuthorEmail" + resetEnv = mockedEnv({ + APPVEYOR: "true" + + APPVEYOR_JOB_ID: "appveyorJobId2" + APPVEYOR_ACCOUNT_NAME: "appveyorAccountName" + APPVEYOR_PROJECT_SLUG: "appveyorProjectSlug" + APPVEYOR_BUILD_VERSION: "appveyorBuildVersion" + APPVEYOR_BUILD_NUMBER: "appveyorBuildNumber" + APPVEYOR_PULL_REQUEST_NUMBER: "appveyorPullRequestNumber" + APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH: "appveyorPullRequestHeadRepoBranch" + + APPVEYOR_REPO_COMMIT: "repoCommit" + APPVEYOR_REPO_COMMIT_MESSAGE: "repoCommitMessage" + APPVEYOR_REPO_BRANCH: "repoBranch" + APPVEYOR_REPO_COMMIT_AUTHOR: "repoCommitAuthor" + APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL: "repoCommitAuthorEmail" + }, {clear: true}) expectsName("appveyor") expectsCiParams({ @@ -66,22 +90,26 @@ describe "lib/util/ci_provider", -> resetEnv() - process.env.APPVEYOR = true - process.env.APPVEYOR_REPO_COMMIT_MESSAGE = "repoCommitMessage" - process.env.APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED = "repoCommitMessageExtended" + resetEnv = mockedEnv({ + APPVEYOR: "true" + APPVEYOR_REPO_COMMIT_MESSAGE: "repoCommitMessage" + APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED: "repoCommitMessageExtended" + }, {clear: true}) expectsCommitParams({ message: "repoCommitMessage\nrepoCommitMessageExtended" }) it "bamboo", -> - process.env["bamboo.buildNumber"] = "123" + resetEnv = mockedEnv({ + "bamboo.buildNumber": "123" - process.env["bamboo.resultsUrl"] = "bamboo.resultsUrl" - process.env["bamboo.buildResultsUrl"] = "bamboo.buildResultsUrl" - process.env["bamboo.planRepository.repositoryUrl"] = "bamboo.planRepository.repositoryUrl" + "bamboo.resultsUrl": "bamboo.resultsUrl" + "bamboo.buildResultsUrl": "bamboo.buildResultsUrl" + "bamboo.planRepository.repositoryUrl": "bamboo.planRepository.repositoryUrl" - process.env["bamboo.planRepository.branch"] = "bamboo.planRepository.branch" + "bamboo.planRepository.branch": "bamboo.planRepository.branch" + }, {clear: true}) expectsName("bamboo") expectsCiParams({ @@ -95,16 +123,18 @@ describe "lib/util/ci_provider", -> }) it "bitbucket", -> - process.env.CI = "1" + resetEnv = mockedEnv({ + CI: "1" - # build information - process.env.BITBUCKET_BUILD_NUMBER = "bitbucketBuildNumber" - process.env.BITBUCKET_REPO_OWNER = "bitbucketRepoOwner" - process.env.BITBUCKET_REPO_SLUG = "bitbucketRepoSlug" + # build information + BITBUCKET_BUILD_NUMBER: "bitbucketBuildNumber" + BITBUCKET_REPO_OWNER: "bitbucketRepoOwner" + BITBUCKET_REPO_SLUG: "bitbucketRepoSlug" - # git information - process.env.BITBUCKET_COMMIT = "bitbucketCommit" - process.env.BITBUCKET_BRANCH = "bitbucketBranch" + # git information + BITBUCKET_COMMIT: "bitbucketCommit" + BITBUCKET_BRANCH: "bitbucketBranch" + }, {clear: true}) expectsName("bitbucket") expectsCiParams({ @@ -125,25 +155,26 @@ describe "lib/util/ci_provider", -> }) it "buildkite", -> - process.env.BUILDKITE = true - - process.env.BUILDKITE_REPO = "buildkiteRepo" - process.env.BUILDKITE_JOB_ID = "buildkiteJobId" - process.env.BUILDKITE_SOURCE = "buildkiteSource" - process.env.BUILDKITE_BUILD_ID = "buildkiteBuildId" - process.env.BUILDKITE_BUILD_URL = "buildkiteBuildUrl" - process.env.BUILDKITE_BUILD_NUMBER = "buildkiteBuildNumber" - process.env.BUILDKITE_PULL_REQUEST = "buildkitePullRequest" - process.env.BUILDKITE_PULL_REQUEST_REPO = "buildkitePullRequestRepo" - process.env.BUILDKITE_PULL_REQUEST_BASE_BRANCH = "buildkitePullRequestBaseBranch" - - process.env.BUILDKITE_COMMIT = "buildKiteCommit" - process.env.BUILDKITE_BRANCH = "buildKiteBranch" - process.env.BUILDKITE_MESSAGE = "buildKiteMessage" - process.env.BUILDKITE_BUILD_CREATOR = "buildKiteBuildCreator" - process.env.BUILDKITE_BUILD_CREATOR_EMAIL = "buildKiteCreatorEmail" - process.env.BUILDKITE_REPO = "buildkiteRepo" - process.env.BUILDKITE_PIPELINE_DEFAULT_BRANCH = "buildkitePipelineDefaultBranch" + resetEnv = mockedEnv({ + BUILDKITE: "true" + + BUILDKITE_REPO: "buildkiteRepo" + BUILDKITE_JOB_ID: "buildkiteJobId" + BUILDKITE_SOURCE: "buildkiteSource" + BUILDKITE_BUILD_ID: "buildkiteBuildId" + BUILDKITE_BUILD_URL: "buildkiteBuildUrl" + BUILDKITE_BUILD_NUMBER: "buildkiteBuildNumber" + BUILDKITE_PULL_REQUEST: "buildkitePullRequest" + BUILDKITE_PULL_REQUEST_REPO: "buildkitePullRequestRepo" + BUILDKITE_PULL_REQUEST_BASE_BRANCH: "buildkitePullRequestBaseBranch" + + BUILDKITE_COMMIT: "buildKiteCommit" + BUILDKITE_BRANCH: "buildKiteBranch" + BUILDKITE_MESSAGE: "buildKiteMessage" + BUILDKITE_BUILD_CREATOR: "buildKiteBuildCreator" + BUILDKITE_BUILD_CREATOR_EMAIL: "buildKiteCreatorEmail" + BUILDKITE_PIPELINE_DEFAULT_BRANCH: "buildkitePipelineDefaultBranch" + }, {clear: true}) expectsName("buildkite") expectsCiParams({ @@ -168,23 +199,25 @@ describe "lib/util/ci_provider", -> }) it "circle", -> - process.env.CIRCLECI = true - - process.env.CIRCLE_JOB = "circleJob" - process.env.CIRCLE_BUILD_NUM = "circleBuildNum" - process.env.CIRCLE_BUILD_URL = "circleBuildUrl" - process.env.CIRCLE_PR_NUMBER = "circlePrNumber" - process.env.CIRCLE_PR_REPONAME = "circlePrReponame" - process.env.CIRCLE_PR_USERNAME = "circlePrUsername" - process.env.CIRCLE_COMPARE_URL = "circleCompareUrl" - process.env.CIRCLE_WORKFLOW_ID = "circleWorkflowId" - process.env.CIRCLE_PULL_REQUEST = "circlePullRequest" - process.env.CIRCLE_REPOSITORY_URL = "circleRepositoryUrl" - process.env.CI_PULL_REQUEST = "ciPullRequest" - - process.env.CIRCLE_SHA1 = "circleSha" - process.env.CIRCLE_BRANCH = "circleBranch" - process.env.CIRCLE_USERNAME = "circleUsername" + resetEnv = mockedEnv({ + CIRCLECI: "true" + + CIRCLE_JOB: "circleJob" + CIRCLE_BUILD_NUM: "circleBuildNum" + CIRCLE_BUILD_URL: "circleBuildUrl" + CIRCLE_PR_NUMBER: "circlePrNumber" + CIRCLE_PR_REPONAME: "circlePrReponame" + CIRCLE_PR_USERNAME: "circlePrUsername" + CIRCLE_COMPARE_URL: "circleCompareUrl" + CIRCLE_WORKFLOW_ID: "circleWorkflowId" + CIRCLE_PULL_REQUEST: "circlePullRequest" + CIRCLE_REPOSITORY_URL: "circleRepositoryUrl" + CI_PULL_REQUEST: "ciPullRequest" + + CIRCLE_SHA1: "circleSha" + CIRCLE_BRANCH: "circleBranch" + CIRCLE_USERNAME: "circleUsername" + }, {clear: true}) expectsName("circle") expectsCiParams({ @@ -207,21 +240,23 @@ describe "lib/util/ci_provider", -> }) it "codeshipBasic", -> - process.env.CODESHIP = "TRUE" - process.env.CI_NAME = "codeship" - - process.env.CI_BUILD_ID = "ciBuildId" - process.env.CI_REPO_NAME = "ciRepoName" - process.env.CI_BUILD_URL = "ciBuildUrl" - process.env.CI_PROJECT_ID = "ciProjectId" - process.env.CI_BUILD_NUMBER = "ciBuildNumber" - process.env.CI_PULL_REQUEST = "ciPullRequest" - - process.env.CI_COMMIT_ID = "ciCommitId" - process.env.CI_BRANCH = "ciBranch" - process.env.CI_COMMIT_MESSAGE = "ciCommitMessage" - process.env.CI_COMMITTER_NAME = "ciCommitterName" - process.env.CI_COMMITTER_EMAIL = "ciCommitterEmail" + resetEnv = mockedEnv({ + CODESHIP: "TRUE" + CI_NAME: "codeship" + + CI_BUILD_ID: "ciBuildId" + CI_REPO_NAME: "ciRepoName" + CI_BUILD_URL: "ciBuildUrl" + CI_PROJECT_ID: "ciProjectId" + CI_BUILD_NUMBER: "ciBuildNumber" + CI_PULL_REQUEST: "ciPullRequest" + + CI_COMMIT_ID: "ciCommitId" + CI_BRANCH: "ciBranch" + CI_COMMIT_MESSAGE: "ciCommitMessage" + CI_COMMITTER_NAME: "ciCommitterName" + CI_COMMITTER_EMAIL: "ciCommitterEmail" + }, {clear: true}) expectsName("codeshipBasic") expectsCiParams({ @@ -241,17 +276,19 @@ describe "lib/util/ci_provider", -> }) it "codeshipPro", -> - process.env.CI_NAME = "codeship" + resetEnv = mockedEnv({ + CI_NAME: "codeship" - process.env.CI_BUILD_ID = "ciBuildId" - process.env.CI_REPO_NAME = "ciRepoName" - process.env.CI_PROJECT_ID = "ciProjectId" + CI_BUILD_ID: "ciBuildId" + CI_REPO_NAME: "ciRepoName" + CI_PROJECT_ID: "ciProjectId" - process.env.CI_COMMIT_ID = "ciCommitId" - process.env.CI_BRANCH = "ciBranch" - process.env.CI_COMMIT_MESSAGE = "ciCommitMessage" - process.env.CI_COMMITTER_NAME = "ciCommitterName" - process.env.CI_COMMITTER_EMAIL = "ciCommitterEmail" + CI_COMMIT_ID: "ciCommitId" + CI_BRANCH: "ciBranch" + CI_COMMIT_MESSAGE: "ciCommitMessage" + CI_COMMITTER_NAME: "ciCommitterName" + CI_COMMITTER_EMAIL: "ciCommitterEmail" + }, {clear: true}) expectsName("codeshipPro") expectsCiParams({ @@ -268,19 +305,21 @@ describe "lib/util/ci_provider", -> }) it "drone", -> - process.env.DRONE = true - - process.env.DRONE_JOB_NUMBER = "droneJobNumber" - process.env.DRONE_BUILD_LINK = "droneBuildLink" - process.env.DRONE_BUILD_NUMBER = "droneBuildNumber" - process.env.DRONE_PULL_REQUEST = "dronePullRequest" - - process.env.DRONE_COMMIT_SHA = "droneCommitSha" - process.env.DRONE_COMMIT_BRANCH = "droneCommitBranch" - process.env.DRONE_COMMIT_MESSAGE = "droneCommitMessage" - process.env.DRONE_COMMIT_AUTHOR = "droneCommitAuthor" - process.env.DRONE_COMMIT_AUTHOR_EMAIL = "droneCommitAuthorEmail" - process.env.DRONE_REPO_BRANCH = "droneRepoBranch" + resetEnv = mockedEnv({ + DRONE: "true" + + DRONE_JOB_NUMBER: "droneJobNumber" + DRONE_BUILD_LINK: "droneBuildLink" + DRONE_BUILD_NUMBER: "droneBuildNumber" + DRONE_PULL_REQUEST: "dronePullRequest" + + DRONE_COMMIT_SHA: "droneCommitSha" + DRONE_COMMIT_BRANCH: "droneCommitBranch" + DRONE_COMMIT_MESSAGE: "droneCommitMessage" + DRONE_COMMIT_AUTHOR: "droneCommitAuthor" + DRONE_COMMIT_AUTHOR_EMAIL: "droneCommitAuthorEmail" + DRONE_REPO_BRANCH: "droneRepoBranch" + }, {clear: true}) expectsName("drone") expectsCiParams({ @@ -299,27 +338,29 @@ describe "lib/util/ci_provider", -> }) it "gitlab", -> - process.env.GITLAB_CI = true - - # Gitlab has job id and build id as synonyms - process.env.CI_BUILD_ID = "ciJobId" - process.env.CI_JOB_ID = "ciJobId" - process.env.CI_JOB_URL = "ciJobUrl" - - process.env.CI_PIPELINE_ID = "ciPipelineId" - process.env.CI_PIPELINE_URL = "ciPipelineUrl" - - process.env.GITLAB_HOST = "gitlabHost" - process.env.CI_PROJECT_ID = "ciProjectId" - process.env.CI_PROJECT_URL = "ciProjectUrl" - process.env.CI_REPOSITORY_URL = "ciRepositoryUrl" - process.env.CI_ENVIRONMENT_URL = "ciEnvironmentUrl" - - process.env.CI_COMMIT_SHA = "ciCommitSha" - process.env.CI_COMMIT_REF_NAME = "ciCommitRefName" - process.env.CI_COMMIT_MESSAGE = "ciCommitMessage" - process.env.GITLAB_USER_NAME = "gitlabUserName" - process.env.GITLAB_USER_EMAIL = "gitlabUserEmail" + resetEnv = mockedEnv({ + GITLAB_CI: "true" + + # Gitlab has job id and build id as synonyms + CI_BUILD_ID: "ciJobId" + CI_JOB_ID: "ciJobId" + CI_JOB_URL: "ciJobUrl" + + CI_PIPELINE_ID: "ciPipelineId" + CI_PIPELINE_URL: "ciPipelineUrl" + + GITLAB_HOST: "gitlabHost" + CI_PROJECT_ID: "ciProjectId" + CI_PROJECT_URL: "ciProjectUrl" + CI_REPOSITORY_URL: "ciRepositoryUrl" + CI_ENVIRONMENT_URL: "ciEnvironmentUrl" + + CI_COMMIT_SHA: "ciCommitSha" + CI_COMMIT_REF_NAME: "ciCommitRefName" + CI_COMMIT_MESSAGE: "ciCommitMessage" + GITLAB_USER_NAME: "gitlabUserName" + GITLAB_USER_EMAIL: "gitlabUserEmail" + }, {clear: true}) expectsName("gitlab") expectsCiParams({ @@ -342,28 +383,30 @@ describe "lib/util/ci_provider", -> authorEmail: "gitlabUserEmail" }) - resetEnv() - - process.env.CI_SERVER_NAME = "GitLab CI" + resetEnv = mockedEnv({ + CI_SERVER_NAME: "GitLab CI" + }, {clear: true}) expectsName("gitlab") - resetEnv() - - process.env.CI_SERVER_NAME = "GitLab" + resetEnv = mockedEnv({ + CI_SERVER_NAME: "GitLab" + }, {clear: true}) expectsName("gitlab") it "jenkins", -> - process.env.JENKINS_URL = true + resetEnv = mockedEnv({ + JENKINS_URL: "true" - process.env.BUILD_ID = "buildId" - process.env.BUILD_URL = "buildUrl" - process.env.BUILD_NUMBER = "buildNumber" - process.env.ghprbPullId = "gbprbPullId" + BUILD_ID: "buildId" + BUILD_URL: "buildUrl" + BUILD_NUMBER: "buildNumber" + ghprbPullId: "gbprbPullId" - process.env.GIT_COMMIT = "gitCommit" - process.env.GIT_BRANCH = "gitBranch" + GIT_COMMIT: "gitCommit" + GIT_BRANCH: "gitBranch" + }, {clear: true}) expectsName("jenkins") expectsCiParams({ @@ -377,43 +420,49 @@ describe "lib/util/ci_provider", -> branch: "gitBranch" }) - resetEnv() - process.env.JENKINS_HOME = "/path/to/jenkins" + resetEnv = mockedEnv({ + JENKINS_HOME: "/path/to/jenkins" + }, {clear: true}) expectsName("jenkins") - resetEnv() - process.env.JENKINS_VERSION = "1.2.3" + resetEnv = mockedEnv({ + JENKINS_VERSION: "1.2.3" + }, {clear: true}) expectsName("jenkins") - resetEnv() - process.env.HUDSON_HOME = "/path/to/jenkins" + resetEnv = mockedEnv({ + HUDSON_HOME: "/path/to/jenkins" + }, {clear: true}) expectsName("jenkins") - resetEnv() - process.env.HUDSON_URL = true + resetEnv = mockedEnv({ + HUDSON_URL: "true" + }, {clear: true}) expectsName("jenkins") it "semaphore", -> - process.env.SEMAPHORE = true - - process.env.SEMAPHORE_BRANCH_ID = "semaphoreBranchId" - process.env.SEMAPHORE_BUILD_NUMBER = "semaphoreBuildNumber" - process.env.SEMAPHORE_CURRENT_JOB = "semaphoreCurrentJob" - process.env.SEMAPHORE_CURRENT_THREAD = "semaphoreCurrentThread" - process.env.SEMAPHORE_EXECUTABLE_UUID = "semaphoreExecutableUuid" - process.env.SEMAPHORE_JOB_COUNT = "semaphoreJobCount" - process.env.SEMAPHORE_JOB_UUID = "semaphoreJobUuid" - process.env.SEMAPHORE_PLATFORM = "semaphorePlatform" - process.env.SEMAPHORE_PROJECT_DIR = "semaphoreProjectDir" - process.env.SEMAPHORE_PROJECT_HASH_ID = "semaphoreProjectHashId" - process.env.SEMAPHORE_PROJECT_NAME = "semaphoreProjectName" - process.env.SEMAPHORE_PROJECT_UUID = "semaphoreProjectUuid" - process.env.SEMAPHORE_REPO_SLUG = "semaphoreRepoSlug" - process.env.SEMAPHORE_TRIGGER_SOURCE = "semaphoreTriggerSource" - process.env.PULL_REQUEST_NUMBER = "pullRequestNumber" - - process.env.REVISION = "revision" - process.env.BRANCH_NAME = "branchName" + resetEnv = mockedEnv({ + SEMAPHORE: "true" + + SEMAPHORE_BRANCH_ID: "semaphoreBranchId" + SEMAPHORE_BUILD_NUMBER: "semaphoreBuildNumber" + SEMAPHORE_CURRENT_JOB: "semaphoreCurrentJob" + SEMAPHORE_CURRENT_THREAD: "semaphoreCurrentThread" + SEMAPHORE_EXECUTABLE_UUID: "semaphoreExecutableUuid" + SEMAPHORE_JOB_COUNT: "semaphoreJobCount" + SEMAPHORE_JOB_UUID: "semaphoreJobUuid" + SEMAPHORE_PLATFORM: "semaphorePlatform" + SEMAPHORE_PROJECT_DIR: "semaphoreProjectDir" + SEMAPHORE_PROJECT_HASH_ID: "semaphoreProjectHashId" + SEMAPHORE_PROJECT_NAME: "semaphoreProjectName" + SEMAPHORE_PROJECT_UUID: "semaphoreProjectUuid" + SEMAPHORE_REPO_SLUG: "semaphoreRepoSlug" + SEMAPHORE_TRIGGER_SOURCE: "semaphoreTriggerSource" + PULL_REQUEST_NUMBER: "pullRequestNumber" + + REVISION: "revision" + BRANCH_NAME: "branchName" + }, {clear: true}) expectsName("semaphore") expectsCiParams({ @@ -439,40 +488,42 @@ describe "lib/util/ci_provider", -> }) it "shippable", -> - process.env.SHIPPABLE = "true" - - # build environment variables - process.env.SHIPPABLE_BUILD_ID = "buildId" - process.env.SHIPPABLE_BUILD_NUMBER = "buildNumber" - process.env.SHIPPABLE_COMMIT_RANGE = "commitRange" - process.env.SHIPPABLE_CONTAINER_NAME = "containerName" - process.env.SHIPPABLE_JOB_ID = "jobId" - process.env.SHIPPABLE_JOB_NUMBER = "jobNumber" - process.env.SHIPPABLE_REPO_SLUG = "repoSlug" - - # additional information - process.env.IS_FORK = "isFork" - process.env.IS_GIT_TAG = "isGitTag" - process.env.IS_PRERELEASE = "isPrerelease" - process.env.IS_RELEASE = "isRelease" - process.env.REPOSITORY_URL = "repositoryUrl" - process.env.REPO_FULL_NAME = "repoFullName" - process.env.REPO_NAME = "repoName" - process.env.BUILD_URL = "buildUrl" - - # pull request variables - process.env.BASE_BRANCH = "baseBranch" - process.env.HEAD_BRANCH = "headBranch" - process.env.IS_PULL_REQUEST = "isPullRequest" - process.env.PULL_REQUEST = "pullRequest" - process.env.PULL_REQUEST_BASE_BRANCH = "pullRequestBaseBranch" - process.env.PULL_REQUEST_REPO_FULL_NAME = "pullRequestRepoFullName" - - # git information - process.env.COMMIT = "commit" - process.env.BRANCH = "branch" - process.env.COMMITTER = "committer" - process.env.COMMIT_MESSAGE = "commitMessage" + resetEnv = mockedEnv({ + SHIPPABLE: "true" + + # build environment variables + SHIPPABLE_BUILD_ID: "buildId" + SHIPPABLE_BUILD_NUMBER: "buildNumber" + SHIPPABLE_COMMIT_RANGE: "commitRange" + SHIPPABLE_CONTAINER_NAME: "containerName" + SHIPPABLE_JOB_ID: "jobId" + SHIPPABLE_JOB_NUMBER: "jobNumber" + SHIPPABLE_REPO_SLUG: "repoSlug" + + # additional information + IS_FORK: "isFork" + IS_GIT_TAG: "isGitTag" + IS_PRERELEASE: "isPrerelease" + IS_RELEASE: "isRelease" + REPOSITORY_URL: "repositoryUrl" + REPO_FULL_NAME: "repoFullName" + REPO_NAME: "repoName" + BUILD_URL: "buildUrl" + + # pull request variables + BASE_BRANCH: "baseBranch" + HEAD_BRANCH: "headBranch" + IS_PULL_REQUEST: "isPullRequest" + PULL_REQUEST: "pullRequest" + PULL_REQUEST_BASE_BRANCH: "pullRequestBaseBranch" + PULL_REQUEST_REPO_FULL_NAME: "pullRequestRepoFullName" + + # git information + COMMIT: "commit" + BRANCH: "branch" + COMMITTER: "committer" + COMMIT_MESSAGE: "commitMessage" + }, {clear: true}) expectsName("shippable") expectsCiParams({ @@ -509,30 +560,36 @@ describe "lib/util/ci_provider", -> }) it "snap", -> - process.env.SNAP_CI = true + resetEnv = mockedEnv({ + SNAP_CI: "true" + }, {clear: true}) expectsName("snap") expectsCiParams(null) expectsCommitParams(null) it "teamcity", -> - process.env.TEAMCITY_VERSION = true + resetEnv = mockedEnv({ + TEAMCITY_VERSION: "true" + }, {clear: true}) expectsName("teamcity") expectsCiParams(null) expectsCommitParams(null) it "teamfoundation", -> - process.env.TF_BUILD = true + resetEnv = mockedEnv({ + TF_BUILD: "true" - process.env.BUILD_BUILDID = "buildId" - process.env.BUILD_BUILDNUMBER = "buildNumber" - process.env.BUILD_CONTAINERID = "containerId" + BUILD_BUILDID: "buildId" + BUILD_BUILDNUMBER: "buildNumber" + BUILD_CONTAINERID: "containerId" - process.env.BUILD_SOURCEVERSION = "commit" - process.env.BUILD_SOURCEBRANCHNAME = "branch" - process.env.BUILD_SOURCEVERSIONMESSAGE = "message" - process.env.BUILD_SOURCEVERSIONAUTHOR = "name" + BUILD_SOURCEVERSION: "commit" + BUILD_SOURCEBRANCHNAME: "branch" + BUILD_SOURCEVERSIONMESSAGE: "message" + BUILD_SOURCEVERSIONAUTHOR: "name" + }, {clear: true}) expectsName("teamfoundation") expectsCiParams({ @@ -548,21 +605,23 @@ describe "lib/util/ci_provider", -> }) it "travis", -> - process.env.TRAVIS = true - - process.env.TRAVIS_JOB_ID = "travisJobId" - process.env.TRAVIS_BUILD_ID = "travisBuildId" - process.env.TRAVIS_REPO_SLUG = "travisRepoSlug" - process.env.TRAVIS_JOB_NUMBER = "travisJobNumber" - process.env.TRAVIS_EVENT_TYPE = "travisEventType" - process.env.TRAVIS_COMMIT_RANGE = "travisCommitRange" - process.env.TRAVIS_BUILD_NUMBER = "travisBuildNumber" - process.env.TRAVIS_PULL_REQUEST = "travisPullRequest" - process.env.TRAVIS_PULL_REQUEST_BRANCH = "travisPullRequestBranch" - - process.env.TRAVIS_COMMIT = "travisCommit" - process.env.TRAVIS_BRANCH = "travisBranch" - process.env.TRAVIS_COMMIT_MESSAGE = "travisCommitMessage" + resetEnv = mockedEnv({ + TRAVIS: "true" + + TRAVIS_JOB_ID: "travisJobId" + TRAVIS_BUILD_ID: "travisBuildId" + TRAVIS_REPO_SLUG: "travisRepoSlug" + TRAVIS_JOB_NUMBER: "travisJobNumber" + TRAVIS_EVENT_TYPE: "travisEventType" + TRAVIS_COMMIT_RANGE: "travisCommitRange" + TRAVIS_BUILD_NUMBER: "travisBuildNumber" + TRAVIS_PULL_REQUEST: "travisPullRequest" + TRAVIS_PULL_REQUEST_BRANCH: "travisPullRequestBranch" + + TRAVIS_COMMIT: "travisCommit" + TRAVIS_BRANCH: "travisBranch" + TRAVIS_COMMIT_MESSAGE: "travisCommitMessage" + }, {clear: true}) expectsName("travis") expectsCiParams({ @@ -582,20 +641,26 @@ describe "lib/util/ci_provider", -> message: "travisCommitMessage" }) - resetEnv() - process.env.TRAVIS = true - process.env.TRAVIS_BRANCH = "travisBranch" + resetEnv = mockedEnv({ + TRAVIS: "true" + TRAVIS_BRANCH: "travisBranch" + }, {clear: true}) + expectsCommitParams({ branch: "travisBranch" }) it "wercker", -> - process.env.WERCKER = true + resetEnv = mockedEnv({ + WERCKER: "true" + }, {clear: true}) expectsName("wercker") expectsCiParams(null) expectsCommitParams(null) - resetEnv() - process.env.WERCKER_MAIN_PIPELINE_STARTED = true + resetEnv = mockedEnv({ + WERCKER_MAIN_PIPELINE_STARTED: "true" + }, {clear: true}) + expectsName("wercker") diff --git a/packages/server/test/unit/exceptions_spec.coffee b/packages/server/test/unit/exceptions_spec.coffee index b0dca8bfba52..ae7e4a80d241 100644 --- a/packages/server/test/unit/exceptions_spec.coffee +++ b/packages/server/test/unit/exceptions_spec.coffee @@ -63,12 +63,23 @@ describe "lib/exceptions", -> at bar /Users/ruby/dev/bar.js:92 """ } + @windowsError = { + name: "Path not found: \\Users\\ruby\\dev\\" + message: "Could not find \\Users\\ruby\\dev\\foo.js" + stack: """ + Error at \\Users\\ruby\\dev\\index.js:102 + at foo \\Users\\ruby\\dev\\foo.js:4 + at bar \\Users\\ruby\\dev\\bar.js:92 + """ + } it "strips paths from name, leaving file name and line number", -> expect(exception.getErr(@err).name).to.equal("Path not found: ") + expect(exception.getErr(@windowsError).name).to.equal("Path not found: ") it "strips paths from message, leaving file name and line number", -> expect(exception.getErr(@err).message).to.equal("Could not find foo.js") + expect(exception.getErr(@windowsError).message).to.equal("Could not find foo.js") it "strips paths from stack, leaving file name and line number", -> expect(exception.getErr(@err).stack).to.equal(""" @@ -76,6 +87,11 @@ describe "lib/exceptions", -> at foo foo.js:4 at bar bar.js:92 """) + expect(exception.getErr(@windowsError).stack).to.equal(""" + Error at index.js:102 + at foo foo.js:4 + at bar bar.js:92 + """) it "handles strippable properties being undefined gracefully", -> expect(-> exception.getErr({})).not.to.throw() diff --git a/packages/server/test/unit/modes/record_spec.coffee b/packages/server/test/unit/modes/record_spec.coffee index f17fd1035f05..7e89581ff032 100644 --- a/packages/server/test/unit/modes/record_spec.coffee +++ b/packages/server/test/unit/modes/record_spec.coffee @@ -4,6 +4,8 @@ _ = require("lodash") os = require("os") debug = require("debug")("test") commitInfo = require("@cypress/commit-info") +mockedEnv = require("mocked-env") + api = require("#{root}../lib/api") errors = require("#{root}../lib/errors") logger = require("#{root}../lib/logger") @@ -88,113 +90,165 @@ describe "lib/modes/record", -> # this is tested inside @cypress/commit-info context ".createRunAndRecordSpecs", -> - specs = [ - { relative: "path/to/spec/a" }, - { relative: "path/to/spec/b" } - ] - - beforeEach -> - sinon.stub(ciProvider, "provider").returns("circle") - sinon.stub(ciProvider, "ciParams").returns({foo: "bar"}) - - @commitDefaults = { - branch: "master", - author: "brian", - email: "brian@cypress.io", - message: "such hax", - sha: "sha-123", - remote: "https://github.com/foo/bar.git" + describe "fallback commit information", -> + resetEnv = null + + env = { + COMMIT_INFO_BRANCH: "my-branch-221", + COMMIT_INFO_MESSAGE: "best commit ever", + COMMIT_INFO_EMAIL: "user@company.com", + COMMIT_INFO_AUTHOR: "Agent Smith", + COMMIT_INFO_SHA: "0123456", + COMMIT_INFO_REMOTE: "remote repo" } - sinon.stub(commitInfo, "commitInfo").resolves(@commitDefaults) - sinon.stub(ciProvider, "commitDefaults").returns({ - sha: @commitDefaults.sha - branch: @commitDefaults.branch - authorName: @commitDefaults.author - authorEmail: @commitDefaults.email - message: @commitDefaults.message - remoteOrigin: @commitDefaults.remote - }) - sinon.stub(api, "createRun").resolves() - - it "calls api.createRun with the right args", -> - key = "recordKey" - projectId = "pId123" - specPattern = ["spec/pattern1", "spec/pattern2"] - projectRoot = "project/root" - ciBuildId = "ciId123" - parallel = null - group = null - runAllSpecs = sinon.stub() - sys = { - osCpus: 1 - osName: 2 - osMemory: 3 - osVersion: 4 - } - browser = { - displayName: "chrome" - version: "59" - } + beforeEach -> + # stub git commands to return nulls + sinon.stub(commitInfo, "getBranch").resolves(null) + sinon.stub(commitInfo, "getMessage").resolves(null) + sinon.stub(commitInfo, "getEmail").resolves(null) + sinon.stub(commitInfo, "getAuthor").resolves(null) + sinon.stub(commitInfo, "getSha").resolves(null) + sinon.stub(commitInfo, "getRemoteOrigin").resolves(null) + # but set environment variables + resetEnv = mockedEnv(env, {clear: true}) + + afterEach -> + resetEnv() + + it "calls api.createRun with the commit extracted from environment variables", -> + createRun = sinon.stub(api, "createRun").resolves() + runAllSpecs = sinon.stub() + recordMode.createRunAndRecordSpecs({ + key: "foo", + sys: {}, + browser: {}, + runAllSpecs + }) + .then -> + expect(runAllSpecs).to.have.been.calledWith({}, false) + expect(createRun).to.have.been.calledOnce + expect(createRun.firstCall.args).to.have.length(1) + { commit } = createRun.firstCall.args[0] + debug('git is %o', commit) + expect(commit).to.deep.equal({ + sha: env.COMMIT_INFO_SHA, + branch: env.COMMIT_INFO_BRANCH, + authorName: env.COMMIT_INFO_AUTHOR, + authorEmail: env.COMMIT_INFO_EMAIL, + message: env.COMMIT_INFO_MESSAGE, + remoteOrigin: env.COMMIT_INFO_REMOTE, + defaultBranch: null + }) + + describe "with CI info", -> + specs = [ + { relative: "path/to/spec/a" }, + { relative: "path/to/spec/b" } + ] + + beforeEach -> + sinon.stub(ciProvider, "provider").returns("circle") + sinon.stub(ciProvider, "ciParams").returns({foo: "bar"}) + + @commitDefaults = { + branch: "master", + author: "brian", + email: "brian@cypress.io", + message: "such hax", + sha: "sha-123", + remote: "https://github.com/foo/bar.git" + } + sinon.stub(commitInfo, "commitInfo").resolves(@commitDefaults) + sinon.stub(ciProvider, "commitDefaults").returns({ + sha: @commitDefaults.sha + branch: @commitDefaults.branch + authorName: @commitDefaults.author + authorEmail: @commitDefaults.email + message: @commitDefaults.message + remoteOrigin: @commitDefaults.remote + }) - recordMode.createRunAndRecordSpecs({ - key - sys - specs - group - browser - parallel - ciBuildId - projectId - projectRoot - specPattern - runAllSpecs - }) - .then -> - expect(commitInfo.commitInfo).to.be.calledWith(projectRoot) - expect(api.createRun).to.be.calledWith({ + sinon.stub(api, "createRun").resolves() + + it "calls api.createRun with the right args", -> + key = "recordKey" + projectId = "pId123" + specPattern = ["spec/pattern1", "spec/pattern2"] + projectRoot = "project/root" + ciBuildId = "ciId123" + parallel = null + group = null + runAllSpecs = sinon.stub() + sys = { + osCpus: 1 + osName: 2 + osMemory: 3 + osVersion: 4 + } + browser = { + displayName: "chrome" + version: "59" + } + + recordMode.createRunAndRecordSpecs({ + key + sys + specs group + browser parallel - projectId ciBuildId - recordKey: key - specPattern: "spec/pattern1,spec/pattern2" - specs: ["path/to/spec/a", "path/to/spec/b"] - platform: { - osCpus: 1 - osName: 2 - osMemory: 3 - osVersion: 4 - browserName: "chrome" - browserVersion: "59" - } - ci: { - params: { - foo: "bar" - } - provider: "circle" - } - commit: { - authorEmail: "brian@cypress.io" - authorName: "brian" - branch: "master" - message: "such hax" - remoteOrigin: "https://github.com/foo/bar.git" - sha: "sha-123" - } - platform: { - browserName: "chrome" - browserVersion: "59" - osCpus: 1 - osMemory: 3 - osName: 2 - osVersion: 4 - } - projectId: "pId123" - recordKey: "recordKey" - specPattern: "spec/pattern1,spec/pattern2" - specs: ["path/to/spec/a", "path/to/spec/b"] + projectId + projectRoot + specPattern + runAllSpecs }) + .then -> + expect(commitInfo.commitInfo).to.be.calledWith(projectRoot) + expect(api.createRun).to.be.calledWith({ + group + parallel + projectId + ciBuildId + recordKey: key + specPattern: "spec/pattern1,spec/pattern2" + specs: ["path/to/spec/a", "path/to/spec/b"] + platform: { + osCpus: 1 + osName: 2 + osMemory: 3 + osVersion: 4 + browserName: "chrome" + browserVersion: "59" + } + ci: { + params: { + foo: "bar" + } + provider: "circle" + } + commit: { + authorEmail: "brian@cypress.io" + authorName: "brian" + branch: "master" + message: "such hax" + remoteOrigin: "https://github.com/foo/bar.git" + sha: "sha-123" + } + platform: { + browserName: "chrome" + browserVersion: "59" + osCpus: 1 + osMemory: 3 + osName: 2 + osVersion: 4 + } + projectId: "pId123" + recordKey: "recordKey" + specPattern: "spec/pattern1,spec/pattern2" + specs: ["path/to/spec/a", "path/to/spec/b"] + }) context ".updateInstanceStdout", -> beforeEach -> diff --git a/packages/ts/package.json b/packages/ts/package.json index d1b28b4c06aa..6d4413319c56 100644 --- a/packages/ts/package.json +++ b/packages/ts/package.json @@ -15,6 +15,6 @@ "typescript": "2.5.2" }, "dependencies": { - "debug": "^2.6.8" + "debug": "2.6.9" } } diff --git a/renovate.json b/renovate.json new file mode 100644 index 000000000000..c63e5459458d --- /dev/null +++ b/renovate.json @@ -0,0 +1,33 @@ +{ + "extends": [ + "config:base" + ], + "automerge": true, + "major": { + "automerge": false + }, + "minor": { + "automerge": false + }, + "rangeStrategy": "pin", + "packageRules": [ + { + "packageNames": [ + "node" + ], + "enabled": false + } + ], + "separateMultipleMajor": true, + "labels": ["type: dependencies", "renovate"], + "commitMessage": "{{semanticPrefix}}Update {{depName}} to {{newVersion}} 🌟", + "prTitle": "{{semanticPrefix}}{{#if isPin}}Pin{{else}}Update{{/if}} dependency {{depName}} to version {{#if isRange}}{{newVersion}}{{else}}{{#if isMajor}}{{newVersionMajor}}.x{{else}}{{newVersion}}{{/if}}{{/if}} 🌟", + "prHourlyLimit": 1, + "prConcurrentLimit": 5, + "updateNotScheduled": false, + "timezone": "America/New_York", + "schedule": [ + "after 10pm and before 5am on every weekday", + "every weekend" + ] +} diff --git a/scripts/check-terminal.js b/scripts/check-terminal.js new file mode 100644 index 000000000000..4b1e8f94b09b --- /dev/null +++ b/scripts/check-terminal.js @@ -0,0 +1,14 @@ +// checks if the terminal has all the variables set (especially on Linux Docker) + +const assert = require('assert') +const isLinux = process.platform === 'linux' + +if (isLinux) { + assert.ok(process.env.TERM === 'xterm', `process.env.TERM=${process.env.TERM} and must be set to "xterm" for Docker to work`) +} + +assert.ok(process.env.COLUMNS === '100', `process.env.COLUMNS=${process.env.COLUMNS} must be set to 100 for snapshots to pass`) + +/* eslint-disable no-console */ +console.log('stdout.isTTY?', process.stdout.isTTY) +console.log('stderr.isTTY?', process.stderr.isTTY) diff --git a/scripts/win-appveyor-build.js b/scripts/win-appveyor-build.js index 78911348e529..9e30e7990cb0 100755 --- a/scripts/win-appveyor-build.js +++ b/scripts/win-appveyor-build.js @@ -17,6 +17,7 @@ shell.set('-e') // any error is fatal const isRightBranch = () => { const branch = process.env.APPVEYOR_REPO_BRANCH + return branch === 'develop' } @@ -49,9 +50,11 @@ shell.exec(`npm run binary-build -- --platform windows --version ${version}`) // make sure we are not including dev dependencies accidentally // TODO how to get the server package folder? const serverPackageFolder = 'C:/projects/cypress/dist/win32/packages/server' + shell.echo(`Checking prod and dev dependencies in ${serverPackageFolder}`) -shell.exec('npm ls --prod --depth 0 || true', {cwd: serverPackageFolder}) -const result = shell.exec('npm ls --dev --depth 0 || true', {cwd: serverPackageFolder}) +shell.exec('npm ls --prod --depth 0 || true', { cwd: serverPackageFolder }) +const result = shell.exec('npm ls --dev --depth 0 || true', { cwd: serverPackageFolder }) + if (result.stdout.includes('nodemon')) { console.error('Hmm, server package includes dev dependency "nodemon"') console.error('which means somehow we are including dev dependencies in the output bundle')