Skip to content
This repository has been archived by the owner on Dec 12, 2020. It is now read-only.

Commit

Permalink
feat: instrument code coverage by default (#339)
Browse files Browse the repository at this point in the history
  • Loading branch information
bahmutov authored Jul 3, 2020
1 parent 2d486fc commit 61eb3b0
Show file tree
Hide file tree
Showing 19 changed files with 273 additions and 41 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ cypress/videos/
cypress/screenshots
.nyc_output
coverage
*.tgz
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

> A little helper to unit test Vue components in the open source [Cypress.io](https://www.cypress.io/) E2E test runner **v4.5.0+**
**Jump to:** [Comparison](#comparison), [Blog posts](#blog-posts), Examples: [basic](#basic-examples), [advanced](#advanced-examples), [external](#external-examples), [Code coverage](#code-coverage)
**Jump to:** [Comparison](#comparison), [Blog posts](#blog-posts), Examples: [basic](#basic-examples), [advanced](#advanced-examples), [full](#full-examples), [external](#external-examples), [Code coverage](#code-coverage)

## TLDR

Expand Down Expand Up @@ -598,6 +598,16 @@ Spec | Description
[mocking-imports](cypress/component/advanced/mocking-imports) | Stub ES6 imports from the tests
<!-- prettier-ignore-end -->

### Full examples

We have several subfolders in [examples](examples) folder.

<!-- prettier-ignore-start -->
Folder Name | Description
--- | ---
[cli](examples/cli) | An example app scaffolded using Vue CLI and the component testing added using `vue add cypress-experimental` command.
<!-- prettier-ignore-end -->

### External examples

<!-- prettier-ignore-start -->
Expand Down
51 changes: 50 additions & 1 deletion circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,20 @@ workflows:
- cypress/install:
name: Install
executor: cypress/base-12
build: npm run build
# creates files in "dist" folder
build: |
npm run build
echo ""
echo "Build package archive 📦"
echo ""
# first show the contents to be packed
npm pack --dry
echo ""
echo "packing ..."
echo ""
npm pack
echo ""
ls -la
post-steps:
- run:
name: Show info 📺
Expand Down Expand Up @@ -40,6 +53,41 @@ workflows:
echo "Test files for this machine are $TESTFILES"
npx cypress run --spec $TESTFILES
- cypress/run:
name: Example CLI
executor: cypress/base-12
requires:
- Install
install-command: npm install
verify-command: echo 'Already verified'
no-workspace: true
working_directory: examples/cli
command: |
echo "🦶🏻 Scaffolding component tests"
echo ""
# scaffolds Babel + Webpack combo
npx --package @vue/cli vue add cypress-experimental
echo ""
echo "🦶🏻 test scaffolded project, should work"
echo ""
DEBUG=cypress-vue-unit-test npx cypress run --spec 'tests/components/**/*.js'
# let's inspect the scaffolded app
ls -la
echo ""
echo "🦶🏻 install the current cypress-vue-unit-test"
echo ""
npm install ../../cypress-vue-unit-test-0.0.0-development.tgz
echo ""
echo "🦶🏻 run component tests"
echo ""
DEBUG=cypress-vue-unit-test npx cypress run --spec 'tests/components/**/*.js'
echo ""
echo "🦶🏻 look at the generated files, should have coverage"
# (after updating cypress-experimental)
echo ""
ls -la
store_artifacts: true

# this job attaches the workspace left by the install job
# so it is ready to run Cypress tests
# only we will run semantic release script instead
Expand All @@ -55,6 +103,7 @@ workflows:
requires:
- Install
- Test
- Example CLI
install-command: echo 'Already installed'
verify-command: echo 'Already verified'
no-workspace: true
Expand Down
22 changes: 3 additions & 19 deletions cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,6 @@
// default webpack file preprocessor is good for simple cases
const { onFileDefaultPreprocessor } = require('../../preprocessor/webpack')

/// <reference types="cypress" />
const preprocessor = require('../../plugins/webpack')
module.exports = (on, config) => {
require('@cypress/code-coverage/task')(on, config)
on('file:preprocessor', onFileDefaultPreprocessor(config))

// IMPORTANT to return the config object
// with the any changed environment variables
preprocessor(on, config)
return config
}

/*
for more complex cases, when the project already includes webpack.config.js
const {
onFilePreprocessor
} = require('cypress-vue-unit-test/preprocessor/webpack')
module.exports = on => {
on('file:preprocessor', onFilePreprocessor('../path/to/webpack.config'))
}
*/
9 changes: 1 addition & 8 deletions cypress/support/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
require('@cypress/code-coverage/support')

beforeEach(() => {
const container = document.getElementById('cypress-jsdom')
if (container) {
container.innerHTML = ''
}
})
require('../../dist/support')
15 changes: 7 additions & 8 deletions docs/manual-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,18 @@
npm install -D cypress cypress-vue-unit-test
```

2. Include this plugin `cypress/plugin/index.js`
2. Include this plugin from your project's `cypress/plugin/index.js` file

```js
// default webpack file preprocessor is good for simple cases
// Required to temporarily patch async components, chunking, and inline image loading
import { onFileDefaultPreprocessor } from 'cypress-vue-unit-test/dist/preprocessor/webpack'

module.exports = (on) => {
on('file:preprocessor', onFileDefaultPreprocessor)
const preprocessor = require('cypress-vue-unit-test/dist/plugins/webpack')
module.exports = (on, config) => {
preprocessor(on, config)
// IMPORTANT return the config object
return config
}
```

3. Include the support file `cypress/support/index.js`
3. Include the support file from your project's `cypress/support/index.js` file

```js
import 'cypress-vue-unit-test/dist/support'
Expand Down
22 changes: 22 additions & 0 deletions examples/cli/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.DS_Store
node_modules
/dist

# local env files
.env.local
.env.*.local

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
1 change: 1 addition & 0 deletions examples/cli/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
3 changes: 3 additions & 0 deletions examples/cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# cli-example

Application scaffolded with Vue CLI v3
5 changes: 5 additions & 0 deletions examples/cli/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
42 changes: 42 additions & 0 deletions examples/cli/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "cli-example",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^2.6.11"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.4.0",
"@vue/cli-plugin-eslint": "~4.4.0",
"@vue/cli-service": "~4.4.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
28 changes: 28 additions & 0 deletions examples/cli/src/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>

<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Binary file added examples/cli/src/assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 58 additions & 0 deletions examples/cli/src/components/HelloWorld.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
8 changes: 8 additions & 0 deletions examples/cli/src/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
render: h => h(App),
}).$mount('#app')
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@
"url": "https://github.com/bahmutov/cypress-vue-unit-test.git"
},
"scripts": {
"build": "babel src --ignore src/*spec.js --out-dir dist && babel preprocessor --out-dir dist/preprocessor",
"build": "babel src --ignore src/*spec.js --out-dir dist && babel preprocessor --out-dir dist/preprocessor && babel plugins --out-dir dist/plugins",
"ban": "ban",
"deps": "echo skip deps-ok && dependency-check --no-dev .",
"issues": "git-issues",
"license": "license-checker --production --onlyunknown --csv",
"lint": "prettier --check '*.js' 'cypress/**/*.js' 'src/**/*.js' 'preprocessor/**/*.js'",
"lint": "prettier --check '*.js' 'cypress/**/*.js' 'src/**/*.js' 'preprocessor/**/*.js' 'plugins/**/*.js'",
"prelint": "npm run pretty",
"pretest": "npm run lint && npm run build",
"pretty": "prettier --write '*.js' 'cypress/**/*.js' 'src/**/*.js' 'preprocessor/**/*.js'",
"pretty": "prettier --write '*.js' 'cypress/**/*.js' 'src/**/*.js' 'preprocessor/**/*.js' 'plugins/**/*.js'",
"size": "npm pack --dry",
"test": "npm run cy:run",
"unit": "mocha src/*-spec.js",
Expand Down
25 changes: 25 additions & 0 deletions plugins/webpack/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/// <reference types="cypress" />
const { onFileDefaultPreprocessor } = require('../../preprocessor/webpack')

/**
* Registers Cypress preprocessor for Vue component testing.
* IMPORTANT to return the config object with
* with the any changed environment variables.
*
* @param {Cypress.PluginConfigOptions} config Cypress config object.
* @example
* // in your project's plugins/index.js file
* const preprocessor = require('cypress-vue-unit-test/dist/plugins/webpack')
* module.exports = (on, config) => {
* preprocessor(on, config)
* // IMPORTANT return the config object
* return config
* }
*/
const cypressPluginsFn = (on, config) => {
require('@cypress/code-coverage/task')(on, config)
on('file:preprocessor', onFileDefaultPreprocessor(config))
return config
}

module.exports = cypressPluginsFn
3 changes: 3 additions & 0 deletions src/support.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
/* eslint-env mocha */
require('@cypress/code-coverage/support')

/** Initialize an empty document with root element */
function renderTestingPlatform() {
const document = cy.state('document')
const el = document.getElementById('cypress-jsdom')
if (el) {
// clean the element before each test
while (el.hasChildNodes()) {
el.removeChild(el.lastChild)
}
Expand Down
Loading

0 comments on commit 61eb3b0

Please sign in to comment.