Skip to content

Commit

Permalink
Merge pull request #57 from salesforcecli/mdonnalley/nuts
Browse files Browse the repository at this point in the history
test: add NUTs
  • Loading branch information
mshanemc committed Mar 3, 2021
2 parents 963ea6a + 44f7c39 commit 3f6f5a3
Show file tree
Hide file tree
Showing 15 changed files with 437 additions and 98 deletions.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@salesforce/dev-scripts": "^0.9.1",
"@salesforce/plugin-command-reference": "^1.3.0",
"@salesforce/prettier-config": "^0.0.2",
"@salesforce/plugin-config": "^1.2.5",
"@salesforce/ts-sinon": "^1.2.3",
"@types/mkdirp": "^1.0.1",
"@typescript-eslint/eslint-plugin": "^4.2.0",
Expand Down Expand Up @@ -73,9 +74,10 @@
"commands": "./lib/commands",
"bin": "sfdx",
"devPlugins": [
"@oclif/plugin-help",
"@oclif/plugin-command-snapshot",
"@salesforce/plugin-command-reference"
"@oclif/plugin-help",
"@salesforce/plugin-command-reference",
"@salesforce/plugin-config"
],
"topics": {
"auth": {
Expand Down
10 changes: 0 additions & 10 deletions src/commands/auth/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,6 @@ import { AuthInfo, Authorization, Messages } from '@salesforce/core';
Messages.importMessagesDirectory(__dirname);
const messages = Messages.loadMessages('@salesforce/plugin-auth', 'list');

export type AuthListInfo = {
alias: string;
username: string;
orgId: string;
instanceUrl: string;
accessToken?: string;
oauthMethod?: 'jwt' | 'web' | 'token' | 'unknown';
error?: string;
};

export default class List extends SfdxCommand {
public static readonly description = messages.getMessage('description');
public static aliases = ['force:auth:list'];
Expand Down
4 changes: 0 additions & 4 deletions test/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,5 @@ module.exports = {
'@typescript-eslint/no-empty-function': 'off',
// Easily return a promise in a mocked method.
'@typescript-eslint/require-await': 'off',

'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
},
};
3 changes: 2 additions & 1 deletion test/commands/auth/device/login.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { DeviceOauthService } from '@salesforce/core';
import { DeviceCodeResponse } from '@salesforce/core/lib/deviceOauthService';
import { UX } from '@salesforce/command';
import { SinonStub } from 'sinon';
import { parseJson } from '../../../testHelper';

interface Options {
approvalTimesout?: boolean;
Expand Down Expand Up @@ -233,7 +234,7 @@ describe('auth:device:login', async () => {
.stdout()
.command(['auth:device:login', '--json'])
.it('should exit early when prompt is answered NO', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJson<AuthFields>(ctx.stdout);
expect(uxStub.callCount).to.equal(1);
expect(response.status).to.equal(0);
expect(response.result).to.deep.equal({});
Expand Down
59 changes: 59 additions & 0 deletions test/commands/auth/jwt/grant.nut.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2020, 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 * as path from 'path';
import { execCmd, TestSession, prepareForJwt } from '@salesforce/cli-plugins-testkit';
import { expect } from 'chai';
import { Env } from '@salesforce/kit';
import { ensureString, getString } from '@salesforce/ts-types';
import { AuthFields } from '@salesforce/core';
import { expectUrlToExist, expectOrgIdToExist, expectAccessTokenToExist } from '../../../testHelper';

let testSession: TestSession;

describe('auth:jwt:grant NUTs', () => {
const env = new Env();
let jwtKey: string;
let username: string;
let instanceUrl: string;
let clientId: string;

before('prepare session and ensure environment variables', () => {
username = ensureString(env.getString('TESTKIT_HUB_USERNAME'));
instanceUrl = ensureString(env.getString('TESTKIT_HUB_INSTANCE'));
clientId = ensureString(env.getString('TESTKIT_JWT_CLIENT_ID'));
ensureString(env.getString('TESTKIT_JWT_KEY'));

testSession = TestSession.create({ authStrategy: 'NONE' });
jwtKey = prepareForJwt(testSession.homeDir);
});

after(async () => {
await testSession?.clean();
});

afterEach(() => {
execCmd(`auth:logout -p -u ${username}`, { ensureExitCode: 0 });
});

it('should authorize an org using jwt (json)', () => {
const command = `auth:jwt:grant -d -u ${username} -i ${clientId} -f ${jwtKey} -r ${instanceUrl} --json`;
const json = execCmd<AuthFields>(command, { ensureExitCode: 0 }).jsonOutput;
expectAccessTokenToExist(json.result);
expectOrgIdToExist(json.result);
expectUrlToExist(json.result, 'instanceUrl');
expectUrlToExist(json.result, 'loginUrl');
expect(json.result.privateKey).to.equal(path.join(testSession.homeDir, 'jwtKey'));
expect(json.result.username).to.equal(username);
});

it('should authorize an org using jwt (human readable)', () => {
const command = `auth:jwt:grant -d -u ${username} -i ${clientId} -f ${jwtKey} -r ${instanceUrl}`;
const result = execCmd(command, { ensureExitCode: 0 });
const output = getString(result, 'shellOutput.stdout');
expect(output).to.include(`Successfully authorized ${username} with org ID`);
});
});
31 changes: 16 additions & 15 deletions test/commands/auth/jwt/grant.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { AuthFields, AuthInfo, SfdxError } from '@salesforce/core';
import { MockTestOrgData } from '@salesforce/core/lib/testSetup';
import { StubbedType, stubInterface, stubMethod } from '@salesforce/ts-sinon';
import { UX } from '@salesforce/command';
import { parseJson, parseJsonError } from '../../../testHelper';

interface Options {
authInfoCreateFails?: boolean;
Expand Down Expand Up @@ -49,7 +50,7 @@ describe('auth:jwt:grant', async () => {
.stdout()
.command(['auth:jwt:grant', '-u', testData.username, '-f', 'path/to/key.json', '-i', '123456', '--json'])
.it('should return auth fields', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJson<AuthFields>(ctx.stdout);
expect(response.status).to.equal(0);
expect(response.result).to.deep.equal(authFields);
});
Expand All @@ -70,7 +71,7 @@ describe('auth:jwt:grant', async () => {
'--json',
])
.it('should set alias when -a is provided', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJson<AuthFields>(ctx.stdout);
expect(response.status).to.equal(0);
expect(response.result).to.deep.equal(authFields);
expect(authInfoStub.setAlias.callCount).to.equal(1);
Expand All @@ -93,7 +94,7 @@ describe('auth:jwt:grant', async () => {
'--json',
])
.it('should set defaultusername to alias when -s and -a are provided', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJson<AuthFields>(ctx.stdout);
expect(response.status).to.equal(0);
expect(response.result).to.deep.equal(authFields);
expect(authInfoStub.setAlias.args[0]).to.deep.equal(['MyAlias']);
Expand All @@ -111,7 +112,7 @@ describe('auth:jwt:grant', async () => {
.stdout()
.command(['auth:jwt:grant', '-u', testData.username, '-f', 'path/to/key.json', '-i', '123456', '-s', '--json'])
.it('should set defaultusername to username when -s is provided', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJson<AuthFields>(ctx.stdout);
expect(response.status).to.equal(0);
expect(response.result).to.deep.equal(authFields);
expect(authInfoStub.setAlias.callCount).to.equal(0);
Expand Down Expand Up @@ -141,7 +142,7 @@ describe('auth:jwt:grant', async () => {
'--json',
])
.it('should set defaultdevhubusername to alias when -d and -a are provided', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJson<AuthFields>(ctx.stdout);
expect(response.status).to.equal(0);
expect(response.result).to.deep.equal(authFields);
expect(authInfoStub.setAlias.args[0]).to.deep.equal(['MyAlias']);
Expand All @@ -159,7 +160,7 @@ describe('auth:jwt:grant', async () => {
.stdout()
.command(['auth:jwt:grant', '-u', testData.username, '-f', 'path/to/key.json', '-i', '123456', '-d', '--json'])
.it('should set defaultdevhubusername to username when -d is provided', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJson<AuthFields>(ctx.stdout);
expect(response.status).to.equal(0);
expect(response.result).to.deep.equal(authFields);
expect(authInfoStub.setAlias.callCount).to.equal(0);
Expand Down Expand Up @@ -188,7 +189,7 @@ describe('auth:jwt:grant', async () => {
'--json',
])
.it('should set defaultusername and defaultdevhubusername to username when -d and -s are provided', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJson<AuthFields>(ctx.stdout);
expect(response.status).to.equal(0);
expect(response.result).to.deep.equal(authFields);
expect(authInfoStub.setAlias.callCount).to.equal(0);
Expand Down Expand Up @@ -219,7 +220,7 @@ describe('auth:jwt:grant', async () => {
'--json',
])
.it('should set defaultusername and defaultdevhubusername to alias when -a, -d, and -s are provided', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJson<AuthFields>(ctx.stdout);
expect(response.status).to.equal(0);
expect(response.result).to.deep.equal(authFields);
expect(authInfoStub.setAlias.args[0]).to.deep.equal(['MyAlias']);
Expand All @@ -237,7 +238,7 @@ describe('auth:jwt:grant', async () => {
.stdout()
.command(['auth:jwt:grant', '-u', testData.username, '-f', 'path/to/key.json', '--json'])
.it('should throw an error when client id (-i) is not provided', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJsonError(ctx.stdout);
expect(response.status).to.equal(1);
expect(response.message).to.include('Missing required flag');
});
Expand All @@ -247,7 +248,7 @@ describe('auth:jwt:grant', async () => {
.stdout()
.command(['auth:jwt:grant', '-u', testData.username, '-f', 'path/to/key.json', '-i', '123456INVALID', '--json'])
.it('should throw an error when client id is invalid', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJsonError(ctx.stdout);
expect(response.status).to.equal(1);
expect(response.message).to.include('We encountered a JSON web token error');
});
Expand All @@ -257,7 +258,7 @@ describe('auth:jwt:grant', async () => {
.stdout()
.command(['auth:jwt:grant', '-u', testData.username, '-i', '123456', '--json'])
.it('should throw an error when private key file (-f) is not provided', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJsonError(ctx.stdout);
expect(response.status).to.equal(1);
expect(response.message).to.include('Missing required flag');
});
Expand All @@ -267,7 +268,7 @@ describe('auth:jwt:grant', async () => {
.stdout()
.command(['auth:jwt:grant', '-u', testData.username, '-f', 'path/to/key.json', '-i', '123456', '--json'])
.it('should not throw an error when the authorization already exists', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJson<AuthFields>(ctx.stdout);
expect(response.status).to.equal(0);
expect(response.result).to.deep.equal(authFields);
});
Expand All @@ -284,7 +285,7 @@ describe('auth:jwt:grant', async () => {
.stdout()
.command(['auth:jwt:grant', '-u', testData.username, '-f', 'path/to/key.json', '-i', '123456', '--json'])
.it('should auth when in demo mode (SFDX_ENV=demo) and prompt is answered with yes', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJson<AuthFields>(ctx.stdout);
expect(response.status).to.equal(0);
expect(response.result).to.deep.equal(authFields);
expect(authInfoStub.save.callCount).to.equal(1);
Expand All @@ -302,7 +303,7 @@ describe('auth:jwt:grant', async () => {
.stdout()
.command(['auth:jwt:grant', '-u', testData.username, '-f', 'path/to/key.json', '-i', '123456', '--json'])
.it('should do nothing when in demo mode (SFDX_ENV=demo) and prompt is answered with no', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJson<AuthFields>(ctx.stdout);
expect(response.status).to.equal(0);
expect(response.result).to.deep.equal({});
expect(authInfoStub.save.callCount).to.equal(0);
Expand All @@ -319,7 +320,7 @@ describe('auth:jwt:grant', async () => {
.stdout()
.command(['auth:jwt:grant', '-u', testData.username, '-f', 'path/to/key.json', '-i', '123456', '--json', '-p'])
.it('should ignore prompt when in demo mode (SFDX_ENV=demo) and -p is provided', (ctx) => {
const response = JSON.parse(ctx.stdout);
const response = parseJson<AuthFields>(ctx.stdout);
expect(response.status).to.equal(0);
expect(response.result).to.deep.equal(authFields);
expect(authInfoStub.save.callCount).to.equal(1);
Expand Down
46 changes: 46 additions & 0 deletions test/commands/auth/list.nut.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2020, 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 { execCmd, TestSession } from '@salesforce/cli-plugins-testkit';
import { expect } from 'chai';
import { Env } from '@salesforce/kit';
import { ensureString, getString } from '@salesforce/ts-types';
import { Authorization } from '@salesforce/core';
import { expectUrlToExist, expectOrgIdToExist, expectAccessTokenToExist } from '../../testHelper';

describe('auth:list NUTs', () => {
let testSession: TestSession;
let username: string;

before('prepare session and ensure environment variables', () => {
const env = new Env();
ensureString(env.getString('TESTKIT_JWT_KEY'));
ensureString(env.getString('TESTKIT_JWT_CLIENT_ID'));
ensureString(env.getString('TESTKIT_HUB_INSTANCE'));
username = ensureString(env.getString('TESTKIT_HUB_USERNAME'));
testSession = TestSession.create({});
});

after(async () => {
await testSession?.clean();
});

it('should list auth files (json)', () => {
const json = execCmd<Authorization[]>('auth:list --json', { ensureExitCode: 0 }).jsonOutput;
const auth = json.result[0];
expectAccessTokenToExist(auth);
expectOrgIdToExist(auth);
expectUrlToExist(auth, 'instanceUrl');
expect(auth.username).to.equal(username);
});

it('should list auth files (human readable)', () => {
const result = execCmd('auth:list', { ensureExitCode: 0 });
const output = getString(result, 'shellOutput.stdout');
expect(output).to.include(username);
expect(output).to.include('jwt');
});
});
7 changes: 4 additions & 3 deletions test/commands/auth/list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
*/

import { $$, expect, test } from '@salesforce/command/lib/test';
import { Aliases, AuthInfo, AuthInfoConfig } from '@salesforce/core';
import { Aliases, AuthInfo, AuthInfoConfig, Authorization } from '@salesforce/core';
import { MockTestOrgData } from '@salesforce/core/lib/testSetup';
import { StubbedType, stubInterface, stubMethod } from '@salesforce/ts-sinon';
import { parseJson } from '../../testHelper';

describe('auth:list', async () => {
const testData = new MockTestOrgData();
Expand Down Expand Up @@ -47,7 +48,7 @@ describe('auth:list', async () => {
.stdout()
.command(['auth:list', '--json'])
.it('should show auth files', (ctx) => {
const auths = JSON.parse(ctx.stdout).result;
const auths = parseJson<Authorization[]>(ctx.stdout).result;
expect(auths[0].alias).to.equal('TestAlias');
expect(auths[0].username).to.equal(testData.username);
expect(auths[0].instanceUrl).to.equal(testData.instanceUrl);
Expand All @@ -60,7 +61,7 @@ describe('auth:list', async () => {
.stdout()
.command(['auth:list', '--json'])
.it('should show files with auth errors', (ctx) => {
const auths = JSON.parse(ctx.stdout).result;
const auths = parseJson<Authorization[]>(ctx.stdout).result;
expect(auths[0].alias).to.equal('TestAlias');
expect(auths[0].username).to.equal(testData.username);
expect(auths[0].instanceUrl).to.equal(testData.instanceUrl);
Expand Down
Loading

0 comments on commit 3f6f5a3

Please sign in to comment.