diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..f2adaaa --- /dev/null +++ b/.babelrc @@ -0,0 +1,5 @@ +{ + "plugins": [ + "istanbul" + ] +} diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 1aabdfb..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,38 +0,0 @@ -version: 2.1 - -default_test_steps: &default_test_steps - steps: - - checkout - - run: yarn - - run: yarn test - -jobs: - test: - docker: - - image: circleci/node:10-browsers - environment: - PERCY_ENABLE: 0 - <<: *default_test_steps - percy_test: - # We've opted this node version to be the one that runs and reports Percy's status - docker: - - image: circleci/node:12-browsers - <<: *default_test_steps - release: - docker: - - image: circleci/node:12 - steps: - - checkout - - run: yarn - - run: npx semantic-release - -workflows: - version: 2.1 - test_and_release: - jobs: - - test - - percy_test - - release: - requires: - - test - - percy_test diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..702dcb6 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,15 @@ +extends: standard +plugins: + - cypress +env: + cypress/globals: true +rules: + prefer-const: off + no-unused-expressions: off + promise/param-names: off + semi: [error, always] + space-before-function-paren: + - error + - anonymous: never + asyncArrow: always + named: never diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..3dc6a0f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: +- package-ecosystem: npm + directory: / + schedule: + interval: weekly + commit-message: + prefix: ⬆️ diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..f98c9e9 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,31 @@ +name-template: 'v$RESOLVED_VERSION' +tag-template: 'v$RESOLVED_VERSION' +categories: + - title: '💥 Breaking Changes' + labels: + - breaking + - title: '✨ Enhancements' + labels: + - feature + - enhancement + - title: '🐛 Bug Fixes' + labels: + - fix + - bugfix + - bug + - title: '🏗 Maintenance' + labels: + - chore + - dependencies +change-title-escapes: '\<*_@' +version-resolver: + major: + labels: + - breaking + minor: + labels: + - feature + - enhancement + default: patch +template: '$CHANGES' +prerelease: true diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml new file mode 100644 index 0000000..ef80779 --- /dev/null +++ b/.github/workflows/changelog.yml @@ -0,0 +1,11 @@ +name: Changelog +on: + push: + branches: [master] +jobs: + update_draft: + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..b32862d --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,21 @@ +name: Lint +on: push +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: 12 + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + - uses: actions/cache@v2 + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: v1/${{ runner.os }}/node-12/${{ hashFiles('**/yarn.lock') }} + restore-keys: v1/${{ runner.os }}/node-12/ + - run: yarn + - run: yarn lint diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..443af54 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,26 @@ +name: Release +on: + release: + types: [published] +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: 12 + registry-url: 'https://registry.npmjs.org' + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + - uses: actions/cache@v2 + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: v1/${{ runner.os }}/node-12/${{ hashFiles('**/yarn.lock') }} + restore-keys: v1/${{ runner.os }}/node-12/ + - run: yarn + - run: yarn build + - run: npm publish --tag next + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..b6d5ef6 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,25 @@ +name: Test +on: push +jobs: + test: + name: Test + strategy: + matrix: + os: [ubuntu-latest] + node: [12] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node }} + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + - uses: actions/cache@v2 + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: v1/${{ runner.os }}/node-${{ matrix.node }}/${{ hashFiles('**/yarn.lock') }} + restore-keys: v1/${{ runner.os }}/node-${{ matrix.node }}/ + - run: yarn + - run: yarn test:coverage diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml new file mode 100644 index 0000000..1648474 --- /dev/null +++ b/.github/workflows/typecheck.yml @@ -0,0 +1,21 @@ +name: Typecheck +on: push +jobs: + typecheck: + name: Typecheck + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: 12 + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + - uses: actions/cache@v2 + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: v1/${{ runner.os }}/node-12/${{ hashFiles('**/yarn.lock') }} + restore-keys: v1/${{ runner.os }}/node-12/ + - run: yarn + - run: yarn test:types diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml deleted file mode 100644 index 842e6e0..0000000 --- a/.github/workflows/windows.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Windows CI -on: [push, pull_request] -jobs: - build: - runs-on: windows-2019 - steps: - - name: Checkout - uses: actions/checkout@master - - name: Install - run: yarn - - name: Build - run: yarn build - - name: Percy Test - uses: percy/exec-action@master - with: - command: "node run-tests.js" - env: - PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }} diff --git a/.gitignore b/.gitignore index 5b3ce88..f806226 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ -node_modules/ -dist/ -cypress/screenshots +node_modules +.nyc_output +coverage +cypress/fixtures diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 81b854d..0000000 --- a/.npmignore +++ /dev/null @@ -1,3 +0,0 @@ -lib/ -cypress/ -cypress.json diff --git a/.nycrc b/.nycrc new file mode 100644 index 0000000..2f62cb3 --- /dev/null +++ b/.nycrc @@ -0,0 +1,6 @@ +{ + "branches": 100, + "lines": 100, + "functions": 100, + "statements": 100 +} diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 81f0d70..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,106 +0,0 @@ -## [2.3.4](https://github.com/percy/percy-cypress/compare/v2.3.3...v2.3.4) (2021-01-21) - - -### Bug Fixes - -* Update Cypress `peerDependency` for Cypress 6 ([#288](https://github.com/percy/percy-cypress/issues/288)) ([6991e44](https://github.com/percy/percy-cypress/commit/6991e44ae73ed756c12d730222f4e917ab07695c)) - -## [2.3.3](https://github.com/percy/percy-cypress/compare/v2.3.2...v2.3.3) (2020-12-01) - - -### Bug Fixes - -* Upgrade deps for security ([#277](https://github.com/percy/percy-cypress/issues/277)) ([98b06a4](https://github.com/percy/percy-cypress/commit/98b06a4)) - -## [2.3.2](https://github.com/percy/percy-cypress/compare/v2.3.1...v2.3.2) (2020-09-30) - - -### Bug Fixes - -* Add cypress 5 to peerDependencies ([#250](https://github.com/percy/percy-cypress/issues/250)) ([98d982d](https://github.com/percy/percy-cypress/commit/98d982d)) - -## [2.3.1](https://github.com/percy/percy-cypress/compare/v2.3.0...v2.3.1) (2020-03-05) - - -### Bug Fixes - -* Update peerDependencies for Cypress v4 ([#198](https://github.com/percy/percy-cypress/issues/198)) ([0502199](https://github.com/percy/percy-cypress/commit/0502199)), closes [#193](https://github.com/percy/percy-cypress/issues/193) - -# [2.3.0](https://github.com/percy/percy-cypress/compare/v2.2.0...v2.3.0) (2020-02-03) - - -### Features - -* Use node v10 ([#190](https://github.com/percy/percy-cypress/issues/190)) ([be177c7](https://github.com/percy/percy-cypress/commit/be177c7)) - -# [2.2.0](https://github.com/percy/percy-cypress/compare/v2.1.1...v2.2.0) (2019-10-08) - - -### Features - -* :sparkles: Add request headers option for asset-discovery ([#159](https://github.com/percy/percy-cypress/issues/159)) ([a595f48](https://github.com/percy/percy-cypress/commit/a595f48)) - -## [2.1.1](https://github.com/percy/percy-cypress/compare/v2.1.0...v2.1.1) (2019-09-20) - - -### Bug Fixes - -* add `percyCSS` option to types ([#156](https://github.com/percy/percy-cypress/issues/156)) ([7475783](https://github.com/percy/percy-cypress/commit/7475783)) - -# [2.1.0](https://github.com/percy/percy-cypress/compare/v2.0.1...v2.1.0) (2019-09-17) - - -### Features - -* Add the ability to pass per-snapshot CSS ([#154](https://github.com/percy/percy-cypress/issues/154)) ([02b976f](https://github.com/percy/percy-cypress/commit/02b976f)) - -## [2.0.1](https://github.com/percy/percy-cypress/compare/v2.0.0...v2.0.1) (2019-08-26) - - -### Bug Fixes - -* pass minHeight option along to agent ([#148](https://github.com/percy/percy-cypress/issues/148)) ([44c2152](https://github.com/percy/percy-cypress/commit/44c2152)) - -# [2.0.0](https://github.com/percy/percy-cypress/compare/v1.0.9...v2.0.0) (2019-08-02) - - -### Bug Fixes - -* Use `cy.task` for health check rather than `cy.exec` (BREAKING CHANGE) ([#140](https://github.com/percy/percy-cypress/issues/140)) ([40550f7](https://github.com/percy/percy-cypress/commit/40550f7)), closes [#104](https://github.com/percy/percy-cypress/issues/104) [#104](https://github.com/percy/percy-cypress/issues/104) [#138](https://github.com/percy/percy-cypress/issues/138) - - -### BREAKING CHANGES - -* ## The problem - -In all of the Percy SDKs we do a thing called a "heath check", which makes sure the Percy agent server is open and ready to accept the DOM we're going to `POST` to it. If the health check fails, we will disable Percy in the SDK so we're not failing your tests due to Percy not running. - -In the Cypress SDK, this was implemented in an interesting way due a limitation with `cy.request`. The TL:DR of that is we can't `.catch` a failed request, so we needed to use `cy.exec` to health check & gracefully fall out. You can read a little more about that limitation here: https://github.com/cypress-io/cypress/issues/3161 - -## [1.0.9](https://github.com/percy/percy-cypress/compare/v1.0.8...v1.0.9) (2019-05-08) - - -### Bug Fixes - -* Add TypeScript types. Closes [#89](https://github.com/percy/percy-cypress/issues/89) ([#96](https://github.com/percy/percy-cypress/issues/96)) ([6548bf7](https://github.com/percy/percy-cypress/commit/6548bf7)), closes [/github.com/percy/percy-cypress/pull/96#issuecomment-490487665](https://github.com//github.com/percy/percy-cypress/pull/96/issues/issuecomment-490487665) - -## [1.0.8](https://github.com/percy/percy-cypress/compare/v1.0.7...v1.0.8) (2019-05-02) - - -### Bug Fixes - -* Properly pass user agent ([#93](https://github.com/percy/percy-cypress/issues/93)) ([9b9f5e6](https://github.com/percy/percy-cypress/commit/9b9f5e6)) - -## [1.0.7](https://github.com/percy/percy-cypress/compare/v1.0.6...v1.0.7) (2019-04-30) - - -### Bug Fixes - -* Open `@percy/agent` version range (tilde over caret) ([#92](https://github.com/percy/percy-cypress/issues/92)) ([0e4b3f9](https://github.com/percy/percy-cypress/commit/0e4b3f9)), closes [/github.com/npm/node-semver#caret-ranges-123-025-004](https://github.com//github.com/npm/node-semver/issues/caret-ranges-123-025-004) [/github.com/npm/node-semver#tilde-ranges-123-12-1](https://github.com//github.com/npm/node-semver/issues/tilde-ranges-123-12-1) - -## [1.0.6](https://github.com/percy/percy-cypress/compare/v1.0.5...v1.0.6) (2019-04-09) - - -### Bug Fixes - -* Require @percy/agent 0.2.2. Resolves issue [#58](https://github.com/percy/percy-cypress/issues/58) ([#80](https://github.com/percy/percy-cypress/issues/80)) ([15c59be](https://github.com/percy/percy-cypress/commit/15c59be)) diff --git a/README.md b/README.md index 7ec8c9e..c762108 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,97 @@ # @percy/cypress +[![Version](https://img.shields.io/npm/v/@percy/cypress.svg)](https://npmjs.org/package/@percy/cypress) +![Test](https://github.com/percy/percy-cypress/workflows/Test/badge.svg) -[![Package Status](https://img.shields.io/npm/v/@percy/cypress.svg)](https://www.npmjs.com/package/@percy/cypress) [![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/percy/percy-cypress) [![CircleCI](https://circleci.com/gh/percy/percy-cypress.svg?style=svg)](https://circleci.com/gh/percy/percy-cypress) +[Percy](https://percy.io) visual testing for [Cypress](https://cypress.io). -[Percy](https://percy.io) visual testing for [Cypress](https://www.cypress.io). +## Installation -## Resources +```sh-session +$ npm install --save-dev @percy/cli @percy/cypress@next +``` -* [Setup and integration docs](https://docs.percy.io/docs/cypress) -* [Tutorial](https://docs.percy.io/docs/cypress-tutorial) -* [Example integration](https://github.com/percy/example-percy-cypress) -* [Example integration with TypeScript](https://github.com/percy/example-percy-cypress-typescript) +Then add to your `cypress/support/index.js` file + +```javascript +import '@percy/cypress' +``` + +## Usage + +This is an example using the `cy.percySnapshot` command. + +```javascript +describe('My app', () => { + it('should look good', () => { + cy.get('body').should('have.class', 'finished-loading'); + cy.percySnapshot(); + + cy.get('button').click(); + cy.percySnapshot('Clicked button'); + }); +}); +``` + +Running the test above will result in the following log: + +```sh-session +$ cypress run +... +[percy] Percy is not running, disabling snapshots +``` + +When running with [`percy +exec`](https://github.com/percy/cli/tree/master/packages/cli-exec#percy-exec), and your project's +`PERCY_TOKEN`, a new Percy build will be created and snapshots will be uploaded to your project. + +```sh-session +$ export PERCY_TOKEN=[your-project-token] +$ percy exec -- cypress run +[percy] Percy has started! +[percy] Created build #1: https://percy.io/[your-project] +[percy] Running "cypress run" +... +[percy] Snapshot taken "My app should look good" +[percy] Snapshot taken "Clicked button" +... +[percy] Stopping percy... +[percy] Finalized build #1: https://percy.io/[your-project] +[percy] Done! +``` + +## Configuration + +`cy.percySnapshot([name][, options])` + +- `name` - The snapshot name; must be unique to each snapshot; defaults to the full test title +- `options` - Additional snapshot options (overrides any project options) + - `options.widths` - An array of widths to take screenshots at + - `options.minHeight` - The minimum viewport height to take screenshots at + - `options.percyCSS` - Percy specific CSS only applied in Percy's rendering environment + - `options.requestHeaders` - Headers that should be used during asset discovery + - `options.enableJavaScript` - Enable JavaScript in Percy's rendering environment + +## Upgrading + +#### Installing `@percy/cli` + +If you're coming from a pre-3.0 version of this package, make sure to install `@percy/cli` after +upgrading to retain any existing scripts that reference the Percy CLI command. + +```sh-session +$ npm install --save-dev @percy/cli +``` + +#### Removing tasks + +If you're coming from 2.x the health check task, `@percy/cypress/task`, is no longer needed and no +longer exists. You should remove this task from your `cypress/plugins/index.js` file. + +#### Migrating Config + +If you have a previous Percy configuration file, migrate it to the newest version with the +[`config:migrate`](https://github.com/percy/cli/tree/master/packages/cli-config#percy-configmigrate-filepath-output) command: + +```sh-session +$ percy config:migrate +``` diff --git a/RELEASING.md b/RELEASING.md deleted file mode 100644 index 5d94c2d..0000000 --- a/RELEASING.md +++ /dev/null @@ -1,3 +0,0 @@ -# Releasing - -Releasing of the `@percy/cypress` package is handled automatically with the [semantic-release](https://github.com/semantic-release/semantic-release) package. diff --git a/cypress.json b/cypress.json index 60ed5aa..8513da0 100644 --- a/cypress.json +++ b/cypress.json @@ -1,3 +1,4 @@ { - "video": false + "video": false, + "screenshotOnRunFailure": false } diff --git a/cypress/integration/index.test.js b/cypress/integration/index.test.js new file mode 100644 index 0000000..352e1ae --- /dev/null +++ b/cypress/integration/index.test.js @@ -0,0 +1,68 @@ +import helpers from '@percy/sdk-utils/test/client'; + +const { match } = Cypress.sinon; + +describe('percySnapshot', () => { + beforeEach(() => { + cy.then(helpers.setup); + cy.visit('http://localhost:8000'); + cy.wrap(cy.spy(Cypress, 'log').log(false)).as('log'); + }); + + afterEach(() => { + cy.then(helpers.teardown); + }); + + it('disables snapshots when the healthcheck fails', () => { + cy.then(() => helpers.testFailure('/percy/healthcheck')); + + cy.percySnapshot(); + cy.percySnapshot('Snapshot 2'); + + cy.then(helpers.getRequests).should('deep.equal', [ + ['/percy/healthcheck'] + ]); + + cy.wrap(helpers.logger.stderr).should('deep.equal', []); + cy.wrap(helpers.logger.stdout).should('deep.equal', [ + '[percy] Percy is not running, disabling snapshots' + ]); + }); + + it('posts snapshots to the local percy server', () => { + cy.percySnapshot(); + cy.percySnapshot('Snapshot 2'); + + cy.then(helpers.getRequests).should(requests => { + // test stub so we can utilize sinon matchers + let test = cy.stub(); test(requests); + + expect(test).to.be.calledWith(match([ + match(['/percy/healthcheck']), + match(['/percy/dom.js']), + match(['/percy/snapshot', match({ + name: 'percySnapshot posts snapshots to the local percy server', + url: 'http://localhost:8000/', + domSnapshot: match(/
(.*?)<\/head>Snapshot Me<\/body><\/html>/), + clientInfo: match(/@percy\/cypress\/.+/), + environmentInfo: match(/cypress\/.+/) + })]), + match(['/percy/snapshot', match({ + name: 'Snapshot 2' + })]) + ])); + }); + }); + + it('handles snapshot failures', () => { + cy.then(() => helpers.testFailure('/percy/snapshot')); + + cy.percySnapshot(); + + cy.wrap(helpers.logger.stdout).should('deep.equal', []); + cy.wrap(helpers.logger.stderr).should('deep.equal', [ + '[percy] Could not take DOM snapshot "percySnapshot handles snapshot failures"', + '[percy] Error: 500 Internal Server Error' + ]); + }); +}); diff --git a/cypress/integration/sdk_spec.js b/cypress/integration/sdk_spec.js deleted file mode 100644 index 6cc60d4..0000000 --- a/cypress/integration/sdk_spec.js +++ /dev/null @@ -1,77 +0,0 @@ -describe('@percy/cypress', function() { - - describe('with local app', function() { - - beforeEach(function() { - // Make sure we start each test with a clean slate. - cy.clearLocalStorage() - // Load the app and verify that it is in fact being loaded correctly. - cy.visit('http://localhost:8000') - cy.get('.todoapp').should('exist') - }) - - it('snapshots with autogenerated name', function() { - cy.percySnapshot() - }) - - it('snapshots with provided name', function() { - cy.percySnapshot('Explicitly given name') - }) - - it('snapshots with provided name and widths', function() { - cy.percySnapshot('Snapshot with widths', { widths: [768, 992, 1200] }) - }) - - it('snapshots with provided name and percyCSS', function() { - cy.percySnapshot('Snapshot with percyCSS', { - percyCSS: `body { background-color: purple; }` - }) - }) - - it('snapshots with provided name and minHeight', function() { - cy.get('.todoapp').should('exist') - cy.percySnapshot('Snapshot with minHeight', { minHeight: 2000 }) - }) - - it('correctly takes multiple snapshots in one test', function() { - // Enter a new todo. - cy.get('.new-todo').type('A thing to accomplish {enter}') - cy.get('.todo-count').should('contain', '1 item left') - cy.percySnapshot('Multiple snapshots #1 -- 1 todo left') - - // Click it off -- it should be marked as completed. - cy.get('.toggle').click() - cy.get('.todo-count').should('contain', '0 items left') - cy.percySnapshot('Multiple snapshots #2 -- 1 checked-off todo') - }) - - it('snapshots part of a page', function() { - cy.percySnapshot('With a passed domTransformation function', { - domTransformation: documentClone => scope(documentClone, 'footer.info') - }) - }) - }) - - describe('with live sites', function() { - // The tests in this block require setting '"chromeWebSecurity": false' in cypress.json. - // For details, see: https://docs.cypress.io/guides/guides/web-security.html#Disabling-Web-Security - - it('snapshots a website with HTTP', function() { - cy.visit('http://example.com/') - cy.percySnapshot('http://example.com/') - }) - - it('snapshots a website with HTTPS, strict CSP, CORS and HSTS setup', function() { - cy.visit('https://sdk-test.percy.dev') - cy.percySnapshot('https://sdk-test.percy.dev') - }) - }) -}) - - -function scope(documentClone, selector) { - let element = documentClone.querySelector(selector); - documentClone.querySelector('body').innerHTML = element.outerHTML; - - return documentClone; -} diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index 8f3dde3..29f8eee 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -1,28 +1,5 @@ -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) -const percyHealthCheck = require("../../task"); - module.exports = (on, config) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config - - // Make it possible to log things to stdout by calling 'cy.task('log', 'some message to log'). - // Useful for development and debugging. - on("task", { - log(message) { - console.log(message); - return null; - } - }); - on("task", percyHealthCheck); + require('@cypress/code-coverage/task')(on, config); + on('file:preprocessor', require('@cypress/code-coverage/use-babelrc')); + return config; }; diff --git a/cypress/support/commands.js b/cypress/support/commands.js deleted file mode 100644 index 4d78771..0000000 --- a/cypress/support/commands.js +++ /dev/null @@ -1,27 +0,0 @@ -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add("login", (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This is will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) - -import '../../dist/index' diff --git a/cypress/support/index.js b/cypress/support/index.js index d68db96..6d36470 100644 --- a/cypress/support/index.js +++ b/cypress/support/index.js @@ -1,20 +1,2 @@ -// *********************************************************** -// This example support/index.js is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import './commands' - -// Alternatively you can use CommonJS syntax: -// require('./commands') +import '@cypress/code-coverage/support'; +import '../..'; diff --git a/cypress/testapp/README.md b/cypress/testapp/README.md deleted file mode 100644 index 4e4badd..0000000 --- a/cypress/testapp/README.md +++ /dev/null @@ -1,11 +0,0 @@ -App for testing the SDK. Based on the -[TodoMVC](https://github.com/tastejs/todomvc) -[Vanilla-ES6](https://github.com/tastejs/todomvc/tree/master/examples/vanilla-es6) -app, forked at commit -[c78ae12a1834a11da6236c64a0c0fb06b20b7c51](https://github.com/tastejs/todomvc/tree/c78ae12a1834a11da6236c64a0c0fb06b20b7c51). - -To see the app in action: - -```bash -$ open index.html -``` diff --git a/cypress/testapp/base.css b/cypress/testapp/base.css deleted file mode 100644 index da65968..0000000 --- a/cypress/testapp/base.css +++ /dev/null @@ -1,141 +0,0 @@ -hr { - margin: 20px 0; - border: 0; - border-top: 1px dashed #c5c5c5; - border-bottom: 1px dashed #f7f7f7; -} - -.learn a { - font-weight: normal; - text-decoration: none; - color: #b83f45; -} - -.learn a:hover { - text-decoration: underline; - color: #787e7e; -} - -.learn h3, -.learn h4, -.learn h5 { - margin: 10px 0; - font-weight: 500; - line-height: 1.2; - color: #000; -} - -.learn h3 { - font-size: 24px; -} - -.learn h4 { - font-size: 18px; -} - -.learn h5 { - margin-bottom: 0; - font-size: 14px; -} - -.learn ul { - padding: 0; - margin: 0 0 30px 25px; -} - -.learn li { - line-height: 20px; -} - -.learn p { - font-size: 15px; - font-weight: 300; - line-height: 1.3; - margin-top: 0; - margin-bottom: 0; -} - -#issue-count { - display: none; -} - -.quote { - border: none; - margin: 20px 0 60px 0; -} - -.quote p { - font-style: italic; -} - -.quote p:before { - content: '“'; - font-size: 50px; - opacity: .15; - position: absolute; - top: -20px; - left: 3px; -} - -.quote p:after { - content: '”'; - font-size: 50px; - opacity: .15; - position: absolute; - bottom: -42px; - right: 3px; -} - -.quote footer { - position: absolute; - bottom: -40px; - right: 0; -} - -.quote footer img { - border-radius: 3px; -} - -.quote footer a { - margin-left: 5px; - vertical-align: middle; -} - -.speech-bubble { - position: relative; - padding: 10px; - background: rgba(0, 0, 0, .04); - border-radius: 5px; -} - -.speech-bubble:after { - content: ''; - position: absolute; - top: 100%; - right: 30px; - border: 13px solid transparent; - border-top-color: rgba(0, 0, 0, .04); -} - -.learn-bar > .learn { - position: absolute; - width: 272px; - top: 8px; - left: -300px; - padding: 10px; - border-radius: 5px; - background-color: rgba(255, 255, 255, .6); - transition-property: left; - transition-duration: 500ms; -} - -@media (min-width: 899px) { - .learn-bar { - width: auto; - padding-left: 300px; - } - - .learn-bar > .learn { - left: 8px; - } -} diff --git a/cypress/testapp/base.js b/cypress/testapp/base.js deleted file mode 100644 index a56b5aa..0000000 --- a/cypress/testapp/base.js +++ /dev/null @@ -1,249 +0,0 @@ -/* global _ */ -(function () { - 'use strict'; - - /* jshint ignore:start */ - // Underscore's Template Module - // Courtesy of underscorejs.org - var _ = (function (_) { - _.defaults = function (object) { - if (!object) { - return object; - } - for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) { - var iterable = arguments[argsIndex]; - if (iterable) { - for (var key in iterable) { - if (object[key] == null) { - object[key] = iterable[key]; - } - } - } - } - return object; - }; - - // By default, Underscore uses ERB-style template delimiters, change the - // following template settings to use alternative delimiters. - _.templateSettings = { - evaluate : /<%([\s\S]+?)%>/g, - interpolate : /<%=([\s\S]+?)%>/g, - escape : /<%-([\s\S]+?)%>/g - }; - - // When customizing `templateSettings`, if you don't want to define an - // interpolation, evaluation or escaping regex, we need one that is - // guaranteed not to match. - var noMatch = /(.)^/; - - // Certain characters need to be escaped so that they can be put into a - // string literal. - var escapes = { - "'": "'", - '\\': '\\', - '\r': 'r', - '\n': 'n', - '\t': 't', - '\u2028': 'u2028', - '\u2029': 'u2029' - }; - - var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; - - // JavaScript micro-templating, similar to John Resig's implementation. - // Underscore templating handles arbitrary delimiters, preserves whitespace, - // and correctly escapes quotes within interpolated code. - _.template = function(text, data, settings) { - var render; - settings = _.defaults({}, settings, _.templateSettings); - - // Combine delimiters into one regular expression via alternation. - var matcher = new RegExp([ - (settings.escape || noMatch).source, - (settings.interpolate || noMatch).source, - (settings.evaluate || noMatch).source - ].join('|') + '|$', 'g'); - - // Compile the template source, escaping string literals appropriately. - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset) - .replace(escaper, function(match) { return '\\' + escapes[match]; }); - - if (escape) { - source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; - } - if (interpolate) { - source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; - } - if (evaluate) { - source += "';\n" + evaluate + "\n__p+='"; - } - index = offset + match.length; - return match; - }); - source += "';\n"; - - // If a variable is not specified, place data values in local scope. - if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; - - source = "var __t,__p='',__j=Array.prototype.join," + - "print=function(){__p+=__j.call(arguments,'');};\n" + - source + "return __p;\n"; - - try { - render = new Function(settings.variable || 'obj', '_', source); - } catch (e) { - e.source = source; - throw e; - } - - if (data) return render(data, _); - var template = function(data) { - return render.call(this, data, _); - }; - - // Provide the compiled function source as a convenience for precompilation. - template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; - - return template; - }; - - return _; - })({}); - - if (location.hostname === 'todomvc.com') { - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); - ga('create', 'UA-31081062-1', 'auto'); - ga('send', 'pageview'); - } - /* jshint ignore:end */ - - function redirect() { - if (location.hostname === 'tastejs.github.io') { - location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com'); - } - } - - function findRoot() { - var base = location.href.indexOf('examples/'); - return location.href.substr(0, base); - } - - function getFile(file, callback) { - if (!location.host) { - return console.info('Miss the info bar? Run TodoMVC from a server to avoid a cross-origin error.'); - } - - var xhr = new XMLHttpRequest(); - - xhr.open('GET', findRoot() + file, true); - xhr.send(); - - xhr.onload = function () { - if (xhr.status === 200 && callback) { - callback(xhr.responseText); - } - }; - } - - function Learn(learnJSON, config) { - if (!(this instanceof Learn)) { - return new Learn(learnJSON, config); - } - - var template, framework; - - if (typeof learnJSON !== 'object') { - try { - learnJSON = JSON.parse(learnJSON); - } catch (e) { - return; - } - } - - if (config) { - template = config.template; - framework = config.framework; - } - - if (!template && learnJSON.templates) { - template = learnJSON.templates.todomvc; - } - - if (!framework && document.querySelector('[data-framework]')) { - framework = document.querySelector('[data-framework]').dataset.framework; - } - - this.template = template; - - if (learnJSON.backend) { - this.frameworkJSON = learnJSON.backend; - this.frameworkJSON.issueLabel = framework; - this.append({ - backend: true - }); - } else if (learnJSON[framework]) { - this.frameworkJSON = learnJSON[framework]; - this.frameworkJSON.issueLabel = framework; - this.append(); - } - - this.fetchIssueCount(); - } - - Learn.prototype.append = function (opts) { - var aside = document.createElement('aside'); - aside.innerHTML = _.template(this.template, this.frameworkJSON); - aside.className = 'learn'; - - if (opts && opts.backend) { - // Remove demo link - var sourceLinks = aside.querySelector('.source-links'); - var heading = sourceLinks.firstElementChild; - var sourceLink = sourceLinks.lastElementChild; - // Correct link path - var href = sourceLink.getAttribute('href'); - sourceLink.setAttribute('href', href.substr(href.lastIndexOf('http'))); - sourceLinks.innerHTML = heading.outerHTML + sourceLink.outerHTML; - } else { - // Localize demo links - var demoLinks = aside.querySelectorAll('.demo-link'); - Array.prototype.forEach.call(demoLinks, function (demoLink) { - if (demoLink.getAttribute('href').substr(0, 4) !== 'http') { - demoLink.setAttribute('href', findRoot() + demoLink.getAttribute('href')); - } - }); - } - - document.body.className = (document.body.className + ' learn-bar').trim(); - document.body.insertAdjacentHTML('afterBegin', aside.outerHTML); - }; - - Learn.prototype.fetchIssueCount = function () { - var issueLink = document.getElementById('issue-count-link'); - if (issueLink) { - var url = issueLink.href.replace('https://github.com', 'https://api.github.com/repos'); - var xhr = new XMLHttpRequest(); - xhr.open('GET', url, true); - xhr.onload = function (e) { - var parsedResponse = JSON.parse(e.target.responseText); - if (parsedResponse instanceof Array) { - var count = parsedResponse.length; - if (count !== 0) { - issueLink.innerHTML = 'This app has ' + count + ' open issues'; - document.getElementById('issue-count').style.display = 'inline'; - } - } - }; - xhr.send(); - } - }; - - redirect(); - getFile('learn.json', Learn); -})(); diff --git a/cypress/testapp/bundle.js b/cypress/testapp/bundle.js deleted file mode 100644 index 37a8ebb..0000000 --- a/cypress/testapp/bundle.js +++ /dev/null @@ -1,57 +0,0 @@ -var $jscomp={scope:{},getGlobal:function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global?global:a}};$jscomp.global=$jscomp.getGlobal(this);$jscomp.initSymbol=function(){$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol);$jscomp.initSymbol=function(){}};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(a){return"jscomp_symbol_"+a+$jscomp.symbolCounter_++}; -$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();$jscomp.global.Symbol.iterator||($jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));$jscomp.initSymbolIterator=function(){}};$jscomp.makeIterator=function(a){$jscomp.initSymbolIterator();if(a[$jscomp.global.Symbol.iterator])return a[$jscomp.global.Symbol.iterator]();var b=0;return{next:function(){return b==a.length?{done:!0}:{done:!1,value:a[b++]}}}}; -$jscomp.arrayFromIterator=function(a){for(var b,c=[];!(b=a.next()).done;)c.push(b.value);return c};$jscomp.arrayFromIterable=function(a){return a instanceof Array?a:$jscomp.arrayFromIterator($jscomp.makeIterator(a))}; -$jscomp.inherits=function(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a;for(var d in b)if($jscomp.global.Object.defineProperties){var e=$jscomp.global.Object.getOwnPropertyDescriptor(b,d);e&&$jscomp.global.Object.defineProperty(a,d,e)}else a[d]=b[d]};$jscomp.array=$jscomp.array||{};$jscomp.array.done_=function(){return{done:!0,value:void 0}}; -$jscomp.array.arrayIterator_=function(a,b){a instanceof String&&(a=String(a));var c=0;$jscomp.initSymbol();$jscomp.initSymbolIterator();var d={},e=(d.next=function(){if(c