diff --git a/README.md b/README.md index ebb5dbe0..003442e3 100644 --- a/README.md +++ b/README.md @@ -298,6 +298,8 @@ Name | Description Set environment variable `DEBUG=netlify-plugin-cypress` to see the debug logs. To see even more information, set `DEBUG=netlify-plugin-cypress,netlify-plugin-cypress:verbose` +**Warning:** be careful with verbose logging, since it can print all environment variables passed to the plugin, including tokens, API keys, and other secrets. + ## Common problems
diff --git a/cypress/integration/spec.js b/cypress/integration/spec.js index 6fa42c8b..9c782ab3 100644 --- a/cypress/integration/spec.js +++ b/cypress/integration/spec.js @@ -3,3 +3,9 @@ it('loads page', () => { cy.visit('/') cy.contains('Placeholder').should('be.visible') }) + +it.skip('skips this test on purpose', () => { + expect(false).to.be.true +}) + +it('has not test yet') diff --git a/package-lock.json b/package-lock.json index ac857f55..231418e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9313,8 +9313,7 @@ "common-tags": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", - "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", - "dev": true + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==" }, "commondir": { "version": "1.0.1", diff --git a/package.json b/package.json index 6a4037f2..94b75c3c 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ ], "license": "ISC", "dependencies": { + "common-tags": "1.8.0", "debug": "4.1.1", "got": "10.7.0", "local-web-server": "^4.2.1", diff --git a/src/index.js b/src/index.js index e16ef131..23edbbbf 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,10 @@ // @ts-check +const { stripIndent } = require('common-tags') const debug = require('debug')('netlify-plugin-cypress') const debugVerbose = require('debug')('netlify-plugin-cypress:verbose') const { ping, getBrowserPath, serveFolder } = require('./utils') +const PLUGIN_NAME = 'netlify-plugin-cypress' const DEFAULT_BROWSER = 'electron' function startServerMaybe(run, options = {}) { @@ -153,13 +155,28 @@ async function cypressInfo(arg) { } } -const processCypressResults = (results, errorCallback) => { +/** + * Reports the number of successful and failed tests. + * If there are failed tests, uses the `errorCallback` to + * fail the build step. + * @param {*} results + * @param {function} errorCallback + * @param {function} summaryCallback + */ +const processCypressResults = (results, errorCallback, summaryCallback) => { if (typeof errorCallback !== 'function') { debug('Typeof of error callback %s', errorCallback) throw new Error( `Expected error callback to be a function, it was ${typeof errorCallback}`, ) } + if (typeof summaryCallback !== 'function') { + debug('Typeof of summary callback %s', summaryCallback) + throw new Error( + `Expected summary callback to be a function, it was ${typeof summaryCallback}`, + ) + } + if (results.failures) { // Cypress failed without even running the tests console.error('Problem running Cypress') @@ -177,6 +194,27 @@ const processCypressResults = (results, errorCallback) => { } }) + let text = stripIndent` + āœ… Passed tests: ${results.totalPassed} + šŸ”„ Failed tests: ${results.totalFailed} + ā­•ļø Pending tests: ${results.totalPending} + šŸš« Skipped tests: ${results.totalSkipped} + ` + if (results.runUrl) { + text += `\nšŸ”— Dashboard url: ${results.runUrl}` + } + summaryCallback({ + title: PLUGIN_NAME, + summary: [ + 'tests:', + `āœ… ${results.totalPassed}`, + `šŸ”„ ${results.totalFailed}`, + `ā­•ļø ${results.totalPending}`, + `šŸš« ${results.totalSkipped}`, + ].join(' '), + text, + }) + // results.totalFailed gives total number of failed tests if (results.totalFailed) { return errorCallback('Failed Cypress tests', { @@ -194,6 +232,7 @@ async function postBuild({ spa, browser, errorCallback, + summaryCallback, }) { const port = 8080 let server @@ -228,7 +267,7 @@ async function postBuild({ }) }) - processCypressResults(results, errorCallback) + processCypressResults(results, errorCallback, summaryCallback) } const hasRecordKey = () => typeof process.env.CYPRESS_RECORD_KEY === 'string' @@ -281,8 +320,9 @@ module.exports = { } const errorCallback = arg.utils.build.failBuild.bind(arg.utils.build) + const summaryCallback = arg.utils.status.show.bind(arg.utils.status) - processCypressResults(results, errorCallback) + processCypressResults(results, errorCallback, summaryCallback) }, onPostBuild: async (arg) => { @@ -319,6 +359,7 @@ module.exports = { const spa = arg.inputs.spa const errorCallback = arg.utils.build.failBuild.bind(arg.utils.build) + const summaryCallback = arg.utils.status.show.bind(arg.utils.status) await postBuild({ fullPublishFolder, @@ -329,9 +370,14 @@ module.exports = { spa, browser, errorCallback, + summaryCallback, }) }, + /** + * Executes after successful Netlify deployment. + * @param {any} arg + */ onSuccess: async (arg) => { debugVerbose('onSuccess arg %o', arg) @@ -363,6 +409,7 @@ module.exports = { debug('onSuccessInputs %s %o', typeof onSuccessInputs, onSuccessInputs) const errorCallback = utils.build.failPlugin.bind(utils.build) + const summaryCallback = utils.status.show.bind(utils.status) if (!deployPrimeUrl) { return errorCallback('Missing DEPLOY_PRIME_URL') @@ -404,6 +451,6 @@ module.exports = { tag, browser, ) - processCypressResults(results, errorCallback) + processCypressResults(results, errorCallback, summaryCallback) }, }