Skip to content

Commit

Permalink
chore: add unit tests for hubauth (#93)
Browse files Browse the repository at this point in the history
* chore: add unit tests for hutbauth

@W-9270862@

* chore: remove lint error

* Revert "fix: add missed export (#91)"

This reverts commit 86084c8.

* Revert "feat: add access token hub auth strategy (#90)"

This reverts commit 296df6e.

* Revert "feat: add access token hub auth strategy (#90)"

This reverts commit 296df6e.

* chore: mock where I can for unit tests

* chore: get rid of eslint errors

* chore: update some mocking

* chore: arrange tests in an order that works
  • Loading branch information
peternhale authored Jun 15, 2021
1 parent 2b31f96 commit 0a8e383
Show file tree
Hide file tree
Showing 6 changed files with 848 additions and 1,651 deletions.
20 changes: 10 additions & 10 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: "monthly"
interval: 'monthly'
labels:
- "dependencies"
- 'dependencies'
open-pull-requests-limit: 100
pull-request-branch-name:
separator: "-"
separator: '-'
ignore:
- dependency-name: "typescript"
- dependency-name: "sinon"
- dependency-name: "string-ansi"
- dependency-name: "*"
update-types: ["version-update:semver-major"]
- dependency-name: 'typescript'
- dependency-name: 'sinon'
- dependency-name: 'string-ansi'
- dependency-name: '*'
update-types: ['version-update:semver-major']
37 changes: 20 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,42 +48,45 @@
}
},
"dependencies": {
"@salesforce/core": "^2.20.3",
"@salesforce/kit": "^1.5.8",
"@salesforce/ts-types": "^1.5.13",
"@salesforce/core": "^2.24.0",
"@salesforce/kit": "^1.5.13",
"@salesforce/ts-types": "^1.5.17",
"archiver": "^5.2.0",
"debug": "^4.3.1",
"shelljs": "^0.8.4",
"sinon": "11.1.1",
"strip-ansi": "6.0.0"
},
"devDependencies": {
"@salesforce/dev-config": "^2.0.0",
"@salesforce/dev-config": "^2.1.2",
"@salesforce/dev-scripts": "^0.9.11",
"@salesforce/prettier-config": "^0.0.2",
"@salesforce/ts-sinon": "^1.3.5",
"@salesforce/ts-sinon": "^1.3.18",
"@types/archiver": "^5.1.0",
"@types/debug": "^4.1.5",
"@types/graceful-fs": "^4.1.5",
"@types/jsforce": "^1.9.29",
"@types/mkdirp": "^1.0.1",
"@types/shelljs": "^0.8.8",
"@types/sinon": "^10.0.1",
"@types/sinon": "^10.0.2",
"@typescript-eslint/eslint-plugin": "^4.26.0",
"@typescript-eslint/parser": "^4.26.0",
"chai": "^4.3.0",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^7.21.0",
"eslint-config-prettier": "^8.1.0",
"eslint-config-salesforce": "^0.1.0",
"eslint-config-salesforce-license": "^0.1.0",
"eslint-config-salesforce-typescript": "^0.2.0",
"eslint": "^7.28.0",
"eslint-config-prettier": "^8.3.0",
"eslint-config-salesforce": "^0.1.6",
"eslint-config-salesforce-license": "^0.1.6",
"eslint-config-salesforce-typescript": "^0.2.7",
"eslint-plugin-header": "^3.1.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-jsdoc": "^35.0.0",
"eslint-plugin-prettier": "^3.3.1",
"husky": "^4.2.5",
"mocha": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"husky": "^4.3.8",
"mocha": "^8.4.0",
"nyc": "^15.1.0",
"prettier": "^2.3.0",
"prettier": "^2.3.1",
"pretty-quick": "^3.1.0",
"sinon": "10.0.0",
"ts-node": "^9.1.1",
"typescript": "^4.1.3"
},
Expand Down
14 changes: 0 additions & 14 deletions test/unit/hubAuth.test.ts

This file was deleted.

9 changes: 9 additions & 0 deletions test/unit/sample.auth.data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"jwtKeyWithHeaderFooter": "-----BEGIN RSA PRIVATE KEY-----MIIJJwIBAAKCAgEAvDt02gSZwhwsyhhkcks8qjiTtB5qs188zMJ0S+rzSriJSQNXX0G2I+di39CNeiEgf1vrIowFh29FHUtQX6aCeBLW8+ONJJSxvgAa5LnaYjvJTiZbjRYzRil6YVF/didK+LfNU7E94u9We/wX3jzSIteswoxZqKQLhk+km+x40fpTwHwRWPc771JNucVDsqpKt+9Q2/W8SUNa33H+5ROgLG4y/uUNuvFyWYYqTfngdYZGXmALF1LVRITa9pyVZCXT1Hsi9w2ufTYNYTULmdz6D6JyBTnZH3/RQNxhc6bf9kEWVeo04ZkuxDpVxGoTA9GVYLGW/P/QOY8P3uY0s9r8x+UUASF+OX49hhUc78y/Vqo5ekJve/+HV56Ikzgt4PF1DfR6zLFZAA4TznB/6h/fnnFZczlKQgYN3r8ZHca2LA==-----END RSA PRIVATE KEY-----",
"jwtKeyWithOutHeaderFooter": "MIIJJwIBAAKCAgEAvDt02gSZwhwsyhhkcks8qjiTtB5qs188zMJ0S+rzSriJSQNXX0G2I+di39CNeiEgf1vrIowFh29FHUtQX6aCeBLW8+ONJJSxvgAa5LnaYjvJTiZbjRYzRil6YVF/didK+LfNU7E94u9We/wX3jzSIteswoxZqKQLhk+km+x40fpTwHwRWPc771JNucVDsqpKt+9Q2/W8SUNa33H+5ROgLG4y/uUNuvFyWYYqTfngdYZGXmALF1LVRITa9pyVZCXT1Hsi9w2ufTYNYTULmdz6D6JyBTnZH3/RQNxhc6bf9kEWVeo04ZkuxDpVxGoTA9GVYLGW/P/QOY8P3uY0s9r8x+UUASF+OX49hhUc78y/Vqo5ekJve/+HV56Ikzgt4PF1DfR6zLFZAA4TznB/6h/fnnFZczlKQgYN3r8ZHca2LA==",
"devHubUsername": "[email protected]",
"clientId": "PlatformCLI",
"sfdxAuthUrl": "force://PlatformCLI::5Aajsgdfjasgfkjashfjasgfkjashfjkashgfds.oweljflakdutp8qoiyhtoalksfnkadjhgewxoljqoiwefgkjtoeijhtb@somedevhub.my.salesforce.com",
"accessToken": "00D00000000xxxx!AQQAQEhasdfjhgashgaslkerhkasjhfjaksdhfladjgrjkasjfkasgfkalsjdfakgrkashfdjasdhbf.",
"instanceUrl": "https://somedevhub.my.salesforce.com"
}
196 changes: 196 additions & 0 deletions test/unit/zzhubAuth.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
/*
* Copyright (c) 2021, 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
*/

/*
* NOTE on chosen file name for these tests. When this test runs before testSession.test.ts
* a number of the testSession fail. Running these tests after testSession tests seems to work,
* so chose a file name that guarantees these will be run last.
*/
import * as os from 'os';
import * as path from 'path';
import { stubMethod } from '@salesforce/ts-sinon';
import * as chai from 'chai';
import { AuthFields, fs as fsCore } from '@salesforce/core';
import { Env, env } from '@salesforce/kit';
import * as sinon from 'sinon';
import * as shell from 'shelljs';
import { AuthStrategy, prepareForAuthUrl, prepareForJwt, transferExistingAuthToEnv } from '../../src/hubAuth';

const { expect } = chai;
const tmp = os.tmpdir();
type SampleData = {
jwtKeyWithHeaderFooter: string;
jwtKeyWithOutHeaderFooter: string;
devHubUsername: string;
clientId: string;
sfdxAuthUrl: string;
accessToken: string;
instanceUrl: string;
};

// eslint-disable-next-line @typescript-eslint/no-var-requires
const sampleAuthData = require(path.join(__dirname, 'sample.auth.data.json')) as SampleData;

const authFields: AuthFields = {
privateKey: '/some/private/key',
instanceUrl: sampleAuthData.instanceUrl,
username: sampleAuthData.devHubUsername,
clientId: sampleAuthData.clientId,
};

let getStringStub: sinon.SinonStub;

describe('hubAuth', () => {
const sandbox = sinon.createSandbox();
type EnvVar = { key: string; value: string };
let homeDir: string;
const stubEnvGet = (envVars: EnvVar[]): void => {
getStringStub = stubMethod(sandbox, Env.prototype, 'getString');
for (const envVar of envVars) {
getStringStub = getStringStub.withArgs(envVar.key).returns(envVar.value);
}
};
beforeEach(() => {
homeDir = `${path.join(tmp, path.sep)}${new Date().getTime()}`;
stubMethod(sandbox, fsCore, 'mkdirpSync');
stubMethod(sandbox, fsCore, 'writeJsonSync');
stubMethod(sandbox, process, 'cwd').returns(homeDir);
});
afterEach(() => {
sandbox.restore();
});
describe('Prepare For Jwt', () => {
it('should prepare test env for use with jwt auth that contains header/footer', () => {
stubEnvGet([
{ key: 'TESTKIT_JWT_KEY', value: sampleAuthData.jwtKeyWithHeaderFooter },
{ key: 'TESTKIT_JWT_CLIENT_ID', value: sampleAuthData.clientId },
{ key: 'TESTKIT_HUB_USERNAME', value: sampleAuthData.devHubUsername },
{ key: 'TESTKIT_HUB_INSTANCE', value: sampleAuthData.instanceUrl },
]);

const writeStub = stubMethod(sandbox, fsCore, 'writeFileSync').callsFake((): void => {
return;
});
stubMethod(sandbox, fsCore, 'existsSync').callsFake((): boolean => {
return true;
});
const readStub = stubMethod(sandbox, fsCore, 'readFileSync').callsFake((): string => {
return sampleAuthData.jwtKeyWithHeaderFooter;
});
const jwtKeyFile = prepareForJwt(homeDir);
// eslint-disable-next-line no-unused-expressions
expect(fsCore.existsSync(jwtKeyFile)).to.be.true;
fsCore.readFileSync(jwtKeyFile, 'utf8');
const jwtPassedToWrite = writeStub.args[0][1] as string;
expect(writeStub.args[0][0]).to.be.equal(jwtKeyFile);
expect((writeStub.args[0][1] as string).replace(/\n/g, '')).to.be.equal(sampleAuthData.jwtKeyWithHeaderFooter);
expect(readStub.args[0][0]).to.be.equal(jwtKeyFile);
expect(jwtPassedToWrite.split('\n').length).to.be.greaterThan(3);
expect(jwtPassedToWrite).to.include('-----BEGIN RSA PRIVATE KEY-----');
expect(jwtPassedToWrite).to.include('-----END RSA PRIVATE KEY-----');
});

it('should prepare test env for use with jwt auth that does not contain header/footer', () => {
stubEnvGet([
{ key: 'TESTKIT_JWT_KEY', value: sampleAuthData.jwtKeyWithOutHeaderFooter },
{ key: 'TESTKIT_JWT_CLIENT_ID', value: sampleAuthData.clientId },
{ key: 'TESTKIT_HUB_USERNAME', value: sampleAuthData.devHubUsername },
{ key: 'TESTKIT_HUB_INSTANCE', value: sampleAuthData.instanceUrl },
]);
const writeStub = stubMethod(sandbox, fsCore, 'writeFileSync').callsFake((): void => {
return;
});
stubMethod(sandbox, fsCore, 'existsSync').callsFake((): boolean => {
return true;
});
const readStub = stubMethod(sandbox, fsCore, 'readFileSync').callsFake((): string => {
return sampleAuthData.jwtKeyWithHeaderFooter;
});
const jwtKeyFile = prepareForJwt(homeDir);
// eslint-disable-next-line no-unused-expressions
expect(fsCore.existsSync(jwtKeyFile)).to.be.true;
fsCore.readFileSync(jwtKeyFile, 'utf8');
const jwtPassedToWrite = writeStub.args[0][1] as string;
expect(writeStub.args[0][0]).to.be.equal(jwtKeyFile);
expect((writeStub.args[0][1] as string).replace(/\n/g, '')).to.be.equal(sampleAuthData.jwtKeyWithHeaderFooter);
expect(readStub.args[0][0]).to.be.equal(jwtKeyFile);
expect(jwtPassedToWrite.split('\n').length).to.be.greaterThan(3);
expect(jwtPassedToWrite).to.include('-----BEGIN RSA PRIVATE KEY-----');
expect(jwtPassedToWrite).to.include('-----END RSA PRIVATE KEY-----');
});

it('should fail to prepare test env for use with jwt when required env var absent', () => {
try {
prepareForJwt(homeDir);
expect.fail('Should have thrown a Error');
} catch (e) {
expect(e).to.be.an.instanceOf(Error);
const error = e as Error;
expect(error.message).to.include('env var TESTKIT_JWT_KEY is undefined');
}
});
});
describe('Prepare For Auth Url', () => {
it('should prepare test env for use with sfdx auth url', () => {
stubEnvGet([{ key: 'TESTKIT_AUTH_URL', value: sampleAuthData.sfdxAuthUrl }]);
const writeStub = stubMethod(sandbox, fsCore, 'writeFileSync').callsFake((): void => {
return;
});
const readStub = stubMethod(sandbox, fsCore, 'readFileSync').callsFake((): string => {
return sampleAuthData.sfdxAuthUrl;
});
stubMethod(sandbox, fsCore, 'existsSync').callsFake((): boolean => {
return true;
});
const authUrlFile = prepareForAuthUrl(homeDir);

// eslint-disable-next-line no-unused-expressions
expect(fsCore.existsSync(authUrlFile)).to.be.true;
const authUrl: string = fsCore.readFileSync(authUrlFile, 'utf8');
expect(readStub.args[0][0]).to.be.equal(authUrlFile);
expect(writeStub.args[0][0]).to.be.equal(authUrlFile);
const authUrlPassedToWrite = writeStub.args[0][1] as string;
expect(authUrl).to.be.equal(authUrlPassedToWrite);
expect(authUrlPassedToWrite).to.be.equal(sampleAuthData.sfdxAuthUrl);
});
});

describe('Transfer Existing Auth To Env', () => {
let shellStub;
beforeEach(() => {
stubEnvGet([
{ key: 'HOME', value: homeDir },
{ key: 'TESTKIT_HUB_USERNAME', value: sampleAuthData.devHubUsername },
]);
stubMethod(sandbox, fsCore, 'readFileSync').returns(sampleAuthData.jwtKeyWithHeaderFooter);
});

it('should prepare test env for auth using existing username with no refresh token', () => {
stubMethod(sandbox, fsCore, 'readJsonSync').returns(authFields);
shellStub = stubMethod(sandbox, shell, 'exec').returns({});
transferExistingAuthToEnv(AuthStrategy.REUSE);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,no-unused-expressions
expect(shellStub.calledOnce).to.be.false;
sandbox.restore();
expect(env.getString('TESTKIT_JWT_KEY')).to.be.equal(sampleAuthData.jwtKeyWithHeaderFooter);
expect(env.getString('TESTKIT_JWT_CLIENT_ID')).to.be.equal(sampleAuthData.clientId);
expect(env.getString('TESTKIT_HUB_INSTANCE')).to.be.equal(sampleAuthData.instanceUrl);
});

it('should prepare test env for auth using existing username with refresh token', () => {
stubMethod(sandbox, fsCore, 'readJsonSync').returns({ refreshToken: 'some-refresh-token' });
shellStub = stubMethod(sandbox, shell, 'exec').returns(
JSON.stringify({ result: { sfdxAuthUrl: sampleAuthData.sfdxAuthUrl } })
);
transferExistingAuthToEnv(AuthStrategy.REUSE);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,no-unused-expressions
expect(shellStub.calledOnce).to.be.true;
sandbox.restore();
expect(env.getString('TESTKIT_AUTH_URL')).to.be.equal(sampleAuthData.sfdxAuthUrl);
});
});
});
Loading

0 comments on commit 0a8e383

Please sign in to comment.