From 6662e0268c638f53152bd40b4d0fb125b87e9fbf Mon Sep 17 00:00:00 2001 From: Felix P Date: Mon, 17 Jul 2023 16:29:25 +0200 Subject: [PATCH 01/11] Add support for scoped-registries --- src/types.ts | 7 ++ src/utils.ts | 22 ++++- .../unit/src/__snapshots__/utils.spec.ts.snap | 83 +++++++++++++++++++ tests/unit/src/utils.spec.ts | 23 +++++ 4 files changed, 133 insertions(+), 2 deletions(-) diff --git a/src/types.ts b/src/types.ts index 93de1bf..af9c404 100644 --- a/src/types.ts +++ b/src/types.ts @@ -6,8 +6,15 @@ export type Suite = { } } +export type ScoredRegistry = { + scope: string; + url: string; + authToken?: string; +}; + export type NpmConfig = { registry?: string; + scopedRegistries?: ScoredRegistry[]; strictSSL?: boolean | string | null; packageLock?: boolean | string | null; packages?: { [key: string]: string | number }; diff --git a/src/utils.ts b/src/utils.ts index d45969b..cbc5707 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -4,7 +4,7 @@ import fs from 'fs'; import _ from 'lodash'; import yargs from 'yargs/yargs'; import npm from './npm'; -import { NpmConfigContainer, PathContainer, SuitesContainer, Suite, NpmConfig, NodeContext } from './types'; +import { NpmConfigContainer, PathContainer, SuitesContainer, Suite, NpmConfig, NodeContext, ScoredRegistry } from './types'; const DEFAULT_REGISTRY = 'https://registry.npmjs.org'; @@ -98,12 +98,30 @@ export function getNpmConfig (runnerConfig: NpmConfigContainer) { if (runnerConfig.npm === undefined) { return {}; } - return { + const cfg: { [key:string]: string | boolean | null } = { registry: runnerConfig.npm.registry || getDefaultRegistry(), 'strict-ssl': runnerConfig.npm.strictSSL !== false, // Setting to false to avoid dealing with the generated file. 'package-lock': runnerConfig.npm.packageLock === true }; + + + // As npm config accepts only key-values pairs, we do the translation + if (runnerConfig.npm.scopedRegistries) { + for (const sr of runnerConfig.npm.scopedRegistries) { + cfg[`${sr.scope}:registry`] = sr.url; + if (sr.authToken) { + let fixedUrl = sr.url; + if (fixedUrl.startsWith('http://')) { + fixedUrl = sr.url.substring(5); + } else if (fixedUrl.startsWith('https://')) { + fixedUrl = sr.url.substring(6); + } + cfg[`${fixedUrl}`] = sr.authToken; + } + } + } + return cfg; } export async function prepareNpmEnv (runCfg: NpmConfigContainer & PathContainer, nodeCtx: NodeContext) { diff --git a/tests/unit/src/__snapshots__/utils.spec.ts.snap b/tests/unit/src/__snapshots__/utils.spec.ts.snap index 02a5e7e..9b1a9db 100644 --- a/tests/unit/src/__snapshots__/utils.spec.ts.snap +++ b/tests/unit/src/__snapshots__/utils.spec.ts.snap @@ -69,6 +69,69 @@ Array [ ] `; +exports[`utils .prepareNpmEnv should configure scoped-registry 1`] = ` +Array [ + Object { + "nodePath": "node-bin", + "npmPath": "npm-bin", + }, + Object { + "@saucelabs:registry": "http://demo.registry.com/npm-test/", + "audit": false, + "fund": false, + "json": false, + "noproxy": "registry.npmjs.org", + "package-lock": false, + "registry": "https://registry.npmjs.org", + "save": false, + "strict-ssl": true, + "update-notifier": false, + }, +] +`; + +exports[`utils .prepareNpmEnv should configure scoped-registry with authtentication 1`] = ` +Array [ + Object { + "nodePath": "node-bin", + "npmPath": "npm-bin", + }, + Object { + "//demo.registry.com/npm-test/": "secretToken", + "@saucelabs:registry": "http://demo.registry.com/npm-test/", + "audit": false, + "fund": false, + "json": false, + "noproxy": "registry.npmjs.org", + "package-lock": false, + "registry": "https://registry.npmjs.org", + "save": false, + "strict-ssl": true, + "update-notifier": false, + }, +] +`; + +exports[`utils .prepareNpmEnv should make flat scopedRegistries 1`] = ` +Array [ + Object { + "nodePath": "node-bin", + "npmPath": "npm-bin", + }, + Object { + "audit": false, + "fund": false, + "json": false, + "noproxy": "registry.npmjs.org", + "package-lock": false, + "registry": "https://registry.npmjs.org", + "save": false, + "strict-ssl": true, + "update-notifier": false, + }, +] +`; + exports[`utils .prepareNpmEnv should set right registry for npm 1`] = ` Array [ Object { @@ -171,6 +234,26 @@ Array [ ] `; +exports[`utils .prepareNpmEnv should use true as the default value for strictSSL 2`] = ` +Array [ + Object { + "nodePath": "node-bin", + "npmPath": "npm-bin", + }, + Object { + "audit": false, + "fund": false, + "json": false, + "noproxy": "registry.npmjs.org", + "package-lock": false, + "registry": "https://registry.npmjs.org", + "save": false, + "strict-ssl": true, + "update-notifier": false, + }, +] +`; + exports[`utils .prepareNpmEnv should use true as the default value for strictSSL if it's null in cfg 1`] = ` Array [ Object { diff --git a/tests/unit/src/utils.spec.ts b/tests/unit/src/utils.spec.ts index 378754e..9ce64b0 100644 --- a/tests/unit/src/utils.spec.ts +++ b/tests/unit/src/utils.spec.ts @@ -195,6 +195,29 @@ describe('utils', function () { await prepareNpmEnv(cfg, nodeCtx); expect(loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]).toMatchSnapshot(); }); + it('should configure scoped-registry', async function () { + const cfg = _.cloneDeep(runCfg); + cfg.npm ||= {}; + cfg.npm.scopedRegistries = [{ + url: 'http://demo.registry.com/npm-test/', + scope: '@saucelabs', + }]; + const loadSpyOn = jest.spyOn(npm, 'configure'); + await prepareNpmEnv(cfg, nodeCtx); + expect(loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]).toMatchSnapshot(); + }); + it('should configure scoped-registry with authtentication', async function () { + const cfg = _.cloneDeep(runCfg); + cfg.npm ||= {}; + cfg.npm.scopedRegistries = [{ + url: 'http://demo.registry.com/npm-test/', + scope: '@saucelabs', + authToken: 'secretToken', + }]; + const loadSpyOn = jest.spyOn(npm, 'configure'); + await prepareNpmEnv(cfg, nodeCtx); + expect(loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]).toMatchSnapshot(); + }); it('should use rebuild node_modules', async function () { const rebuildSpyOn = jest.spyOn(npm, 'rebuild'); const statSyncSpyOn = jest.spyOn(fs, 'statSync'); From ed574985a03ce7b058c3f699be6f69924bf4343c Mon Sep 17 00:00:00 2001 From: Felix P Date: Mon, 17 Jul 2023 16:38:14 +0200 Subject: [PATCH 02/11] remove obsolete snapshots --- .../unit/src/__snapshots__/utils.spec.ts.snap | 40 ------------------- 1 file changed, 40 deletions(-) diff --git a/tests/unit/src/__snapshots__/utils.spec.ts.snap b/tests/unit/src/__snapshots__/utils.spec.ts.snap index 9b1a9db..535c222 100644 --- a/tests/unit/src/__snapshots__/utils.spec.ts.snap +++ b/tests/unit/src/__snapshots__/utils.spec.ts.snap @@ -112,26 +112,6 @@ Array [ ] `; -exports[`utils .prepareNpmEnv should make flat scopedRegistries 1`] = ` -Array [ - Object { - "nodePath": "node-bin", - "npmPath": "npm-bin", - }, - Object { - "audit": false, - "fund": false, - "json": false, - "noproxy": "registry.npmjs.org", - "package-lock": false, - "registry": "https://registry.npmjs.org", - "save": false, - "strict-ssl": true, - "update-notifier": false, - }, -] -`; - exports[`utils .prepareNpmEnv should set right registry for npm 1`] = ` Array [ Object { @@ -234,26 +214,6 @@ Array [ ] `; -exports[`utils .prepareNpmEnv should use true as the default value for strictSSL 2`] = ` -Array [ - Object { - "nodePath": "node-bin", - "npmPath": "npm-bin", - }, - Object { - "audit": false, - "fund": false, - "json": false, - "noproxy": "registry.npmjs.org", - "package-lock": false, - "registry": "https://registry.npmjs.org", - "save": false, - "strict-ssl": true, - "update-notifier": false, - }, -] -`; - exports[`utils .prepareNpmEnv should use true as the default value for strictSSL if it's null in cfg 1`] = ` Array [ Object { From e439ef127d9d11dd94030c5caf95c8ca9a34e348 Mon Sep 17 00:00:00 2001 From: Felix P Date: Mon, 17 Jul 2023 22:20:16 +0200 Subject: [PATCH 03/11] Moved from ScopedRegistries to Registries --- src/types.ts | 4 ++-- src/utils.ts | 18 +++++++++--------- tests/unit/src/npm.spec.ts | 6 +++--- tests/unit/src/utils.spec.ts | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/types.ts b/src/types.ts index af9c404..f9b7d06 100644 --- a/src/types.ts +++ b/src/types.ts @@ -6,7 +6,7 @@ export type Suite = { } } -export type ScoredRegistry = { +export type Registry = { scope: string; url: string; authToken?: string; @@ -14,7 +14,7 @@ export type ScoredRegistry = { export type NpmConfig = { registry?: string; - scopedRegistries?: ScoredRegistry[]; + registries?: Registry[]; strictSSL?: boolean | string | null; packageLock?: boolean | string | null; packages?: { [key: string]: string | number }; diff --git a/src/utils.ts b/src/utils.ts index cbc5707..2ec3280 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -4,7 +4,7 @@ import fs from 'fs'; import _ from 'lodash'; import yargs from 'yargs/yargs'; import npm from './npm'; -import { NpmConfigContainer, PathContainer, SuitesContainer, Suite, NpmConfig, NodeContext, ScoredRegistry } from './types'; +import { NpmConfigContainer, PathContainer, SuitesContainer, Suite, NpmConfig, NodeContext, Registry } from './types'; const DEFAULT_REGISTRY = 'https://registry.npmjs.org'; @@ -107,17 +107,17 @@ export function getNpmConfig (runnerConfig: NpmConfigContainer) { // As npm config accepts only key-values pairs, we do the translation - if (runnerConfig.npm.scopedRegistries) { - for (const sr of runnerConfig.npm.scopedRegistries) { + if (runnerConfig.npm.registries) { + for (const sr of runnerConfig.npm.registries) { cfg[`${sr.scope}:registry`] = sr.url; if (sr.authToken) { - let fixedUrl = sr.url; - if (fixedUrl.startsWith('http://')) { - fixedUrl = sr.url.substring(5); - } else if (fixedUrl.startsWith('https://')) { - fixedUrl = sr.url.substring(6); + let authUrl = sr.url; + if (authUrl.startsWith('http://')) { + authUrl = sr.url.substring(5); + } else if (authUrl.startsWith('https://')) { + authUrl = sr.url.substring(6); } - cfg[`${fixedUrl}`] = sr.authToken; + cfg[`${authUrl}:_authToken`] = sr.authToken; } } } diff --git a/tests/unit/src/npm.spec.ts b/tests/unit/src/npm.spec.ts index 5260163..80dd61a 100644 --- a/tests/unit/src/npm.spec.ts +++ b/tests/unit/src/npm.spec.ts @@ -22,12 +22,12 @@ describe('NPM', function () { spawk.unload(); }); - it('.configure must invoke npm config set', async function () { + it.only('.configure must invoke npm config set', async function () { const interceptor = spawk.spawn(nodeCtx.nodePath).stdout('npm runned').exit(0); - await NPM.configure(nodeCtx, { registry: 'myregistry' }); + await NPM.configure(nodeCtx, { registry: 'myregistry', '@saucelabs:registry': 'https://google.com/' }); expect(interceptor.calledWith.command).toEqual(nodeCtx.nodePath); - expect(interceptor.calledWith.args).toEqual([nodeCtx.npmPath, 'config', 'set', 'registry=myregistry']); + expect(interceptor.calledWith.args).toEqual([nodeCtx.npmPath, 'config', 'set', 'registry=myregistry', '@saucelabs:registry=https://google.com/']); }); it('.rebuild must invoke npm rebuild', async function () { diff --git a/tests/unit/src/utils.spec.ts b/tests/unit/src/utils.spec.ts index 9ce64b0..2fec2d6 100644 --- a/tests/unit/src/utils.spec.ts +++ b/tests/unit/src/utils.spec.ts @@ -198,7 +198,7 @@ describe('utils', function () { it('should configure scoped-registry', async function () { const cfg = _.cloneDeep(runCfg); cfg.npm ||= {}; - cfg.npm.scopedRegistries = [{ + cfg.npm.registries = [{ url: 'http://demo.registry.com/npm-test/', scope: '@saucelabs', }]; @@ -209,7 +209,7 @@ describe('utils', function () { it('should configure scoped-registry with authtentication', async function () { const cfg = _.cloneDeep(runCfg); cfg.npm ||= {}; - cfg.npm.scopedRegistries = [{ + cfg.npm.registries = [{ url: 'http://demo.registry.com/npm-test/', scope: '@saucelabs', authToken: 'secretToken', From d70bfd8fc85b49968c2b4e2e9d5aa1a52fe8a304 Mon Sep 17 00:00:00 2001 From: Felix P Date: Mon, 17 Jul 2023 22:23:41 +0200 Subject: [PATCH 04/11] More clear --- src/utils.ts | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 2ec3280..1ac4a43 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -94,6 +94,16 @@ export function hasNodeModulesFolder (runCfg: PathContainer) { return false; } +function getRegistryAuthConfigField (url: string): string { + let authUrl = url; + if (authUrl.startsWith('http://')) { + authUrl = url.substring(5); + } else if (authUrl.startsWith('https://')) { + authUrl = url.substring(6); + } + return `${authUrl}:_authToken`; +} + export function getNpmConfig (runnerConfig: NpmConfigContainer) { if (runnerConfig.npm === undefined) { return {}; @@ -109,15 +119,15 @@ export function getNpmConfig (runnerConfig: NpmConfigContainer) { // As npm config accepts only key-values pairs, we do the translation if (runnerConfig.npm.registries) { for (const sr of runnerConfig.npm.registries) { - cfg[`${sr.scope}:registry`] = sr.url; + if (sr.scope) { + cfg[`${sr.scope}:registry`] = sr.url; + } else { + cfg.registry = sr.url; + } + if (sr.authToken) { - let authUrl = sr.url; - if (authUrl.startsWith('http://')) { - authUrl = sr.url.substring(5); - } else if (authUrl.startsWith('https://')) { - authUrl = sr.url.substring(6); - } - cfg[`${authUrl}:_authToken`] = sr.authToken; + const field = getRegistryAuthConfigField(sr.url); + cfg[field] = sr.authToken; } } } From 039d1a7f1af399e113ea6a7f1249e8eb6846be69 Mon Sep 17 00:00:00 2001 From: Felix P Date: Mon, 17 Jul 2023 22:35:30 +0200 Subject: [PATCH 05/11] Add priority check --- src/types.ts | 2 +- src/utils.ts | 2 +- .../unit/src/__snapshots__/utils.spec.ts.snap | 24 ++++++++++++++++++- tests/unit/src/npm.spec.ts | 2 +- tests/unit/src/utils.spec.ts | 15 ++++++++++++ 5 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/types.ts b/src/types.ts index f9b7d06..ceca86c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,7 +7,7 @@ export type Suite = { } export type Registry = { - scope: string; + scope?: string; url: string; authToken?: string; }; diff --git a/src/utils.ts b/src/utils.ts index 1ac4a43..30eedff 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -54,6 +54,7 @@ export async function setUpNpmConfig (nodeCtx: NodeContext, userConfig: NpmConfi registry: getDefaultRegistry(), 'update-notifier': false }; + await npm.configure(nodeCtx, Object.assign({}, defaultConfig, userConfig)); } @@ -115,7 +116,6 @@ export function getNpmConfig (runnerConfig: NpmConfigContainer) { 'package-lock': runnerConfig.npm.packageLock === true }; - // As npm config accepts only key-values pairs, we do the translation if (runnerConfig.npm.registries) { for (const sr of runnerConfig.npm.registries) { diff --git a/tests/unit/src/__snapshots__/utils.spec.ts.snap b/tests/unit/src/__snapshots__/utils.spec.ts.snap index 535c222..fd2c652 100644 --- a/tests/unit/src/__snapshots__/utils.spec.ts.snap +++ b/tests/unit/src/__snapshots__/utils.spec.ts.snap @@ -17,6 +17,28 @@ Object { } `; +exports[`utils .prepareNpmEnv registries should be prioritary on registry 1`] = ` +Array [ + Object { + "nodePath": "node-bin", + "npmPath": "npm-bin", + }, + Object { + "//demo.registry.com/npm-test/:_authToken": "secretToken", + "@saucelabs:registry": "http://demo.registry.com/npm-test/", + "audit": false, + "fund": false, + "json": false, + "noproxy": "registry.npmjs.org", + "package-lock": false, + "registry": "http://demo.registry.com", + "save": false, + "strict-ssl": true, + "update-notifier": false, + }, +] +`; + exports[`utils .prepareNpmEnv should be able to set strictSSL to false 1`] = ` Array [ Object { @@ -97,7 +119,7 @@ Array [ "npmPath": "npm-bin", }, Object { - "//demo.registry.com/npm-test/": "secretToken", + "//demo.registry.com/npm-test/:_authToken": "secretToken", "@saucelabs:registry": "http://demo.registry.com/npm-test/", "audit": false, "fund": false, diff --git a/tests/unit/src/npm.spec.ts b/tests/unit/src/npm.spec.ts index 80dd61a..5f7a547 100644 --- a/tests/unit/src/npm.spec.ts +++ b/tests/unit/src/npm.spec.ts @@ -22,7 +22,7 @@ describe('NPM', function () { spawk.unload(); }); - it.only('.configure must invoke npm config set', async function () { + it('.configure must invoke npm config set', async function () { const interceptor = spawk.spawn(nodeCtx.nodePath).stdout('npm runned').exit(0); await NPM.configure(nodeCtx, { registry: 'myregistry', '@saucelabs:registry': 'https://google.com/' }); diff --git a/tests/unit/src/utils.spec.ts b/tests/unit/src/utils.spec.ts index 2fec2d6..2e577e6 100644 --- a/tests/unit/src/utils.spec.ts +++ b/tests/unit/src/utils.spec.ts @@ -218,6 +218,21 @@ describe('utils', function () { await prepareNpmEnv(cfg, nodeCtx); expect(loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]).toMatchSnapshot(); }); + it('registries should be prioritary on registry', async function () { + const cfg = _.cloneDeep(runCfg); + cfg.npm ||= {}; + cfg.npm.registry = 'http://demo.bad-registry.com', + cfg.npm.registries = [{ + url: 'http://demo.registry.com', + }, { + url: 'http://demo.registry.com/npm-test/', + scope: '@saucelabs', + authToken: 'secretToken', + }]; + const loadSpyOn = jest.spyOn(npm, 'configure'); + await prepareNpmEnv(cfg, nodeCtx); + expect(loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]).toMatchSnapshot(); + }); it('should use rebuild node_modules', async function () { const rebuildSpyOn = jest.spyOn(npm, 'rebuild'); const statSyncSpyOn = jest.spyOn(fs, 'statSync'); From ea26793b6d72ae01447a62bb09ef3299f52e10b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20P?= Date: Mon, 17 Jul 2023 23:48:34 +0200 Subject: [PATCH 06/11] Update src/utils.ts Co-authored-by: Alex Plischke --- src/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.ts b/src/utils.ts index 30eedff..4ed2d6e 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -116,7 +116,7 @@ export function getNpmConfig (runnerConfig: NpmConfigContainer) { 'package-lock': runnerConfig.npm.packageLock === true }; - // As npm config accepts only key-values pairs, we do the translation + // As npm config accepts only key-value pairs, we do the translation if (runnerConfig.npm.registries) { for (const sr of runnerConfig.npm.registries) { if (sr.scope) { From f2f4be7dab66606b453d09ff10314c98bdb6877b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20P?= Date: Mon, 17 Jul 2023 23:49:35 +0200 Subject: [PATCH 07/11] Update tests/unit/src/utils.spec.ts Co-authored-by: Mike Han <56001373+mhan83@users.noreply.github.com> --- tests/unit/src/utils.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/src/utils.spec.ts b/tests/unit/src/utils.spec.ts index 2e577e6..4c3f505 100644 --- a/tests/unit/src/utils.spec.ts +++ b/tests/unit/src/utils.spec.ts @@ -206,7 +206,7 @@ describe('utils', function () { await prepareNpmEnv(cfg, nodeCtx); expect(loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]).toMatchSnapshot(); }); - it('should configure scoped-registry with authtentication', async function () { + it('should configure scoped-registry with authentication', async function () { const cfg = _.cloneDeep(runCfg); cfg.npm ||= {}; cfg.npm.registries = [{ From 48f9473e67ffffdd63d99516f7717eeb0bb727cc Mon Sep 17 00:00:00 2001 From: Felix P Date: Mon, 17 Jul 2023 23:52:25 +0200 Subject: [PATCH 08/11] Fix snapshot --- tests/unit/src/__snapshots__/utils.spec.ts.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/src/__snapshots__/utils.spec.ts.snap b/tests/unit/src/__snapshots__/utils.spec.ts.snap index fd2c652..04a54dc 100644 --- a/tests/unit/src/__snapshots__/utils.spec.ts.snap +++ b/tests/unit/src/__snapshots__/utils.spec.ts.snap @@ -112,7 +112,7 @@ Array [ ] `; -exports[`utils .prepareNpmEnv should configure scoped-registry with authtentication 1`] = ` +exports[`utils .prepareNpmEnv should configure scoped-registry with authentication 1`] = ` Array [ Object { "nodePath": "node-bin", From fe20f50b8d81bdcb2ef9743b9c7fc1a50dfd8a1c Mon Sep 17 00:00:00 2001 From: Felix P Date: Tue, 18 Jul 2023 11:15:07 +0200 Subject: [PATCH 09/11] Don't rely on snapshots --- .../unit/src/__snapshots__/utils.spec.ts.snap | 65 ------------------- tests/unit/src/utils.spec.ts | 21 +++++- 2 files changed, 18 insertions(+), 68 deletions(-) diff --git a/tests/unit/src/__snapshots__/utils.spec.ts.snap b/tests/unit/src/__snapshots__/utils.spec.ts.snap index 04a54dc..02a5e7e 100644 --- a/tests/unit/src/__snapshots__/utils.spec.ts.snap +++ b/tests/unit/src/__snapshots__/utils.spec.ts.snap @@ -17,28 +17,6 @@ Object { } `; -exports[`utils .prepareNpmEnv registries should be prioritary on registry 1`] = ` -Array [ - Object { - "nodePath": "node-bin", - "npmPath": "npm-bin", - }, - Object { - "//demo.registry.com/npm-test/:_authToken": "secretToken", - "@saucelabs:registry": "http://demo.registry.com/npm-test/", - "audit": false, - "fund": false, - "json": false, - "noproxy": "registry.npmjs.org", - "package-lock": false, - "registry": "http://demo.registry.com", - "save": false, - "strict-ssl": true, - "update-notifier": false, - }, -] -`; - exports[`utils .prepareNpmEnv should be able to set strictSSL to false 1`] = ` Array [ Object { @@ -91,49 +69,6 @@ Array [ ] `; -exports[`utils .prepareNpmEnv should configure scoped-registry 1`] = ` -Array [ - Object { - "nodePath": "node-bin", - "npmPath": "npm-bin", - }, - Object { - "@saucelabs:registry": "http://demo.registry.com/npm-test/", - "audit": false, - "fund": false, - "json": false, - "noproxy": "registry.npmjs.org", - "package-lock": false, - "registry": "https://registry.npmjs.org", - "save": false, - "strict-ssl": true, - "update-notifier": false, - }, -] -`; - -exports[`utils .prepareNpmEnv should configure scoped-registry with authentication 1`] = ` -Array [ - Object { - "nodePath": "node-bin", - "npmPath": "npm-bin", - }, - Object { - "//demo.registry.com/npm-test/:_authToken": "secretToken", - "@saucelabs:registry": "http://demo.registry.com/npm-test/", - "audit": false, - "fund": false, - "json": false, - "noproxy": "registry.npmjs.org", - "package-lock": false, - "registry": "https://registry.npmjs.org", - "save": false, - "strict-ssl": true, - "update-notifier": false, - }, -] -`; - exports[`utils .prepareNpmEnv should set right registry for npm 1`] = ` Array [ Object { diff --git a/tests/unit/src/utils.spec.ts b/tests/unit/src/utils.spec.ts index 4c3f505..76ee68a 100644 --- a/tests/unit/src/utils.spec.ts +++ b/tests/unit/src/utils.spec.ts @@ -203,8 +203,13 @@ describe('utils', function () { scope: '@saucelabs', }]; const loadSpyOn = jest.spyOn(npm, 'configure'); + loadSpyOn.mockClear(); await prepareNpmEnv(cfg, nodeCtx); - expect(loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]).toMatchSnapshot(); + + expect(loadSpyOn).toHaveBeenCalledTimes(1); + const call = loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]; + expect(call[1]['@saucelabs:registry']).toBe('http://demo.registry.com/npm-test/'); + expect(call[1].registry).toBe('https://registry.npmjs.org'); }); it('should configure scoped-registry with authentication', async function () { const cfg = _.cloneDeep(runCfg); @@ -215,8 +220,13 @@ describe('utils', function () { authToken: 'secretToken', }]; const loadSpyOn = jest.spyOn(npm, 'configure'); + loadSpyOn.mockClear(); await prepareNpmEnv(cfg, nodeCtx); - expect(loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]).toMatchSnapshot(); + expect(loadSpyOn).toHaveBeenCalledTimes(1); + const call = loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]; + expect(call[1]['//demo.registry.com/npm-test/:_authToken']).toBe('secretToken'); + expect(call[1]['@saucelabs:registry']).toBe('http://demo.registry.com/npm-test/'); + expect(call[1].registry).toBe('https://registry.npmjs.org'); }); it('registries should be prioritary on registry', async function () { const cfg = _.cloneDeep(runCfg); @@ -230,8 +240,13 @@ describe('utils', function () { authToken: 'secretToken', }]; const loadSpyOn = jest.spyOn(npm, 'configure'); + loadSpyOn.mockClear(); await prepareNpmEnv(cfg, nodeCtx); - expect(loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]).toMatchSnapshot(); + expect(loadSpyOn).toHaveBeenCalledTimes(1); + const call = loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]; + expect(call[1]['//demo.registry.com/npm-test/:_authToken']).toBe('secretToken'); + expect(call[1]['@saucelabs:registry']).toBe('http://demo.registry.com/npm-test/'); + expect(call[1].registry).toBe('http://demo.registry.com'); }); it('should use rebuild node_modules', async function () { const rebuildSpyOn = jest.spyOn(npm, 'rebuild'); From 7e329b39e2c9c54fd24d9707a422fc8cb1fc8397 Mon Sep 17 00:00:00 2001 From: Felix P Date: Tue, 18 Jul 2023 23:45:40 +0200 Subject: [PATCH 10/11] Annotate registry as deprecated --- src/types.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/types.ts b/src/types.ts index ceca86c..436c81a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -13,6 +13,9 @@ export type Registry = { }; export type NpmConfig = { + /** + * @deprecated: registry should be avoided in favor of a "registries" entry. + */ registry?: string; registries?: Registry[]; strictSSL?: boolean | string | null; From df4f13b7c5aab9997df044ea90de4cb378133de7 Mon Sep 17 00:00:00 2001 From: Felix P Date: Tue, 18 Jul 2023 23:50:29 +0200 Subject: [PATCH 11/11] Don't use deprecated field anymore --- src/utils.ts | 2 +- tests/unit/src/utils.spec.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 4ed2d6e..4884b71 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -4,7 +4,7 @@ import fs from 'fs'; import _ from 'lodash'; import yargs from 'yargs/yargs'; import npm from './npm'; -import { NpmConfigContainer, PathContainer, SuitesContainer, Suite, NpmConfig, NodeContext, Registry } from './types'; +import { NpmConfigContainer, PathContainer, SuitesContainer, Suite, NpmConfig, NodeContext } from './types'; const DEFAULT_REGISTRY = 'https://registry.npmjs.org'; diff --git a/tests/unit/src/utils.spec.ts b/tests/unit/src/utils.spec.ts index 76ee68a..23cf813 100644 --- a/tests/unit/src/utils.spec.ts +++ b/tests/unit/src/utils.spec.ts @@ -153,7 +153,7 @@ describe('utils', function () { it('should use user registry', async function () { const cfg = _.cloneDeep(runCfg); cfg.npm ||= {}; - cfg.npm.registry = 'registryland.io'; + cfg.npm.registries = [{ url: 'registryland.io' }]; const loadSpyOn = jest.spyOn(npm, 'configure'); await prepareNpmEnv(cfg, nodeCtx); expect(loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]).toMatchSnapshot(); @@ -172,7 +172,7 @@ describe('utils', function () { const cfg = _.cloneDeep(runCfg); cfg.npm ||= {}; cfg.npm.strictSSL = null; - cfg.npm.registry = 'test.strictSSL.null'; + cfg.npm.registries = [{ url: 'test.strictSSL.null' }]; const loadSpyOn = jest.spyOn(npm, 'configure'); await prepareNpmEnv(runCfg, nodeCtx); expect(loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]).toMatchSnapshot(); @@ -181,7 +181,7 @@ describe('utils', function () { const cfg = _.cloneDeep(runCfg); cfg.npm ||= {}; cfg.npm.strictSSL = false; - cfg.npm.registry = 'test.strictSSL.false'; + cfg.npm.registries = [{ url: 'test.strictSSL.false' }]; const loadSpyOn = jest.spyOn(npm, 'configure'); await prepareNpmEnv(cfg, nodeCtx); expect(loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]).toMatchSnapshot(); @@ -190,7 +190,7 @@ describe('utils', function () { const cfg = _.cloneDeep(runCfg); cfg.npm ||= {}; cfg.npm.strictSSL = true; - cfg.npm.registry = 'test.strictSSL.true'; + cfg.npm.registries = [{ url: 'test.strictSSL.true' }]; const loadSpyOn = jest.spyOn(npm, 'configure'); await prepareNpmEnv(cfg, nodeCtx); expect(loadSpyOn.mock.calls[loadSpyOn.mock.calls.length - 1]).toMatchSnapshot();