From 011cdd02b78ef615eb5c49640057e4f743d5894b Mon Sep 17 00:00:00 2001 From: mshanemc Date: Mon, 1 Jan 2024 18:12:43 -0600 Subject: [PATCH] test: stub esm with testdouble (experiment) --- LICENSE.txt | 2 +- package.json | 3 +- test/commands/org/login/login.device.test.ts | 107 +++++++++++++++++-- yarn.lock | 40 ++++++- 4 files changed, 142 insertions(+), 10 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index f2cee7bb..6cfd8734 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2023, Salesforce.com, Inc. +Copyright (c) 2024, Salesforce.com, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/package.json b/package.json index d1f817e7..71f3ee25 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "eslint-plugin-sf-plugin": "^1.17.0", "oclif": "^4.1.0", "shx": "0.3.4", + "testdouble": "^3.20.1", "ts-node": "^10.9.2", "typescript": "^5.3.3" }, @@ -221,7 +222,7 @@ "output": [] }, "link-check": { - "command": "node -e \"process.exit(process.env.CI ? 0 : 1)\" || linkinator \"**/*.md\" --skip \"CHANGELOG.md|node_modules|test/|confluence.internal.salesforce.com|my.salesforce.com|%s\" --markdown --retry --directory-listing --verbosity error", + "command": "node -e \"process.exit(process.env.CI ? 0 : 1)\" || linkinator \"**/*.md\" --skip \"CHANGELOG.md|node_modules|test/|confluence.internal.salesforce.com|%s\" --markdown --retry --directory-listing --verbosity error", "files": [ "./*.md", "./!(CHANGELOG).md", diff --git a/test/commands/org/login/login.device.test.ts b/test/commands/org/login/login.device.test.ts index 0aa59710..667281f5 100644 --- a/test/commands/org/login/login.device.test.ts +++ b/test/commands/org/login/login.device.test.ts @@ -6,16 +6,85 @@ */ /* eslint-disable camelcase */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-unsafe-call */ -import { AuthFields, AuthInfo, DeviceOauthService } from '@salesforce/core'; +/* + * Copyright (c) 2023, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +/* + * Copyright (c) 2023, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +/* + * Copyright (c) 2023, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +/* + * Copyright (c) 2023, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +/* + * Copyright (c) 2023, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +/* + * Copyright (c) 2023, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +/* + * Copyright (c) 2023, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +/* + * Copyright (c) 2023, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +/* + * Copyright (c) 2023, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +/* + * Copyright (c) 2023, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +/* + * Copyright (c) 2023, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +import { AuthFields, AuthInfo, DeviceOauthService, Global, Mode } from '@salesforce/core'; import { MockTestOrgData, TestContext } from '@salesforce/core/lib/testSetup.js'; import { StubbedType, stubInterface, stubMethod } from '@salesforce/ts-sinon'; import { DeviceCodeResponse } from '@salesforce/core/lib/deviceOauthService.js'; import { expect } from 'chai'; import { Config } from '@oclif/core'; import { SfCommand } from '@salesforce/sf-plugins-core'; -import Login from '../../../../src/commands/org/login/device.js'; -import common from '../../../../src/common.js'; +import * as td from 'testdouble'; +import type LoginDevice from '../../../../src/commands/org/login/device.js'; interface Options { approvalTimesout?: boolean; approvalFails?: boolean; @@ -34,6 +103,16 @@ describe('org:login:device', () => { let authFields: AuthFields; let authInfoStub: StubbedType; + let Login: typeof LoginDevice; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let confirmStub: any; + beforeEach(async () => { + confirmStub = (await td.replaceEsm('@inquirer/confirm')).default; + await td.replaceEsm('@inquirer/password', {}, () => Promise.resolve('1234')); + Login = (await import('../../../../src/commands/org/login/device.js')).default; + }); + + afterEach(() => td.reset()); async function prepareStubs(options: Options = {}): Promise { authFields = await testData.getConfig(); @@ -136,11 +215,27 @@ describe('org:login:device', () => { it('should prompt for client secret if client id is provided', async () => { await prepareStubs(); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - $$.SANDBOX.stub(common, 'clientSecretPrompt').resolves('1234'); const login = new Login(['-i', 'CoffeeBeans', '--json'], {} as Config); const response = await login.run(); expect(response.username).to.equal(testData.username); }); + + describe('demo mode', () => { + it('should prompt for when in demo mode (SFDX_ENV=demo)', async () => { + await prepareStubs(); + $$.SANDBOX.stub(Global, 'getEnvironmentMode').returns(Mode.DEMO); + td.when(confirmStub(), { ignoreExtraArgs: true }).thenResolve(true); + const login = new Login(['--json'], {} as Config); + const response = await login.run(); + expect(response.username).to.equal(testData.username); + }); + + it('should exit early when prompt is answered NO', async () => { + $$.SANDBOX.stub(Global, 'getEnvironmentMode').returns(Mode.DEMO); + td.when(confirmStub(), { ignoreExtraArgs: true }).thenResolve(false); + const login = new Login(['--json'], {} as Config); + const response = await login.run(); + expect(response).to.deep.equal({}); + }); + }); }); diff --git a/yarn.lock b/yarn.lock index 13563c31..484e420f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4391,7 +4391,7 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== -is-plain-obj@^1.1.0: +is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== @@ -4414,6 +4414,11 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA== + is-retry-allowed@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" @@ -6390,6 +6395,14 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quibble@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/quibble/-/quibble-0.9.1.tgz#a0eb3a78cfc8696f94f87676021ad32f1d4f7007" + integrity sha512-2EkLLm3CsBhbHfYEgBWHSJZZRpVHUZLeuJVEQoU/lsCqxcOvVkgVlF4nWv2ACWKkb0lgxgMh3m8vq9rhx9LTIg== + dependencies: + lodash "^4.17.21" + resolve "^1.22.8" + quick-format-unescaped@^4.0.3: version "4.0.4" resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" @@ -6606,7 +6619,7 @@ resolve-global@1.0.0, resolve-global@^1.0.0: dependencies: global-dirs "^0.1.1" -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.22.4: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.22.4, resolve@^1.22.8: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -7148,6 +7161,14 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +stringify-object-es5@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/stringify-object-es5/-/stringify-object-es5-2.5.0.tgz#057c3c9a90a127339bb9d1704a290bb7bd0a1ec5" + integrity sha512-vE7Xdx9ylG4JI16zy7/ObKUB+MtxuMcWlj/WHHr3+yAlQoN6sst2stU9E+2Qs3OrlJw/Pf3loWxL1GauEHf6MA== + dependencies: + is-plain-obj "^1.0.0" + is-regexp "^1.0.0" + "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -7271,6 +7292,16 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +testdouble@^3.20.1: + version "3.20.1" + resolved "https://registry.yarnpkg.com/testdouble/-/testdouble-3.20.1.tgz#259aa86087ec69987d3b3ba88e152a5c72bce44c" + integrity sha512-D9Or6ayxr16dPPEkmXyGb8ow7VcQjUzuYFUxPTkx2FdSkn5Z6EC6cxQHwEGhedmE30FAJOYiAW+r7XXg6FmYOQ== + dependencies: + lodash "^4.17.21" + quibble "^0.9.1" + stringify-object-es5 "^2.5.0" + theredoc "^1.0.0" + text-extensions@^1.0.0: version "1.9.0" resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" @@ -7286,6 +7317,11 @@ textextensions@^5.12.0, textextensions@^5.13.0: resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-5.15.0.tgz#4bb3296ad6fc111cf4b39c589dd028d8aaaf7060" integrity sha512-MeqZRHLuaGamUXGuVn2ivtU3LA3mLCCIO5kUGoohTCoGmCBg/+8yPhWVX9WSl9telvVd8erftjFk9Fwb2dD6rw== +theredoc@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/theredoc/-/theredoc-1.0.0.tgz#bcace376af6feb1873efbdd0f91ed026570ff062" + integrity sha512-KU3SA3TjRRM932jpNfD3u4Ec3bSvedyo5ITPI7zgWYnKep7BwQQaxlhI9qbO+lKJoRnoAbEVfMcAHRuKVYikDA== + thread-stream@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.3.0.tgz#4fc07fb39eff32ae7bad803cb7dd9598349fed33"