Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add unit tests for hubauth #93

Merged
merged 10 commits into from
Jun 15, 2021
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