Skip to content

Commit 5d15e5d

Browse files
alan-agius4filipesilva
authored andcommitted
test(@angular/cli): add ng add and ng update E2E tests for secure repositories
With this change we add E2E tests to validate that `ng add` and `ng update` work with secure NPM registries. This is a follow up of #21140 which addressed several issues with secure registries.
1 parent efafc15 commit 5d15e5d

File tree

7 files changed

+168
-24
lines changed

7 files changed

+168
-24
lines changed

tests/legacy-cli/e2e/tests/commands/add/registry-option.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default async function () {
1212
});
1313
// The environment variable has priority over the .npmrc
1414
const originalRegistryVariable = process.env['NPM_CONFIG_REGISTRY'];
15-
process.env['NPM_CONFIG_REGISTRY'] = undefined;
15+
delete process.env['NPM_CONFIG_REGISTRY'];
1616

1717
try {
1818
await expectToFail(() => ng('add', '@angular/pwa', '--skip-confirmation'));
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { expectFileNotToExist, expectFileToExist } from '../../../utils/fs';
2+
import { git, ng } from '../../../utils/process';
3+
import { createNpmConfigForAuthentication } from '../../../utils/registry';
4+
import { expectToFail } from '../../../utils/utils';
5+
6+
export default async function () {
7+
// The environment variable has priority over the .npmrc
8+
const originalRegistryVariable = process.env['NPM_CONFIG_REGISTRY'];
9+
delete process.env['NPM_CONFIG_REGISTRY'];
10+
11+
try {
12+
const command = ['add', '@angular/pwa', '--skip-confirmation'];
13+
await expectFileNotToExist('src/manifest.webmanifest');
14+
15+
// Works with unscoped registry authentication details
16+
await createNpmConfigForAuthentication(false);
17+
await ng(...command);
18+
await expectFileToExist('src/manifest.webmanifest');
19+
await git('clean', '-dxf');
20+
21+
// Works with scoped registry authentication details
22+
await expectFileNotToExist('src/manifest.webmanifest');
23+
24+
await createNpmConfigForAuthentication(true);
25+
await ng(...command);
26+
await expectFileToExist('src/manifest.webmanifest');
27+
28+
// Invalid authentication token
29+
await createNpmConfigForAuthentication(false, true);
30+
await expectToFail(() => ng(...command));
31+
32+
await createNpmConfigForAuthentication(true, true);
33+
await expectToFail(() => ng(...command));
34+
} finally {
35+
process.env['NPM_CONFIG_REGISTRY'] = originalRegistryVariable;
36+
}
37+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { ng } from '../../utils/process';
2+
import { createNpmConfigForAuthentication } from '../../utils/registry';
3+
import { expectToFail } from '../../utils/utils';
4+
5+
export default async function () {
6+
// The environment variable has priority over the .npmrc
7+
const originalRegistryVariable = process.env['NPM_CONFIG_REGISTRY'];
8+
delete process.env['NPM_CONFIG_REGISTRY'];
9+
10+
const worksMessage = 'We analyzed your package.json';
11+
12+
try {
13+
// Valid authentication token
14+
await createNpmConfigForAuthentication(false);
15+
const { stdout: stdout1 } = await ng('update');
16+
if (!stdout1.includes(worksMessage)) {
17+
throw new Error(`Expected stdout to contain "${worksMessage}"`);
18+
}
19+
20+
await createNpmConfigForAuthentication(true);
21+
const { stdout: stdout2 } = await ng('update');
22+
if (!stdout2.includes(worksMessage)) {
23+
throw new Error(`Expected stdout to contain "${worksMessage}"`);
24+
}
25+
26+
// Invalid authentication token
27+
await createNpmConfigForAuthentication(false, true);
28+
await expectToFail(() => ng('update'));
29+
30+
await createNpmConfigForAuthentication(true, true);
31+
await expectToFail(() => ng('update'));
32+
} finally {
33+
process.env['NPM_CONFIG_REGISTRY'] = originalRegistryVariable;
34+
}
35+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { ChildProcess, spawn } from 'child_process';
2+
import { copyFileSync, mkdtempSync, realpathSync } from 'fs';
3+
import { tmpdir } from 'os';
4+
import { join } from 'path';
5+
import { writeFile } from './fs';
6+
7+
export function createNpmRegistry(withAuthentication = false): ChildProcess {
8+
// Setup local package registry
9+
const registryPath = mkdtempSync(join(realpathSync(tmpdir()), 'angular-cli-e2e-registry-'));
10+
11+
copyFileSync(
12+
join(__dirname, '../../', withAuthentication ? 'verdaccio_auth.yaml' : 'verdaccio.yaml'),
13+
join(registryPath, 'verdaccio.yaml'),
14+
);
15+
16+
return spawn('node', [require.resolve('verdaccio/bin/verdaccio'), '-c', './verdaccio.yaml'], {
17+
cwd: registryPath,
18+
stdio: 'inherit',
19+
});
20+
}
21+
22+
export function createNpmConfigForAuthentication(
23+
/**
24+
* When true, the authentication token will be scoped to the registry URL.
25+
* @example
26+
* ```ini
27+
* //localhost:4876/:_auth="dGVzdGluZzpzM2NyZXQ="
28+
* ```
29+
*
30+
* When false, the authentication will be added as seperate key.
31+
* @example
32+
* ```ini
33+
* _auth="dGVzdGluZzpzM2NyZXQ="`
34+
* ```
35+
*/
36+
scopedAuthentication: boolean,
37+
/** When true, an incorrect token is used. Use this to validate authentication failures. */
38+
invalidToken = false,
39+
): Promise<void> {
40+
// Token was generated using `echo -n 'testing:s3cret' | openssl base64`.
41+
const token = invalidToken ? `invalid=` : `dGVzdGluZzpzM2NyZXQ=`;
42+
const registry = `//localhost:4876/`;
43+
44+
return writeFile(
45+
'.npmrc',
46+
scopedAuthentication
47+
? `
48+
${registry}:_auth="${token}"
49+
registry=http:${registry}
50+
`
51+
: `
52+
_auth="${token}"
53+
registry=http:${registry}
54+
`,
55+
);
56+
}

tests/legacy-cli/e2e_runner.ts

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@
33
import { logging } from '@angular-devkit/core';
44
import { createConsoleLogger } from '@angular-devkit/core/node';
55
import * as colors from 'ansi-colors';
6-
import { spawn } from 'child_process';
7-
import * as fs from 'fs';
86
import glob from 'glob';
97
import minimist from 'minimist';
10-
import * as os from 'os';
118
import * as path from 'path';
129
import { setGlobalVariable } from './e2e/utils/env';
1310
import { gitClean } from './e2e/utils/git';
11+
import { createNpmRegistry } from './e2e/utils/registry';
1412

1513
Error.stackTraceLimit = Infinity;
1614

@@ -127,16 +125,8 @@ setGlobalVariable('ci', process.env['CI']?.toLowerCase() === 'true' || process.e
127125
setGlobalVariable('package-manager', argv.yarn ? 'yarn' : 'npm');
128126
setGlobalVariable('package-registry', 'http://localhost:4873');
129127

130-
// Setup local package registry
131-
const registryPath = fs.mkdtempSync(
132-
path.join(fs.realpathSync(os.tmpdir()), 'angular-cli-e2e-registry-'),
133-
);
134-
fs.copyFileSync(path.join(__dirname, 'verdaccio.yaml'), path.join(registryPath, 'verdaccio.yaml'));
135-
const registryProcess = spawn(
136-
'node',
137-
[require.resolve('verdaccio/bin/verdaccio'), '-c', './verdaccio.yaml'],
138-
{ cwd: registryPath, stdio: 'inherit' },
139-
);
128+
const registryProcess = createNpmRegistry();
129+
const secureRegistryProcess = createNpmRegistry(true);
140130

141131
testsToRun
142132
.reduce((previous, relativeName, testIndex) => {
@@ -210,9 +200,8 @@ testsToRun
210200
}, Promise.resolve())
211201
.then(
212202
() => {
213-
if (registryProcess) {
214-
registryProcess.kill();
215-
}
203+
registryProcess.kill();
204+
secureRegistryProcess.kill();
216205

217206
console.log(colors.green('Done.'));
218207
process.exit(0);
@@ -223,9 +212,8 @@ testsToRun
223212
console.error(colors.red(err.message));
224213
console.error(colors.red(err.stack));
225214

226-
if (registryProcess) {
227-
registryProcess.kill();
228-
}
215+
registryProcess.kill();
216+
secureRegistryProcess.kill();
229217

230218
if (argv.debug) {
231219
console.log(`Current Directory: ${process.cwd()}`);

tests/legacy-cli/verdaccio.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ storage: ./storage
33
auth:
44
auth-memory:
55
users: {}
6-
6+
listen: localhost:4873
77
uplinks:
88
npmjs:
99
url: https://registry.npmjs.org/
@@ -20,7 +20,7 @@ packages:
2020
'@angular/{cli,pwa}':
2121
access: $all
2222
publish: $all
23-
23+
2424
'@angular-devkit/*':
2525
access: $all
2626
publish: $all
@@ -42,8 +42,8 @@ packages:
4242
proxy: npmjs
4343

4444
logs:
45-
- {type: stdout, format: pretty, level: warn}
45+
- { type: stdout, format: pretty, level: warn }
4646

4747
# https://github.com/verdaccio/verdaccio/issues/301
4848
server:
49-
keepAliveTimeout: 0
49+
keepAliveTimeout: 0

tests/legacy-cli/verdaccio_auth.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
storage: ./storage
2+
auth:
3+
auth-memory:
4+
users:
5+
testing:
6+
name: testing
7+
password: s3cret
8+
listen: localhost:4876
9+
uplinks:
10+
local:
11+
url: http://localhost:4873
12+
cache: false
13+
maxage: 20m
14+
max_fails: 32
15+
timeout: 60s
16+
agent_options:
17+
keepAlive: true
18+
maxSockets: 32
19+
maxFreeSockets: 8
20+
packages:
21+
'**':
22+
access: $authenticated
23+
proxy: local
24+
logs:
25+
- { type: stdout, format: pretty, level: http }
26+
# https://github.com/verdaccio/verdaccio/issues/301
27+
server:
28+
keepAliveTimeout: 0

0 commit comments

Comments
 (0)