Skip to content

Commit fab55c4

Browse files
committed
test: replace all loopback address usages with Windows native compatible variant
When testing native Windows via WSL, the loopback address (localhost) is not necessarily the correct one anymore. NOTE: This is not needed for general development/testing inside WSL; it's just needed because we still want to test native Windows on CI, and launch powershell/cmd from inside WSL to simulate a real native Windows CLI user experience. Context on why this is needed: When spawning e.g. ng serve via CMD, the process runs outside WSL, so `localhost`, when a test wants to assert the served content, is not correct. Instead the NAT IP of the Windows host needs to be used directly. This is what this change enables. Notably WSL does have a mirrored networking mode, but it doesn't work well. Requests from WSL to the Windows host typically fail with connection refused errors (and there are many issues reported). The NAT approach (default by WSL) is safer, and works, but is a little more work as can be seen in this commit.
1 parent 73036a3 commit fab55c4

24 files changed

+65
-57
lines changed

tests/legacy-cli/e2e/tests/basic/rebuild.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { setTimeout } from 'node:timers/promises';
2-
import { getGlobalVariable } from '../../utils/env';
2+
import { getGlobalVariable, loopbackAddr } from '../../utils/env';
33
import { appendToFile, replaceInFile, writeMultipleFiles } from '../../utils/fs';
44
import { silentNg, waitForAnyProcessOutputToMatch } from '../../utils/process';
55
import { ngServe } from '../../utils/project';
@@ -66,9 +66,7 @@ export default async function () {
6666
}),
6767
]);
6868
{
69-
console.error(`http://localhost:${port}/main.js`);
70-
// await setTimeout(1000 * 60 * 20);
71-
const response = await fetch(`http://localhost:${port}/main.js`);
69+
const response = await fetch(`http://${loopbackAddr}:${port}/main.js`);
7270
const body = await response.text();
7371
if (!body.match(/\$\$_E2E_GOLDEN_VALUE_1/)) {
7472
throw new Error('Expected golden value 1.');
@@ -90,7 +88,7 @@ export default async function () {
9088
]);
9189

9290
{
93-
const response = await fetch(`http://localhost:${port}/main.js`);
91+
const response = await fetch(`http://${loopbackAddr}:${port}/main.js`);
9492
const body = await response.text();
9593
if (!body.match(/testingTESTING123/)) {
9694
throw new Error('Expected component HTML to update.');
@@ -106,7 +104,7 @@ export default async function () {
106104
]);
107105

108106
{
109-
const response = await fetch(`http://localhost:${port}/main.js`);
107+
const response = await fetch(`http://${loopbackAddr}:${port}/main.js`);
110108
const body = await response.text();
111109
if (!body.match(/color:\s?blue/)) {
112110
throw new Error('Expected component CSS to update.');
@@ -122,7 +120,7 @@ export default async function () {
122120
]);
123121

124122
{
125-
const response = await fetch(`http://localhost:${port}/styles.css`);
123+
const response = await fetch(`http://${loopbackAddr}:${port}/styles.css`);
126124
const body = await response.text();
127125
if (!body.match(/color:\s?green/)) {
128126
throw new Error('Expected global CSS to update.');

tests/legacy-cli/e2e/tests/basic/serve.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { loopbackAddr } from '../../utils/env';
12
import { killAllProcesses } from '../../utils/process';
23
import { ngServe } from '../../utils/project';
34

@@ -13,13 +14,13 @@ export default async function () {
1314
}
1415

1516
async function verifyResponse(port: number): Promise<void> {
16-
const indexResponse = await fetch(`http://localhost:${port}/`);
17+
const indexResponse = await fetch(`http://${loopbackAddr}:${port}/`);
1718

1819
if (!/<app-root><\/app-root>/.test(await indexResponse.text())) {
1920
throw new Error('Response does not match expected value.');
2021
}
2122

22-
const assetResponse = await fetch(`http://localhost:${port}/favicon.ico`);
23+
const assetResponse = await fetch(`http://${loopbackAddr}:${port}/favicon.ico`);
2324

2425
if (!assetResponse.ok) {
2526
throw new Error('Expected favicon asset to be available.');

tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n-base-href.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { expectFileToMatch, writeFile } from '../../../utils/fs';
44
import { execAndWaitForOutputToMatch, ng, noSilentNg, silentNg } from '../../../utils/process';
55
import { langTranslations, setupI18nConfig } from '../../i18n/setup';
66
import { findFreePort } from '../../../utils/network';
7-
import { getGlobalVariable } from '../../../utils/env';
7+
import { getGlobalVariable, loopbackAddr } from '../../../utils/env';
88
import { installWorkspacePackages, uninstallPackage } from '../../../utils/packages';
99
import { useSha } from '../../../utils/project';
1010

@@ -90,7 +90,7 @@ export default async function () {
9090
const pathnamesToVerify = ['/ssr', '/ssg'];
9191
for (const { lang } of langTranslations) {
9292
for (const pathname of pathnamesToVerify) {
93-
const res = await fetch(`http://localhost:${port}/base/${lang}${pathname}`);
93+
const res = await fetch(`http://${loopbackAddr}:${port}/base/${lang}${pathname}`);
9494
const text = await res.text();
9595

9696
assert.match(

tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n-sub-path.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { expectFileToMatch, writeFile } from '../../../utils/fs';
44
import { execAndWaitForOutputToMatch, ng, noSilentNg, silentNg } from '../../../utils/process';
55
import { langTranslations, setupI18nConfig } from '../../i18n/setup';
66
import { findFreePort } from '../../../utils/network';
7-
import { getGlobalVariable } from '../../../utils/env';
7+
import { getGlobalVariable, loopbackAddr } from '../../../utils/env';
88
import { installWorkspacePackages, uninstallPackage } from '../../../utils/packages';
99
import { updateJsonFile, useSha } from '../../../utils/project';
1010

@@ -125,7 +125,7 @@ export default async function () {
125125
for (const pathname of pathnamesToVerify) {
126126
const subPath = URL_SUB_PATH[lang];
127127
const urlPathname = `/base${subPath ? `/${subPath}` : ''}${pathname}`;
128-
const res = await fetch(`http://localhost:${port}${urlPathname}`);
128+
const res = await fetch(`http://${loopbackAddr}:${port}${urlPathname}`);
129129
const text = await res.text();
130130

131131
assert.match(

tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-i18n.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { expectFileToMatch, writeFile } from '../../../utils/fs';
44
import { execAndWaitForOutputToMatch, ng, noSilentNg, silentNg } from '../../../utils/process';
55
import { langTranslations, setupI18nConfig } from '../../i18n/setup';
66
import { findFreePort } from '../../../utils/network';
7-
import { getGlobalVariable } from '../../../utils/env';
7+
import { getGlobalVariable, loopbackAddr } from '../../../utils/env';
88
import { installWorkspacePackages, uninstallPackage } from '../../../utils/packages';
99
import { useSha } from '../../../utils/project';
1010

@@ -99,7 +99,7 @@ export default async function () {
9999
// We run the tests twice to ensure that the locale ID is set correctly.
100100
for (const iteration of [1, 2]) {
101101
for (const { lang, translation } of langTranslations) {
102-
const res = await fetch(`http://localhost:${port}/${lang}${pathname}`);
102+
const res = await fetch(`http://${loopbackAddr}:${port}/${lang}${pathname}`);
103103
const text = await res.text();
104104

105105
for (const match of [`<p id="date">${translation.date}</p>`, `<p id="locale">${lang}</p>`]) {

tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server-platform-neutral.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
uninstallPackage,
1010
} from '../../../utils/packages';
1111
import { updateJsonFile, useSha } from '../../../utils/project';
12-
import { getGlobalVariable } from '../../../utils/env';
12+
import { getGlobalVariable, loopbackAddr } from '../../../utils/env';
1313
import { findFreePort } from '../../../utils/network';
1414
import { readFile } from 'node:fs/promises';
1515

@@ -126,7 +126,7 @@ export default async function () {
126126
/Server initialized/,
127127
);
128128

129-
const res = await fetch(`http://localhost:${port}/ssr`);
129+
const res = await fetch(`http://${loopbackAddr}:${port}/ssr`);
130130
const text = await res.text();
131131
assert.match(text, new RegExp('ssr works!'));
132132
}

tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-output-mode-server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { expectFileToMatch, readFile, replaceInFile, writeFile } from '../../../
55
import { execAndWaitForOutputToMatch, ng, noSilentNg, silentNg } from '../../../utils/process';
66
import { installWorkspacePackages, uninstallPackage } from '../../../utils/packages';
77
import { useSha } from '../../../utils/project';
8-
import { getGlobalVariable } from '../../../utils/env';
8+
import { getGlobalVariable, loopbackAddr } from '../../../utils/env';
99
import { findFreePort } from '../../../utils/network';
1010

1111
export default async function () {
@@ -172,7 +172,7 @@ export default async function () {
172172
const port = await spawnServer();
173173
for (const [pathname, { content, headers, serverContext }] of Object.entries(responseExpects)) {
174174
// NOTE: A global 'UND_ERR_SOCKET' may occur due to an incorrect Content-Length header value.
175-
const res = await fetch(`http://localhost:${port}${pathname}`);
175+
const res = await fetch(`http://${loopbackAddr}:${port}${pathname}`);
176176
const text = await res.text();
177177

178178
assert.match(

tests/legacy-cli/e2e/tests/build/server-rendering/server-routes-preload-links.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { replaceInFile, writeMultipleFiles } from '../../../utils/fs';
33
import { execAndWaitForOutputToMatch, ng, noSilentNg, silentNg } from '../../../utils/process';
44
import { installWorkspacePackages, uninstallPackage } from '../../../utils/packages';
55
import { ngServe, updateJsonFile, useSha } from '../../../utils/project';
6-
import { getGlobalVariable } from '../../../utils/env';
6+
import { getGlobalVariable, loopbackAddr } from '../../../utils/env';
77
import { findFreePort } from '../../../utils/network';
88

99
export default async function () {
@@ -186,15 +186,15 @@ const RESPONSE_EXPECTS: Record<
186186

187187
async function runTests(port: number): Promise<void> {
188188
for (const [pathname, { matches, notMatches }] of Object.entries(RESPONSE_EXPECTS)) {
189-
const res = await fetch(`http://localhost:${port}${pathname}`);
189+
const res = await fetch(`http://${loopbackAddr}:${port}${pathname}`);
190190
const text = await res.text();
191191

192192
for (const match of matches) {
193193
assert.match(text, match, `Response for '${pathname}': ${match} was not matched in content.`);
194194

195195
// Ensure that the url is correct and it's a 200.
196196
const link = text.match(match)?.[1];
197-
const preloadRes = await fetch(`http://localhost:${port}/${link}`);
197+
const preloadRes = await fetch(`http://${loopbackAddr}:${port}/${link}`);
198198
assert.equal(preloadRes.status, 200);
199199
}
200200

tests/legacy-cli/e2e/tests/commands/serve/assets.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import assert from 'node:assert';
22
import { randomUUID } from 'node:crypto';
33
import { mkdir, rm, writeFile } from 'node:fs/promises';
44
import { ngServe, updateJsonFile } from '../../../utils/project';
5-
import { getGlobalVariable } from '../../../utils/env';
5+
import { getGlobalVariable, loopbackAddr } from '../../../utils/env';
66

77
export default async function () {
88
const outsideDirectoryName = `../outside-${randomUUID()}`;
@@ -22,15 +22,15 @@ export default async function () {
2222

2323
const port = await ngServe();
2424

25-
let response = await fetch(`http://localhost:${port}/favicon.ico`);
25+
let response = await fetch(`http://${loopbackAddr}:${port}/favicon.ico`);
2626
assert.strictEqual(response.status, 200, 'favicon.ico response should be ok');
2727

28-
response = await fetch(`http://localhost:${port}/outside/some-asset.xyz`);
28+
response = await fetch(`http://${loopbackAddr}:${port}/outside/some-asset.xyz`);
2929
assert.strictEqual(response.status, 200, 'outside/some-asset.xyz response should be ok');
3030
assert.strictEqual(await response.text(), 'XYZ', 'outside/some-asset.xyz content is wrong');
3131

3232
// A non-existent HTML file request with accept header should fallback to the index HTML
33-
response = await fetch(`http://localhost:${port}/does-not-exist.html`, {
33+
response = await fetch(`http://${loopbackAddr}:${port}/does-not-exist.html`, {
3434
headers: { accept: 'text/html' },
3535
});
3636
assert.strictEqual(
@@ -51,7 +51,7 @@ export default async function () {
5151
}
5252

5353
// A non-existent file without an html accept header should not be found.
54-
response = await fetch(`http://localhost:${port}/does-not-exist.png`);
54+
response = await fetch(`http://${loopbackAddr}:${port}/does-not-exist.png`);
5555
assert.strictEqual(response.status, 404, 'non-existent file response should be not found');
5656
} finally {
5757
await rm(outsideDirectoryName, { force: true, recursive: true });

tests/legacy-cli/e2e/tests/commands/serve/head-request.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1+
import { loopbackAddr } from '../../../utils/env';
12
import { ngServe } from '../../../utils/project';
23

34
export default async function () {
45
const port = await ngServe();
56
// HTML
6-
await checkHeadForUrl(`http://localhost:${port}/index.html`);
7+
await checkHeadForUrl(`http://${loopbackAddr}:${port}/index.html`);
78
// Generated JS
8-
await checkHeadForUrl(`http://localhost:${port}/main.js`);
9+
await checkHeadForUrl(`http://${loopbackAddr}:${port}/main.js`);
910
// Generated CSS
10-
await checkHeadForUrl(`http://localhost:${port}/styles.css`);
11+
await checkHeadForUrl(`http://${loopbackAddr}:${port}/styles.css`);
1112
// Configured asset
12-
await checkHeadForUrl(`http://localhost:${port}/favicon.ico`);
13+
await checkHeadForUrl(`http://${loopbackAddr}:${port}/favicon.ico`);
1314
}
1415

1516
async function checkHeadForUrl(url: string): Promise<void> {

0 commit comments

Comments
 (0)