From f4e86262ff79d2bafc1250e5c47e93a8abf93624 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Mon, 8 Feb 2021 22:11:59 -0500 Subject: [PATCH 1/2] fix: improve the ping code --- src/ping-cli.js | 19 +++++++++++++ src/ping.js | 75 +++++++++++++++++++++++++++++++++++++++++++++++++ src/utils.js | 40 +------------------------- 3 files changed, 95 insertions(+), 39 deletions(-) create mode 100644 src/ping-cli.js create mode 100644 src/ping.js diff --git a/src/ping-cli.js b/src/ping-cli.js new file mode 100644 index 00000000..4caad042 --- /dev/null +++ b/src/ping-cli.js @@ -0,0 +1,19 @@ +// a little CLI utility for testing pinging websites +// node ./src/ping-cli + +const { ping } = require('./utils') +const timeoutSeconds = 60 +const url = process.argv[2] +console.log('pinging url %s for %d seconds', url, timeoutSeconds) +if (!url) { + console.error('Missing url to ping') + process.exit(1) +} +ping(url, timeoutSeconds * 1000).then( + () => { + console.log('all good') + }, + (err) => { + console.error('a problem', err) + }, +) diff --git a/src/ping.js b/src/ping.js new file mode 100644 index 00000000..6fb45e5f --- /dev/null +++ b/src/ping.js @@ -0,0 +1,75 @@ +const got = require('got') +const debug = require('debug')('netlify-plugin-cypress') +const debugVerbose = require('debug')('netlify-plugin-cypress:verbose') + +/** + * A small utility for checking when an URL responds, kind of + * a poor man's https://www.npmjs.com/package/wait-on. This version + * is implemented using https://github.com/sindresorhus/got + */ +const ping = (url, timeout) => { + if (!timeout) { + throw new Error('Expected timeout in ms') + } + + debug('pinging "%s" for %d ms max', url, timeout) + + // make copy of the error codes that "got" retries on + const errorCodes = [...got.defaults.options.retry.errorCodes] + errorCodes.push('ESOCKETTIMEDOUT') + + // we expect the server to respond within a time limit + // and if it does not - retry up to total "timeout" duration + const individualPingTimeout = Math.min(timeout, 30000) + const limit = Math.ceil(timeout / individualPingTimeout) + + debug(`total ping timeout ${timeout}`) + debug(`individual ping timeout ${individualPingTimeout}ms`) + debug(`retries limit ${limit}`) + + const start = +new Date() + return got(url, { + headers: { + Accept: 'text/html, application/json, text/plain, */*', + }, + timeout: individualPingTimeout, + errorCodes, + retry: { + limit, + calculateDelay({ error, attemptCount }) { + if (error) { + debugVerbose(`got error ${JSON.stringify(error)}`) + } + const now = +new Date() + const elapsed = now - start + debugVerbose( + `${elapsed}ms ${error.method} ${error.host} ${error.code} attempt ${attemptCount}`, + ) + if (elapsed > timeout) { + console.error( + '%s timed out on retry %d of %d', + url, + attemptCount, + limit, + ) + return 0 + } + + // if the error code is ECONNREFUSED use shorter timeout + // because the server is probably starting + if (error.code === 'ECONNREFUSED') { + return 1000 + } + + // default "long" timeout + return individualPingTimeout + }, + }, + }).then(() => { + const now = +new Date() + const elapsed = now - start + debug(`pinging ${url} has finished ok after ${elapsed}ms`) + }) +} + +module.exports = { ping } diff --git a/src/utils.js b/src/utils.js index 6bf80357..4b3dbaf5 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,45 +1,7 @@ // @ts-check const puppeteer = require('puppeteer') -const got = require('got') const debug = require('debug')('netlify-plugin-cypress') -const debugVerbose = require('debug')('netlify-plugin-cypress:verbose') - -/** - * A small utility for checking when an URL responds, kind of - * a poor man's https://www.npmjs.com/package/wait-on - */ -const ping = (url, timeout) => { - debug('pinging "%s" for %d ms max', url, timeout) - const start = +new Date() - - return got(url, { - retry: { - limit: 30, - calculateDelay({ attemptCount, retryOptions, error }) { - const now = +new Date() - const elapsed = now - start - debugVerbose(`attempt ${attemptCount} ${elapsed}ms ${error.message}`) - - if (elapsed > timeout) { - debug( - '%s timed out after %dms, timeout was %dms', - url, - elapsed, - timeout, - ) - console.error( - '%s timed out after %dms, timeout was %dms', - url, - elapsed, - timeout, - ) - return 0 - } - return 1000 - }, - }, - }) -} +const { ping } = require('./ping') const getBrowserPath = async () => { const browserFetcher = puppeteer.createBrowserFetcher() From f0e5a6377acc3bf4e8e1db4d9f0aacbf53ea6b91 Mon Sep 17 00:00:00 2001 From: Gleb Bahmutov Date: Mon, 8 Feb 2021 22:33:00 -0500 Subject: [PATCH 2/2] add link to Gatsby site --- README.md | 1 + tests/routing/netlify.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 890b62e8..ab92cf62 100644 --- a/README.md +++ b/README.md @@ -274,6 +274,7 @@ Name | Description [netlify-plugin-prebuild-example](https://github.com/cypress-io/netlify-plugin-prebuild-example) | Runs tests twice, first using the development version of the site, then after Netlify builds the production bundles, runs the tests again [cypress-example-kitchensink](https://github.com/cypress-io/cypress-example-kitchensink) | Runs only a subset of all tests before publishing the folder to Netlify [bahmutov/eleventyone](https://github.com/bahmutov/eleventyone) | Example used in [Test Sites Deployed To Netlify Using netlify-plugin-cypress](https://glebbahmutov.com/blog/test-netlify/) tutorial +[gatsby-starter-portfolio-cara](https://github.com/bahmutov/gatsby-starter-portfolio-cara) | A Gatsby site example ## Debugging diff --git a/tests/routing/netlify.toml b/tests/routing/netlify.toml index 24f50cdc..7916d428 100644 --- a/tests/routing/netlify.toml +++ b/tests/routing/netlify.toml @@ -22,6 +22,7 @@ TERM = "xterm" [plugins.inputs.preBuild] start = 'npm start' wait-on = 'http://localhost:3000' + wait-on-timeout = '45' # seconds # and test the built site after [plugins.inputs]