diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ace6778262..b49fc6eaa6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,6 +9,7 @@ Thanks for taking the time to contribute! :smile: - [Writing Documentation](#writing-documentation) - [Links](#links) - [Adding Examples](#adding-examples) + - [Adding Plugins](#adding-plugins) - [Committing Code](#committing-code) - [Linting](#linting) - [Pull Requests](#pull-requests) @@ -61,7 +62,7 @@ variable set `DEBUG=docs npm run build` ### Adding Examples - To add an blog, talk, or podcast to our docs, just add your data to the corresponding [blogs.yml](https://github.com/cypress-io/cypress-documentation/blob/develop/source/_data/blogs.yml), [talks.yml](https://github.com/cypress-io/cypress-documentation/blob/develop/source/_data/talks.yml), or [podcasts.yml](https://github.com/cypress-io/cypress-documentation/blob/develop/source/_data/podcasts.yml) file. + To add an blog, talk, or podcast to our docs, submit a [pull request](#Pull-Requests) with your data added to the corresponding [blogs.yml](https://github.com/cypress-io/cypress-documentation/blob/develop/source/_data/blogs.yml), [talks.yml](https://github.com/cypress-io/cypress-documentation/blob/develop/source/_data/talks.yml), or [podcasts.yml](https://github.com/cypress-io/cypress-documentation/blob/develop/source/_data/podcasts.yml) file. Add an associating image with the example within the [`source/img/examples`](/source/img/examples) directory. Each image should be resolution **715w x 480h**. Reference the image in the markdown document as follows: @@ -69,7 +70,9 @@ Add an associating image with the example within the [`source/img/examples`](/so {% img /img/examples/name-of-file.jpg "alt text describing img" %} ``` -To add anything else to an example page, the documents outlining examples are within the [`source/examples`](/source/examples) directory. Each document is written in markdown with a little bit of [Hexo flair](https://hexo.io/docs/tag-plugins.html). To add an example to a document, just try to follow the formatting of any previous examples in the markdown file. +### Adding Plugins + +To add a plugin, submit a [pull request](#Pull-Requests) with the corresponding data added to the [plugins.yml](https://github.com/cypress-io/cypress-documentation/blob/develop/source/_data/plugins.yml) file. Your plugin should have a name, description, link to the plugins code, and any keywords. ## Commiting Code @@ -80,8 +83,7 @@ Danger 📛: because we are minifying client side code using a [Hexo plugin](htt ### Pull Requests -You should push your local changes to your forked GitHub repository and then -open a pull request from your repo to the `cypress-io/cypress-documentation` repo. +You should push your local changes to your forked GitHub repository and then open a pull request from your repo to the `cypress-io/cypress-documentation` repo. - The pull request should be from your repository to the `develop` branch in `cypress-io/cypress-documentation` - When opening a PR for a specific issue already open, please use the `address #[issue number]` or `closes #[issue number]` syntax in the pull request description. diff --git a/_config.yml b/_config.yml index 263ac1a254..755452f34e 100644 --- a/_config.yml +++ b/_config.yml @@ -57,6 +57,8 @@ alias: tutorials/test-a-react-todo-app/: tutorials/test-a-react-todo-app/introduction-to-tutorials.html tutorials/: tutorials/test-a-react-todo-app/introduction-to-tutorials.html + plugins/: plugins/index.html + examples/index.html: examples/recipes/unit-testing-recipe.html dashboard/index.html: guides/core-concepts/dashboard-service.html diff --git a/source/_data/main-menu.yml b/source/_data/main-menu.yml index 511752357d..588ca06313 100644 --- a/source/_data/main-menu.yml +++ b/source/_data/main-menu.yml @@ -1,5 +1,6 @@ guides: /guides/overview/why-cypress.html api: /api/introduction/api.html tutorials: /tutorials/test-a-react-todo-app/introduction-to-tutorials.html +plugins: /plugins/ examples: /examples/recipes/unit-testing-recipe.html faq: /faq/questions/general-questions-faq.html diff --git a/source/_data/plugins.yml b/source/_data/plugins.yml new file mode 100644 index 0000000000..0f43dd5027 --- /dev/null +++ b/source/_data/plugins.yml @@ -0,0 +1,16 @@ +- name: Preprocessors + plugins: + - name: Browserify + description: For bundling JavaScript via browserify. This is the default preprocessor that's built into Cypress. + link: https://github.com/cypress-io/cypress-browserify-preprocessor + keywords: [browserify] + + - name: Webpack + description: For bundling JavaScript via webpack. + link: https://github.com/cypress-io/cypress-webpack-preprocessor + keywords: [webpack] + + - name: Watch + description: Simple preprocessor that only watches files. Useful as an example reference. + link: https://github.com/cypress-io/cypress-watch-preprocessor + keywords: [file-watcher] diff --git a/source/_data/sidebar.yml b/source/_data/sidebar.yml index d6989fd465..61db00741f 100644 --- a/source/_data/sidebar.yml +++ b/source/_data/sidebar.yml @@ -26,6 +26,7 @@ guides: launching-browsers: launching-browsers.html web-security: web-security.html reporters: reporters.html + plugins-guide: plugins-guide.html # advanced-cypress: # the-cypress-workflow: the-cypress-workflow.html # coming-from-selenium: coming-from-selenium.html @@ -147,6 +148,9 @@ api: env: env.html cypress-log: cypress-log.html cypress-server: cypress-server.html + plugins: + writing-a-plugin: writing-a-plugin.html + preprocessors-api: preprocessors-api.html tutorials: test-a-react-todo-app: @@ -156,6 +160,9 @@ tutorials: react-todo-form-submission: react-todo-form-submission.html react-todo-app-init: react-todo-app-init.html +plugins: + plugins: index.html + examples: recipes: unit-testing-recipe: unit-testing-recipe.html diff --git a/source/api/commands/fixture.md b/source/api/commands/fixture.md index b7e2271974..c1f5c68b92 100644 --- a/source/api/commands/fixture.md +++ b/source/api/commands/fixture.md @@ -29,7 +29,7 @@ cy.fixture('logo.png').then((logo) => { **{% fa fa-angle-right %} filePath** ***(String)*** -A path to a file within the {% url `fixturesFolder` configuration#Folders %} , which defaults to `cypress/fixtures`. +A path to a file within the {% url `fixturesFolder` configuration#Folders-Files %} , which defaults to `cypress/fixtures`. You can nest fixtures within folders and reference them by defining the path from the fixturesFolder: @@ -77,7 +77,7 @@ cy.fixture('users.json').as('usersData') ***Omit the fixture file's extension*** -When no extension is passed to `cy.fixture()`, Cypress will search for files with the specified name within the {% url `fixturesFolder` configuration#Folders %} (which defaults to `cypress/fixtures`) and resolve the first one. +When no extension is passed to `cy.fixture()`, Cypress will search for files with the specified name within the {% url `fixturesFolder` configuration#Folders-Files %} (which defaults to `cypress/fixtures`) and resolve the first one. ```javascript cy.fixture('admin').as('adminJSON') diff --git a/source/api/commands/screenshot.md b/source/api/commands/screenshot.md index e2cf566726..7455d94329 100644 --- a/source/api/commands/screenshot.md +++ b/source/api/commands/screenshot.md @@ -45,7 +45,7 @@ Option | Default | Description The screenshot will be stored in the `cypress/screenshots` folder by default. -You can change the directory where screenshots are saved in your {% url 'configuration' configuration#Folders %}. +You can change the directory where screenshots are saved in your {% url 'configuration' configuration#Folders-Files %}. ## No Args diff --git a/source/api/introduction/api.md b/source/api/introduction/api.md index 1c802fb3de..c638dbd401 100644 --- a/source/api/introduction/api.md +++ b/source/api/introduction/api.md @@ -13,6 +13,8 @@ comments: false - **{% url 'Cypress API:' custom-commands %}** Configure the behavior of how Cypress works internally. You can do things like access Environment Variables, change configuration, create custom commands, and more. +- **{% url 'Plugins:' writing-a-plugin %}** Write a plugin to modify and extend the behavior of Cypress. + # Rules Each document attempts to cover the essentials of each method including: diff --git a/source/api/plugins/preprocessors-api.md b/source/api/plugins/preprocessors-api.md new file mode 100644 index 0000000000..1125e36399 --- /dev/null +++ b/source/api/plugins/preprocessors-api.md @@ -0,0 +1,136 @@ +--- +title: Preprocessors API +comments: false +--- + +A preprocessor is the plugin responsible for preparing a {% url "support file" writing-and-organizing-tests#Support-file %} or a {% url "test file" writing-and-organizing-tests#Test-files %} for the browser. + +A preprocessor could transpile your file from another language (CoffeeScript or ClojureScript) or from a newer version of JavaScript (ES2017). + +A preprocessor also typically watches the source files for changes, processes them again, and then notifies Cypress to re-run the tests. + +# Examples + +We've created three preprocessors as examples for you to look at. These are fully functioning preprocessors. + +The code contains comments that explain how it utilizes the preprocessor API. + +* {% url 'Browserify Preprocessor' https://github.com/cypress-io/cypress-browserify-preprocessor %} +* {% url 'Webpack Preprocessor' https://github.com/cypress-io/cypress-webpack-preprocessor %} +* {% url 'Watch Preprocessor' https://github.com/cypress-io/cypress-watch-preprocessor %} + +# Defaults + +By default, Cypress comes packaged with the **Browserify Preprocessor** already installed. + +The Browserify Preprocessor handles: + +- CoffeeScript `1.x.x` +- ES2015 via Babel +- JSX and CJSX +- Watching and caching files + +The exact default configuration options {% url 'can be found here' https://github.com/cypress-io/cypress-browserify-preprocessor#browserifyoptions %}. + +{% note info %} +Are you looking to change the **default options** for Browserify? +{% endnote %} + +Changing the Browserify options lets you: + +- Add your own Babel plugins +- Add support for Typescript +- Add support for CoffeeScript `2.x.x` + +Please read this link in the {% url 'browserify preprocessor' https://github.com/cypress-io/cypress-browserify-preprocessor#modifying-default-options %} repo for instructions on modifying these. + +# Usage + +The use a preprocessor, you should bind to the `file:preprocessor` event in your {% url "`pluginsFile`" configuration#Folders-Files %}: + +```javascript +// plugins file +module.exports = (on, config) => { + on('file:preprocessor', (file) => { + // ... + }) +} +``` + +***The callback function should return one of the following:*** + +* A promise\* that eventually resolves the path to the **built file**\*\*. +* A promise\* that eventually rejects with an error that occurred during processing. + +> \* The promise should resolve only after the file has completed writing to disk. The promise resolving is a signal that the file is ready to be served to the browser. + +--- + +> \*\* The built file is the file that is created by the preprocessor that will eventually be served to the browser. + +> If, for example, the source file is `spec.coffee`, the preprocessor should: +1. Compile the CoffeeScript into JavaScript `spec.js` +2. Write that JavaScript file to disk (example: `/Users/foo/tmp/spec.js`) +3. Resolve with the absolute path to that file: `/Users/foo/tmp/spec.js` + +{% note warning %} +This callback function can and *will* be called multiple times with the same `filePath`. + +The callback function is called any time a file is requested by the browser. This happens on each run of the tests. + +Make sure not to start a new watcher each time it is called. Instead, cache the watcher and, on subsequent calls, return a promise that resolves when the latest version of the file has been processed. +{% endnote %} + +# Req object + +The `file` object passed to the callback function has the following properties: + +Property | Description +--------- | ---------- +`filePath` | The full path to the source file. +`outputPath` | The suggested path for saving the preprocessed file to disk. This is unique to the source file. A preprocessor can choose to write the file elsewhere, but Cypress automatically provides you this value as a convenient default. +`shouldWatch` | A boolean indicating whether the preprocessor should watch for file changes or not. + +# Req events + +The `file` object passed to the callback function is an [Event Emitter](https://nodejs.org/api/events.html#events_class_eventemitter). + +***Receiving 'close' event*** + +When the spec being run is closed or the project is closed, the `close` event will be emitted. The preprocessor should do any necessary cleanup in this function, like closing the watcher when watching. + +```javascript +// example +const watcher = fs.watch(filePath, /* ... */) + +file.on('close', () => { + watcher.close() +}) +``` + +***Sending 'rerun' event*** + +If watching for file changes, emit `rerun` after a file has finished being processed to let Cypress know to rerun the tests. + +```javascript +// example +fs.watch(filePath, () => { + file.emit('rerun') +}) +``` + +# Publishing + +Publish preprocessors to [npm](https://www.npmjs.com/) with the naming convention `cypress-*-preprocessor` (e.g. cypress-clojurescript-preprocessor). + +Use the following npm keywords: + +```json +"keywords": [ + "cypress", + "cypress-plugin", + "cypress-preprocessor" +] +``` + +Feel free to submit your published plugins to our {% url "list of plugins" plugins %}. diff --git a/source/api/plugins/writing-a-plugin.md b/source/api/plugins/writing-a-plugin.md new file mode 100644 index 0000000000..67aae9e1e2 --- /dev/null +++ b/source/api/plugins/writing-a-plugin.md @@ -0,0 +1,146 @@ +--- +title: Writing a Plugin +comments: false +--- + +The Plugins API allows you to hook into and extend Cypress behavior. + +{% note info %} +**Note:** This document assumes you have read the {% url 'Plugins Guide' plugins-guide %}. +{% endnote %} + +# Plugins API + +To get started, open up this file: + +```text +cypress/plugins/index.js +``` + +{% note info %} +By default Cypress seeds this file for new projects, but if you have an existing project just create this file yourself. +{% endnote %} + +The plugins file must export a function with the following signature: + +```javascript +// cypress/plugins/index.js + +// export a function +module.exports = (on, config) => { + // configure plugins here +} +``` + +The exported function is called whenever a project is opened either with {% url "`cypress open`" command-line#cypress-open %} or {% url "`cypress run`" command-line#cypress-run %}. + +Your function will receive 2 arguments: `on` and `config`. + +## on + +`on` is a function that you will use to register to various **events** that Cypress exposes. + +Registering to an event looks like this: + +```javascript +module.exports = (on, config) => { + on('', (arg1, arg2) => { + // plugin stuff here + }) +} +``` + +Each event documents its own argument signature. To understand how to use them, please {% urlHash 'refer to docs for each one' 'List-of-events' %}. + +## config + +`config` is the resolved [Cypress configuration](https://on.cypress.io/guides/configuration) of the opened project. + +This configuration contains all of the values that get passed into the browser for your project. + +Some plugins may utilize or require these values, so they can take certain actions based on the configuration. + +{% url 'For a comprehensive list of all configuration values look here.' https://github.com/cypress-io/cypress/blob/master/packages/server/lib/config.coffee %} + +## List of events + +***The following events are available:*** + +Event | Description +--- | --- +{% url `file:preprocessor` preprocessors-api %} | Occurs when a spec or spec-related file needs to be transpiled for the browser. + +{% note warning "More Coming Soon" %} +The Plugins API is brand new. + +We have many new plugin events {% issue 684 'we are adding' %}. +{% endnote %} + +# Execution context + +Your `pluginsFile` is invoked when Cypress opens a project. + +Cypress does this by spawning an independent `child_process` which then `requires` in your `pluginsFile`. This is similar to the way Visual Studio Code or Atom works. + +You will need to keep in mind it is **Cypress who is requiring your file** - not your local project, not your local node version, and not anything else under your control. + +Because of this, this global context and the version of node is controlled by Cypress. + +{% note warning %} +Your code must be compatible with the {% url 'version of node' https://github.com/cypress-io/cypress/blob/master/.node-version %} that comes with Cypress! +{% endnote %} + +You can find the current node version we use {% url 'here' https://github.com/cypress-io/cypress/blob/master/.node-version %}. + +This node version gets updated regularly (next version will be in the `8.x.x` range) so you'll likely be able to use all the latest ES7 features. + +## NPM modules + +When Cypress executes your `pluginsFile` it will execute with `process.cwd()` set to your project's path. Additionally - you will be able to `require` **any node module** you have installed. + +You can also `require` local files relative to your project. + +**For example, if your `package.json` looked like this:** + +```js +{ + "name": "My Project", + "dependencies": { + "debug": "x.x.x" + }, + "devDependencies": { + "lodash": "x.x.x" + } +} +``` + +**Then you could do any of the following in your `pluginsFile`:** + +```js +// cypress/plugins/index.js + +const _ = require('lodash') // yup, dev dependencies +const path = require('path') // yup, built in node modules +const debug = require('debug') // yup, dependencies +const User = require('../../lib/models/user') // yup, relative local modules + +console.log(__dirname) // /Users/janelane/Dev/my-project/cypress/plugins/index.js + +console.log(process.cwd()) // /Users/janelane/Dev/my-project +``` + +# Error handling + +Cypress spawns your `pluginsFile` in its own child process so it is isolated away from the context that Cypress itself runs in. That means you cannot accidentally modify or change Cypress' own execution in any way. + +If your `pluginsFile` has an uncaught exception, an unhandled rejection from a promise, a syntax error, or anything else - we will automatically catch those and display them to you inside of the console and even in the Test Runner itself. + +Errors from your plugins *will not crash* Cypress. + +# File changes + +Normally when writing code in Node, you typically have to restart the process after changing any files. + +With Cypress, we automatically watch your `pluginsFile` and any changes made will take effect immediately. We will read the file in and execute the exported function again. + +This enables you to iterate on plugin code even with Cypress already running. diff --git a/source/guides/core-concepts/dashboard-service.md b/source/guides/core-concepts/dashboard-service.md index 8b5c024eed..bd704da0c5 100644 --- a/source/guides/core-concepts/dashboard-service.md +++ b/source/guides/core-concepts/dashboard-service.md @@ -79,12 +79,12 @@ Make sure you {% url "install" installing-cypress %} and {% url "open" installin 10. Within {% url 'Continuous Integration' continuous-integration %}, or from your local computer's terminal, pass the displayed {% urlHash "Record Key" Identification %} while running the {% url '`cypress run`' command-line#cypress-run %} command. - Provide record key directly: ```shell - cypress run --record --key abc-key-123 + cypress run --record --key <record key> ``` - Or set record key as environment variable ```shell - export CYPRESS_RECORD_KEY=abc-key-123 + export CYPRESS_RECORD_KEY=<record key> ``` ```shell cypress run --record diff --git a/source/guides/core-concepts/writing-and-organizing-tests.md b/source/guides/core-concepts/writing-and-organizing-tests.md index 0e93ba64b6..22e88d753a 100644 --- a/source/guides/core-concepts/writing-and-organizing-tests.md +++ b/source/guides/core-concepts/writing-and-organizing-tests.md @@ -24,6 +24,9 @@ After adding a new project, Cypress will automatically scaffold out a suggested /integration - example_spec.js + /plugins + - index.js + /support - commands.js - index.js @@ -35,7 +38,13 @@ While Cypress allows to configure where your tests, fixtures, and support files You can modify the folder configuration in your `cypress.json`. See {% url 'configuration' configuration %} for more detail. -## Test Files +## Fixture Files + +Fixtures are used as external pieces of static data that can be used by your tests. + +You would typically use them with the {% url `cy.fixture()` fixture %} command and most often when you're stubbing {% url 'Network Requests' network-requests %}. + +## Test files Test files may be written as: @@ -54,7 +63,13 @@ To see an example of every command used in Cypress, open the {% url "`example_sp To start writing tests for your app, simply create a new file like `app_spec.js` within your `cypress/integration` folder. Refresh your tests list in the Cypress Test Runner and your new file should have appeared in the list. -## Support Files +## Plugin Files + +By default Cypress will automatically include the plugins file `cypress/plugins/index.js` **before** every single spec file it runs. We do this purely as a convenience mechanism so you don't have to import this file in every single one of your spec files. + +{% url "Read more about using plugins to extend Cypress behavior." plugins-guide %} + +## Support file By default Cypress will automatically include the support file `cypress/support/index.js` **before** every single spec file it runs. We do this purely as a convenience mechanism so you don't have to import this file in every single one of your spec files. @@ -68,11 +83,7 @@ We automatically seed you an example support file, which has several commented o Our {% url 'Extending Cypress recipes' extending-cypress-recipe %} show you how to modify the support file. {% endnote %} -## Fixture Files -Fixtures are used as external pieces of static data that can be used by your tests. - -You would typically use them with the {% url `cy.fixture()` fixture %} command and most often when you're stubbing {% url 'Network Requests' network-requests %}. # How to Write Tests diff --git a/source/guides/guides/plugins-guide.md b/source/guides/guides/plugins-guide.md new file mode 100644 index 0000000000..c70b7db487 --- /dev/null +++ b/source/guides/guides/plugins-guide.md @@ -0,0 +1,93 @@ +--- +title: Plugins +comments: false +--- + +Plugins enable you to tap into, modify, or extend the internal behavior of Cypress. + +Normally, as a user, all of your test code, your application, and Cypress commands are executed in the browser. But Cypress is also a **Node.js** process that plugins can use. + +> Plugins enable you to tap into the `node` process running outside of the browser. + +Plugins are a "seam" for you to write your own custom code that executes during particular stages of the Cypress lifecycle. + +{% note info "New Projects" %} +When new projects are added to Cypress we will automatically seed them with a basic plugins file. + +By default Cypress will create a plugins file at: `cypress/plugins/index.js`. + +This is configurable in your `cypress.json` with the {% url "`pluginsFile`" configuration#Folders-Files %} option. +{% endnote %} + +# Plugin types + +## Preprocessors + +As of today we offer a single plugin event: `file:preprocessor`. This event is used to customize how your test code is transpiled and sent to the browser. By default Cypress handles CoffeeScript and ES6 using `babel` and then uses `browserify` to package it for the browser. + +You can use the `file:preprocessor` event to do things like: + +- Add TypeScript support. +- Add the latest ES* support. +- Write your test code in ClosureScript. +- Customize the `babel` settings to add your own plugins. +- Swap out `browserify` for `webpack` or anything else. + +Check out our {% url 'File Preprocessor API docs' preprocessors-api %} which describe how to use this event. + +# List of plugins + +Cypress maintains an official list of plugins created by us and the community. You can `npm install` any of the plugins listed below: + +{% url 'Our official list of Cypress plugins.' plugins %} + +# Installing plugins + +Plugins from our {% url 'official list' plugins %} are just NPM modules. This enables them to be versioned and updated separately without needing to update Cypress itself. + +You can install any published plugin using NPM: + +```shell +npm install <plugin name> --save-dev +``` + +# Using a plugin + +Whether you install an NPM module, or just want to write your own code - you should do all of that in this file: + +```text +cypress/plugins/index.js +``` + +{% note info %} +By default Cypress seeds this file for new projects, but if you have an existing project just create this file yourself. +{% endnote %} + +Inside of this file, you will export a function. Cypress will call this function, pass you the project's configuration, and enable you to bind to the events exposed. + +```javascript +// cypress/plugins/index.js + +// export a function +module.exports = (on, config) => { + + // bind to the event we care about + on('', (arg1, arg2) => { + // plugin stuff here + }) +} +``` + +Check out our {% url 'Writing a Plugin doc' writing-a-plugin %} which describes how to write plugins. + +{% note warning "Node version" %} + +Keep in mind - code executed in plugins is executed **by the node version** that comes bundled in Cypress itself. + +This version of node has **nothing to do** with your locally installed versions. Therefore you have to write node code which is compatible with this version. + +You can find the current node version we use {% url 'here' https://github.com/cypress-io/cypress/blob/master/.node-version %}. + +This node version gets updated regularly (next version will be in the `8.x.x` range) so you'll likely be able to use all the latest ES7 features. + +{% endnote %} diff --git a/source/guides/references/best-practices.md b/source/guides/references/best-practices.md index cc37f0e680..2689b1eeca 100644 --- a/source/guides/references/best-practices.md +++ b/source/guides/references/best-practices.md @@ -426,7 +426,7 @@ The simplest solution here is to move your reset code to **before** the test run Code put in a `before` or `beforeEach` hook will **always** run prior to the test - even if you refreshed Cypress in the middle of an existing one! -This is also a great opportunity to use {%url 'root level hooks in mocha' https://github.com/mochajs/mochajs.github.io/blob/master/index.md#root-level-hooks %}. A perfect place to put these is in the {% url "`cypress/support/index.js` file" writing-and-organizing-tests#Support-Files %} because it is always evaluated before any test code from your spec files. +This is also a great opportunity to use {%url 'root level hooks in mocha' https://github.com/mochajs/mochajs.github.io/blob/master/index.md#root-level-hooks %}. A perfect place to put these is in the {% url "`cypress/support/index.js` file" writing-and-organizing-tests#Support-file %} because it is always evaluated before any test code from your spec files. **Hooks you add to the root will always run on all suites!** diff --git a/source/guides/references/changelog.md b/source/guides/references/changelog.md index f9fec1ddd8..da1e83d5ac 100644 --- a/source/guides/references/changelog.md +++ b/source/guides/references/changelog.md @@ -597,7 +597,7 @@ Fixed {% url "`.type()`" type %} not firing `input` event for {% url "React" htt **Breaking Changes:** -- Previously, we auto-magically included all files within {% url '`cypress/support`' writing-and-organizing-tests#Folder-Structure %}. This has now {% url 'gone away' error-messages %} and we've simplified this to automatically including a single `cypress/support/index.js` file. That single file acts as the entry point meaning you should `import` or `require` the other support files you'd like to include. Although this is still "automatic" it's much less magical and we'll be updating all of our docs to reflect this. The purpose of `cypress/support` hasn't really changed, just the implementation of it has. We will automatically seed a `cypress/support/index.js` file for you (even on existing projects). The file location of `cypress/support/index.js` can be changed with the new {% url `supportFile` configuration#Folders %} option in your `cypress.json`. This feature can also be turned off by specifying `supportFile: false`. +- Previously, we auto-magically included all files within {% url '`cypress/support`' writing-and-organizing-tests#Folder-Structure %}. This has now {% url 'gone away' error-messages %} and we've simplified this to automatically including a single `cypress/support/index.js` file. That single file acts as the entry point meaning you should `import` or `require` the other support files you'd like to include. Although this is still "automatic" it's much less magical and we'll be updating all of our docs to reflect this. The purpose of `cypress/support` hasn't really changed, just the implementation of it has. We will automatically seed a `cypress/support/index.js` file for you (even on existing projects). The file location of `cypress/support/index.js` can be changed with the new {% url `supportFile` configuration#Folders-Files %} option in your `cypress.json`. This feature can also be turned off by specifying `supportFile: false`. **Features:** @@ -609,7 +609,7 @@ Fixed {% url "`.type()`" type %} not firing `input` event for {% url "React" htt - We improved the logic around when and if we scaffold files on a new project. We're much smarter about this and not generating these forcibly every time. Fixes {% issue 285 '#285' %}. - Simplified handling of support files and made them less "magical". Fixes {% issue 286 '#286' %}. -- Renamed `supportFolder` to {% url `supportFile` configuration#Folders %} in `cypress.json`. We will automatically rename your `cypress.json` if this property was present on update. +- Renamed `supportFolder` to {% url `supportFile` configuration#Folders-Files %} in `cypress.json`. We will automatically rename your `cypress.json` if this property was present on update. # 0.17.12 @@ -1162,9 +1162,9 @@ Fixed {% url "`.type()`" type %} not firing `input` event for {% url "React" htt **Breaking Changes:** - Cypress no longer looks at your `tests` directory for test files. Now, by default, it looks in the `cypress/integration` directory. -- We've removed the configuration option `testFolder` and renamed it to {% url `integrationFolder` configuration#Folders %} inside of the `cypress.json`. +- We've removed the configuration option `testFolder` and renamed it to {% url `integrationFolder` configuration#Folders-Files %} inside of the `cypress.json`. - We've renamed the `cypress` npm package to be `cypress-cli`. You'll see a giant deprecation warning until your scripts have been updated to reference `cypress-cli`.. You can also uninstall the `cypress` npm package. -- Added new {% url `fileServerFolder` configuration#Folders %} configuration option that can mount a directory other than your project root when using Cypress as a web server. +- Added new {% url `fileServerFolder` configuration#Folders-Files %} configuration option that can mount a directory other than your project root when using Cypress as a web server. **Misc:** diff --git a/source/guides/references/configuration.md b/source/guides/references/configuration.md index 1b4d1a4876..f052573518 100644 --- a/source/guides/references/configuration.md +++ b/source/guides/references/configuration.md @@ -43,15 +43,16 @@ Option | Default | Description `requestTimeout` | `5000` | Time, in milliseconds, to wait for an XHR request to go out in a {% url `cy.wait()` wait %} command `responseTimeout` | `30000` | Time, in milliseconds, to wait until a response in a {% url `cy.request()` request %}, {% url `cy.wait()` wait %}, {% url `cy.fixture()` fixture %}, {% url `cy.getCookie()` getcookie %}, {% url `cy.getCookies()` getcookies %}, {% url `cy.setCookie()` setcookie %}, {% url `cy.clearCookie()` clearcookie %}, {% url `cy.clearCookies()` clearcookies %}, and {% url `cy.screenshot()` screenshot %} commands -## Folders +## Folders / Files Option | Default | Description ----- | ---- | ---- `fileServerFolder` | root project folder |Path to folder where application files will attempt to be served from `fixturesFolder` | `cypress/fixtures` | Path to folder containing fixture files (Pass `false` to disable) `integrationFolder` | `cypress/integration` | Path to folder containing integration test files +`pluginsFile` | `cypress/plugins/index.js` | Path to plugins file. (Pass `false` to disable) `screenshotsFolder` | `cypress/screenshots` | Path to folder where screenshots will be saved from {% url `cy.screenshot()` screenshot %} command or after a headless or CI run's test failure -`supportFile` | `cypress/support` | Path to file to load before test files load. This file is compiled and bundled. (Pass `false` to disable) +`supportFile` | `cypress/support/index.js` | Path to file to load before test files load. This file is compiled and bundled. (Pass `false` to disable) `videosFolder` | `cypress/videos` | Path to folder where videos will be saved after a headless or CI run ## Screenshots diff --git a/source/guides/references/error-messages.md b/source/guides/references/error-messages.md index 6c7b16bea2..4433746745 100644 --- a/source/guides/references/error-messages.md +++ b/source/guides/references/error-messages.md @@ -29,7 +29,7 @@ When the error is fixed in your test file, your tests will automatically re-run. ## {% fa fa-exclamation-triangle red %} Support file missing or invalid -The `supportFolder` option was removed from Cypress in version {% url `0.18.0` changelog#0-18-0 %} and was replaced by module support and the {% url `supportFile` configuration#Folders %} configuration option. +The `supportFolder` option was removed from Cypress in version {% url `0.18.0` changelog#0-18-0 %} and was replaced by module support and the {% url `supportFile` configuration#Folders-Files %} configuration option. Cypress used to automatically include any scripts in the `supportFolder` before your test files. However, automatically including all the files in a certain directory is somewhat magical and unintuitive, and requires creating globals for the purpose of utility functions. @@ -49,14 +49,14 @@ it('uses modules', function () { ***Use supportFile to load scripts before your test code*** -It's still useful to load a setup file before your test code. If you are setting Cypress defaults or utilizing custom Cypress commands, instead of needing to import/require those defaults/commands in every test file, you can use the {% url `supportFile` configuration#Folders %} configuration option. +It's still useful to load a setup file before your test code. If you are setting Cypress defaults or utilizing custom Cypress commands, instead of needing to import/require those defaults/commands in every test file, you can use the {% url `supportFile` configuration#Folders-Files %} configuration option. -To include code before your test files, set the {% url `supportFile` configuration#Folders %} path. By default, {% url `supportFile` configuration#Folders %} is set to look for one of the following files: +To include code before your test files, set the {% url `supportFile` configuration#Folders-Files %} path. By default, {% url `supportFile` configuration#Folders-Files %} is set to look for one of the following files: * `cypress/support/index.js` * `cypress/support/index.coffee` -Just like with your test files, the {% url `supportFile` configuration#Folders %} can use ES2015+ (or CoffeeScript) and modules, so you can import/require other files as needed. +Just like with your test files, the {% url `supportFile` configuration#Folders-Files %} can use ES2015+ (or CoffeeScript) and modules, so you can import/require other files as needed. # Command Errors diff --git a/source/plugins/index.md b/source/plugins/index.md new file mode 100644 index 0000000000..676366b392 --- /dev/null +++ b/source/plugins/index.md @@ -0,0 +1,7 @@ +--- +title: Plugins +layout: plugins +comments: false +--- + +{% url "Plugins" plugins-guide %} provide a way to extend the behavior of Cypress. To submit your own plugin, [follow these instructions](https://github.com/cypress-io/cypress-documentation/blob/develop/CONTRIBUTING.md#adding-plugins). diff --git a/themes/cypress/languages/en.yml b/themes/cypress/languages/en.yml index 6bd873353d..3561e107e2 100644 --- a/themes/cypress/languages/en.yml +++ b/themes/cypress/languages/en.yml @@ -2,6 +2,7 @@ menu: guides: Guides api: API tutorials: Tutorials + plugins: Plugins faq: FAQ examples: Examples dashboard: Dashboard @@ -68,6 +69,7 @@ sidebar: roadmap: Roadmap cypress-api-design: API Design all-videos: Videos + plugins-guide: Plugins api: introduction: Introduction api: API @@ -172,6 +174,9 @@ sidebar: dom: dom cypress-log: log cypress-server: Server + plugins: Plugins + writing-a-plugin: Writing a Plugin + preprocessors-api: Preprocessors tutorials: test-a-react-todo-app: Test a React Todo App introduction-to-tutorials: Introduction diff --git a/themes/cypress/layout/plugins.swig b/themes/cypress/layout/plugins.swig new file mode 100644 index 0000000000..23415bd56f --- /dev/null +++ b/themes/cypress/layout/plugins.swig @@ -0,0 +1,32 @@ +
+
+
+
+

{{ page.title }}

+ {{ __('page.improve') }} +
+
+ {{ (page.content) }} + {% for pluginType in site.data.plugins %} +

{{ pluginType.name }}

+
    + {% for plugin in pluginType.plugins %} +
  • +

    + {{ plugin.name }} +

    +

    {{ plugin.description }}

    + {% for keyword in plugin.keywords %} + #{{ keyword }} + {% endfor %} +
  • + {% endfor %} +
+ {% endfor %} +
+ +
+
+
diff --git a/themes/cypress/source/css/_partial/base.scss b/themes/cypress/source/css/_partial/base.scss index 5d737e96fd..f5f65edc66 100644 --- a/themes/cypress/source/css/_partial/base.scss +++ b/themes/cypress/source/css/_partial/base.scss @@ -60,9 +60,7 @@ button, select, input, input[type="submit"]::-moz-focus-inner, input[type="butto border: 0; } -.wrapper { - margin: 0 auto; - +@mixin clearfix { &:before { content: ""; display: table; @@ -75,16 +73,13 @@ button, select, input, input[type="submit"]::-moz-focus-inner, input[type="butto } } +.wrapper { + margin: 0 auto; + @include clearfix; +} + .inner { - &:before { - content: ""; - display: table; - } - &:after { - content: ""; - display: table; - clear: both; - } + @include clearfix; } #content-wrap { @@ -139,28 +134,10 @@ button, select, input, input[type="submit"]::-moz-focus-inner, input[type="butto // border-left: 1px solid #eee; // margin-top: -50px; position: relative; - - &:before { - content: ""; - display: table; - } - - &:after { - content: ""; - display: table; - clear: both; - } + @include clearfix; } #content-inner { - &:before { - content: ""; - display: table; - } - &:after { - content: ""; - display: table; - clear: both; - } + @include clearfix; } #container { diff --git a/themes/cypress/source/css/_partial/footer.scss b/themes/cypress/source/css/_partial/footer.scss index 80e13c9add..4e6c276f56 100644 --- a/themes/cypress/source/css/_partial/footer.scss +++ b/themes/cypress/source/css/_partial/footer.scss @@ -3,6 +3,7 @@ footer.wrapper { position: relative; background: $color-background; flex-shrink: 0; /* Prevent Chrome, Opera, and Safari from letting these items shrink to smaller than their content's default minimum size. */ + @include clearfix; input.form-control { background-color: #fff; diff --git a/themes/cypress/source/css/_partial/media_queries.scss b/themes/cypress/source/css/_partial/media_queries.scss index 49612662e2..a4543297b1 100644 --- a/themes/cypress/source/css/_partial/media_queries.scss +++ b/themes/cypress/source/css/_partial/media_queries.scss @@ -278,6 +278,10 @@ margin: 0 auto; } } + + ul.plugins-list li { + width: 50%; + } } @media screen and(max-width: 620px) { @@ -286,3 +290,9 @@ padding-right: 0; } } + +@media screen and(max-width: 500px) { + ul.plugins-list li { + width: 100%; + } +} diff --git a/themes/cypress/source/css/_partial/page.scss b/themes/cypress/source/css/_partial/page.scss index a019333559..0a598019f8 100644 --- a/themes/cypress/source/css/_partial/page.scss +++ b/themes/cypress/source/css/_partial/page.scss @@ -459,16 +459,7 @@ position: relative; overflow: auto; - &:before { - content: ""; - display: table; - } - - &:after { - content: ""; - display: table; - clear: both; - } + @include clearfix; } .article-footer-prev, .article-footer-next { @@ -515,30 +506,13 @@ padding-top: 2em; position: relative; - &:before { - content: ""; - display: table; - } - - &:after { - content: ""; - display: table; - clear: both; - } + @include clearfix; } .article-header { margin: 0 0 15px 0; border-bottom: 1px solid #ddd; - &:before { - content: ""; - display: table; - } - &:after { - content: ""; - display: table; - clear: both; - } + @include clearfix; } .article-title { @@ -552,15 +526,7 @@ } .article-inner { - &:before { - content: ""; - display: table; - } - &:after { - content: ""; - display: table; - clear: both; - } + @include clearfix; } .embed-container { diff --git a/themes/cypress/source/css/_partial/plugins.scss b/themes/cypress/source/css/_partial/plugins.scss new file mode 100644 index 0000000000..77608556a9 --- /dev/null +++ b/themes/cypress/source/css/_partial/plugins.scss @@ -0,0 +1,53 @@ +.plugins { + .wrapper { + padding: 0 40px; + } + + h2 { + border-bottom: 0; + margin-bottom: 0; + } + + h3 { + font-size: 1.3em; + margin: 0.6em 0; + + a { + + border-bottom: 0; + &:hover { + border-bottom: 0; + } + } + + + + } +} + +ul.plugins-list { + display: flex; + flex-flow: row wrap; + margin: 0 -20px; + padding: 0; + + li { + box-sizing: border-box; + list-style: none; + padding: 20px; + width: 30%; + margin: 20px; + border: 1px solid #e8e8e8; + box-shadow: 0px 1px 1px 0px rgba(0,0,0,0.15); + + p { + margin-bottom: 0.5em; + } + } + + .keyword { + font-weight: 300; + font-size: 0.9em; + color: #777; + } +} diff --git a/themes/cypress/source/css/_partial/toc.scss b/themes/cypress/source/css/_partial/toc.scss index 51cb238b9a..40c8a9e3fa 100644 --- a/themes/cypress/source/css/_partial/toc.scss +++ b/themes/cypress/source/css/_partial/toc.scss @@ -34,16 +34,7 @@ margin-top: 0; } - &:before { - content: ""; - display: table; - } - - &:after { - content: ""; - display: table; - clear: both; - } + @include clearfix; } .toc-link { diff --git a/themes/cypress/source/css/cypress.scss b/themes/cypress/source/css/cypress.scss index 04718f791e..288c22f3f5 100644 --- a/themes/cypress/source/css/cypress.scss +++ b/themes/cypress/source/css/cypress.scss @@ -11,4 +11,5 @@ @import "_partial/footer"; @import "_partial/highlight"; @import "_partial/examples"; +@import "_partial/plugins"; @import "_partial/media_queries";