Connection refused on node v18 in CI
MarcusElevait opened this issue · comments
Current behavior
We have an angular project that we test with cypress.
It runs fine, until we tried to switch from node v16 to node v18.
After switching to node v18 we get the following error in every cypress test:
http://localhost:4206/
We attempted to make an http request to this URL but the request failed without a response.
We received this error at the network level:
> Error: connect ECONNREFUSED 127.0.0.1:4206
Common situations why this would fail:
- you don't have internet access
- you forgot to run / boot your web server
- your web server isn't accessible
- you have weird network configuration settings on your computer
Because this error occurred during a `before each` hook we are skipping the remaining tests in the current suite: 'Test navigation functionali...'
at <unknown> (http://localhost:4206/__cypress/runner/cypress_runner.js:138168:82)
at visitFailedByErr (http://localhost:4206/__cypress/runner/cypress_runner.js:137560:12)
at <unknown> (http://localhost:4206/__cypress/runner/cypress_runner.js:138167:11)
at tryCatcher (http://localhost:4206/__cypress/runner/cypress_runner.js:8914:23)
at Promise._settlePromiseFromHandler (http://localhost:4206/__cypress/runner/cypress_runner.js:6849:31)
at Promise._settlePromise (http://localhost:4206/__cypress/runner/cypress_runner.js:6906:18)
at Promise._settlePromise0 (http://localhost:4206/__cypress/runner/cypress_runner.js:6951:10)
at Promise._settlePromises (http://localhost:4206/__cypress/runner/cypress_runner.js:7027:18)
at _drainQueueStep (http://localhost:4206/__cypress/runner/cypress_runner.js:3621:12)
at _drainQueue ([http://localhost:4206/__cypress/runner/cypress_runner.js:3614:9](http://localhost:4206/__cypress/runner/cypress_runner.js:3614#-9))
at ../../node_modules/bluebird/js/release/async.js.Async._drainQueues ([http://localhost:4206/__cypress/runner/cypress_runner.js:3630:5](http://localhost:4206/__cypress/runner/cypress_runner.js:3630#-5))
at Async.drainQueues (http://localhost:4206/__cypress/runner/cypress_runner.js:3500:14)
From Your Spec Code:
at Context.eval (webpack:///./src/e2e/navigation/navigating-in-collections.cy.ts:25:11)
From Node.js Internals:
Error: connect ECONNREFUSED 127.0.0.1:4206
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1187:16)
Initially thought the angular app maybe crashed, but we see this right before the error message:
** Angular Live Development Server is listening on localhost:4206, open your browser on http://localhost:4206/ **
We're using the cypress/browsers:node18.12.0-chrome103-ff107
docker image as a base image for our pipeline.
We're running this in bitbucket.
What I've tried so far:
- Run the cypress/browser image locally and start the tests there -> error curiously doesn't occurre
- Use the node 18.13.0 (latest lts) image with the needed dependencies described on cypress documentation -> same error in the CI pipeline
Desired behavior
Basically just want the test to run without this connection refused error.
Test code to reproduce
Running a basic angular application on port 4206
describe('Test basic app functionalities', () => {
beforeEach(() => {
cy.visit('/');
});
}
cypress.config.ts:
import { nxE2EPreset } from '@nrwl/cypress/plugins/cypress-preset';
import { defineConfig } from 'cypress';
const cypressJsonConfig = {
fileServerFolder: '.',
fixturesFolder: './src/fixtures',
video: true,
videosFolder: '../../dist/cypress/apps/explorait-e2e/videos',
screenshotsFolder: '../../dist/cypress/apps/explorait-e2e/screenshots',
chromeWebSecurity: false,
baseUrl: 'http://0.0.0.0:4206',
requestTimeout: 15000,
defaultCommandTimeout: 15000,
videoUploadOnPasses: false,
viewportWidth: 1920,
viewportHeight: 1080,
retries: {
runMode: 2,
openMode: 0,
},
reporter: '../../node_modules/mochawesome',
reporterOptions: {
reportDir: '../../dist/cypress/apps/explorait-e2e/results',
overwrite: false,
html: false,
json: true,
},
specPattern: 'src/e2e/**/*.cy.{js,jsx,ts,tsx}',
supportFile: 'src/support/e2e.ts',
};
export default defineConfig({
e2e: {
...nxE2EPreset(__filename),
...cypressJsonConfig,
setupNodeEvents(on) {
on('before:browser:launch', (browser, launchOptions) => {
if (browser.name === 'chrome') {
// exposes window.gc() function that will manually force garbage collection
launchOptions.args.push('--js-flags=--expose-gc');
}
return launchOptions;
});
},
},
});
Cypress Version
12.3.0
Node version
18.12.0
Operating System
docker image cypress/browsers:node18.12.0-chrome103-ff107
Debug Logs
Wanted to give you the logs here, but github says body is too long :-(
Other
We're using nx monorepo. There we have this anuglar application and another application which holds the cypress tests.
This is the nx project.json of the cypress app
{
"name": "explorait-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/explorait-e2e/src",
"projectType": "application",
"targets": {
"e2e": {
"executor": "@nrwl/cypress:cypress",
"options": {
"cypressConfig": "apps/explorait-e2e/cypress.config.ts",
"tsConfig": "apps/explorait-e2e/tsconfig.e2e.json",
"devServerTarget": "explorait:serve:e2e",
"testingType": "e2e"
},
"configurations": {
"production": {
"devServerTarget": "explorait:serve:production"
}
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"options": {
"lintFilePatterns": ["apps/explorait-e2e/**/*.{js,ts}"]
}
}
},
"tags": ["e2e", "angular"],
"implicitDependencies": ["explorait"]
}
I face the same error locally on my linux machine and in the pipeline using the cypress/base:18.12.1
image.
I could workaround this problem by serving Angular on 127.0.0.1
instead of localhost
. You can do this by using command line ng serve --host=127.0.0.1
or by updating your angular.json
:
{
[...],
"projects": {
"your-project": {
[...]
"architect": {
[...]
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
[...]
"host": "127.0.0.1"
},
[...]
Anyways it'd be nice if Cypress would work with the default settings.
I recently investigated this very issue. I posted about it here. I believe there are two issues:
- Use of
localhost
as the defaulthost
option for the Angular/webpack-dev-server builder. I don't see any documentation/recommendations for usinglocalhost
as the value here (DevServer docs). When it's used, it does not allow ipv4 addresses (so 127.0.0.1 does not work) - Cypress derives
127.0.0.1
from a baseUrl withhttp://localhost:xxxx
configured when it should derive[::1]
(ipv6). This is only an issue when usinghost: "localhost"
though.host: "[::1]"
works just fine.
Edit: I made some headway into the issue I linked above (new comment here). Might be related, but I'll return to this issue tomorrow to see if they are similar.
@MarcusElevait There has been a lot of info posted regarding the workaround (using the host: '127.0.0.1'
) and an issue on our side #25397. Have you been able to try the workaround? I wasn't able to reproduce the issue with docker locally (though you said everything was working fine with your local docker setup).
I don't run into any issues with a very simple angular + nx repo, regardless of node version. The only issue I found (which is what I linked above) is when a cy.request
is made before the visit. You might be running into this issue, but we would need more information on your repo to see if you are experiencing a different issue (docker adds more complexity, especially coupled with CI). Are you able to provide a minimal reproduction exhibiting your failure? Otherwise I'm going to have to close this as a duplicate of #25397
We had a workaround by setting the following env in the docker image that we use to run the tests in our ci pipeline: NODE_OPTIONS=--dns-result-order=ipv4first
.
So for us it is good with that.
But yes, in our tests we're running always a cy.request
before starting the test for login reasons.
Basically we have the following setup:
- Bitbucket CI
- Cypress browser image 18.12.0
A test running the following code:
cy.request({
method: 'POST',
url: `http://localhost:3100/login/`,
body: { username, password },
}).then(response => {
cy.setCookie('localhost_sso_access_token', response.body.accessToken);
cy.setCookie('localhost_sso_refresh_token', response.body.refreshToken);
cy.reload();
});
cy.visit('/')
Based on your comments iI'd say the cy.request
before the cy.visit
is what is causing the issue. Thanks for posting back, going to close as a duplicate of #25397, you can follow that issue to track the progress.
Thanks! This helped me! I have been struggling with this for a week. Thank you so much for sharing!