Skip to content

Commit

Permalink
fix: more casing issues
Browse files Browse the repository at this point in the history
  • Loading branch information
mshanemc committed Feb 8, 2021
1 parent 703a266 commit 8b3a6f9
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 87 deletions.
70 changes: 33 additions & 37 deletions src/commands/force/user/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
UserFields,
} from '@salesforce/core';
import { QueryResult } from 'jsforce';
import { omit } from '@salesforce/kit';
import { getString, Dictionary, isArray } from '@salesforce/ts-types';
import { flags, FlagsConfig, SfdxCommand } from '@salesforce/command';

Expand All @@ -43,6 +44,26 @@ const permsetsStringToArray = (fieldsPermsets: string | string[]): string[] => {
: fieldsPermsets.split(',').map((item) => item.replace("'", '').trim());
};

const lowercaseAllKeys = (input: Record<string, unknown>): Record<string, unknown> => {
return Object.keys(input).reduce(function (accum, key) {
accum[key.toLowerCase()] = input[key];
return accum;
}, {});
};

const standardizePasswordToBoolean = (input: unknown): boolean => {
if (typeof input === 'boolean') {
return input;
}
if (input === 'true' || input === 1) {
return true;
}
if (input === 'false' || input === 0) {
return false;
}
return true;
};

export class UserCreateCommand extends SfdxCommand {
public static readonly description = messages.getMessage('description');
public static readonly examples = messages.getMessage('examples').split(os.EOL);
Expand Down Expand Up @@ -74,13 +95,7 @@ export class UserCreateCommand extends SfdxCommand {
* @private
*/
private static stripInvalidAPIFields(fields: UserFields & Dictionary<string>): UserFields {
const copy = Object.assign({}, fields);
// remove invalid fields for userCreate()
delete copy.permsets;
delete copy.generatepassword;
delete copy.generatePassword;
delete copy.profileName;
return copy as UserFields;
return omit(fields, ['permsets', 'generatepassword', 'generatePassword', 'profileName']);
}

public async run(): Promise<UserCreateOutput> {
Expand Down Expand Up @@ -156,7 +171,7 @@ export class UserCreateCommand extends SfdxCommand {
return {
orgId: this.org.getOrgId(),
permissionSetAssignments: permsetsStringToArray(permsets),
fields: { ...fieldsWithoutPermsets },
fields: { ...lowercaseAllKeys(fieldsWithoutPermsets) },
};
}

Expand Down Expand Up @@ -194,48 +209,29 @@ export class UserCreateCommand extends SfdxCommand {

if (this.varargs) {
Object.keys(this.varargs).forEach((key) => {
defaultFields[this.lowerFirstLetter(key)] = this.varargs[key];

if (key.toLowerCase() === 'generatepassword') {
defaultFields['generatePassword'] = this.varargs[key];
// standardize generatePassword casing
defaultFields['generatePassword'] = standardizePasswordToBoolean(this.varargs[key]);
} else if (key.toLowerCase() === 'profilename') {
// standardize profileName casing
defaultFields['profileName'] = this.varargs[key];
} else {
// all other varargs are left "as is"
defaultFields[this.lowerFirstLetter(key)] = this.varargs[key];
}
});
}

// check if "profileName" was passed, this needs to become a profileId before calling User.create
if (defaultFields['profileName']) {
const name = (defaultFields['profileName'] || 'Standard User') as string;
const name = (defaultFields['profileName'] ?? 'Standard User') as string;
this.logger.debug(`Querying org for profile name [${name}]`);
const response: QueryResult<{ Id: string }> = await this.org
.getConnection()
.query(`SELECT id FROM profile WHERE name='${name}'`);
defaultFields.profileId = response.records[0].Id;
}

// the file schema is camelCase and boolean while the cli arg is no capitalization and a string
// we will add logic to capture camelcase in varargs just in case
if (
defaultFields['generatepassword'] === 'true' ||
defaultFields['generatePassword'] === 'true' ||
defaultFields['generatePassword'] === true
) {
// since only one may be set, set both variations, prefer camelCase and boolean for coding
// this will also maintain --json backwards compatibility for the all lower case scenario
defaultFields['generatepassword'] = 'true';
defaultFields['generatePassword'] = true;
}
// for the false case
if (
defaultFields['generatepassword'] === 'false' ||
defaultFields['generatePassword'] === 'false' ||
defaultFields['generatePassword'] === false
) {
// since only one may be set, set both variations, prefer camelCase and boolean for coding
// this will also maintain --json backwards compatibility for the all lower case scenario
defaultFields['generatepassword'] = 'false';
defaultFields['generatePassword'] = false;
}

return defaultFields;
}

Expand Down Expand Up @@ -272,5 +268,5 @@ export default UserCreateCommand;
interface UserCreateOutput {
orgId: string;
permissionSetAssignments: string[];
fields: UserFields;
fields: Record<string, unknown>;
}
97 changes: 47 additions & 50 deletions test/commands/user/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */

import { $$, expect, test } from '@salesforce/command/lib/test';
import { Aliases, AuthInfo, Connection, DefaultUserFields, fs, Logger, Org, User } from '@salesforce/core';
import { Aliases, AuthInfo, Connection, DefaultUserFields, fs, Logger, Org, User, UserFields } from '@salesforce/core';
import { stubMethod } from '@salesforce/ts-sinon';
import { IConfig } from '@oclif/config';
import UserCreateCommand from '../../../src/commands/force/user/create';
Expand Down Expand Up @@ -66,7 +66,7 @@ describe('force:user:create', () => {
async function prepareStubs(throws: { license?: boolean; duplicate?: boolean } = {}, readsFile?) {
stubMethod($$.SANDBOX, Org.prototype, 'getConnection').callsFake(() => Connection.prototype);
stubMethod($$.SANDBOX, DefaultUserFields, 'create').resolves({
getFields: () => {
getFields: (): UserFields => {
return {
id: '0052D0000043PawWWR',
username: '[email protected]',
Expand Down Expand Up @@ -109,7 +109,7 @@ describe('force:user:create', () => {
test
.do(async () => {
stubMethod($$.SANDBOX, User.prototype, 'assignPassword').resolves();
await prepareStubs({}, { profileName: 'profileFromFile', permsets: ['perm1', 'perm2'] });
await prepareStubs({}, { profilename: 'profileFromFile', permsets: ['perm1', 'perm2'] });
})
.stdout()
.command([
Expand All @@ -121,25 +121,24 @@ describe('force:user:create', () => {
'[email protected]',
"permsets='permCLI, permCLI2'",
'generatepassword=true',
'profileName=profileFromArgs',
'profilename=profileFromArgs',
])
.it('will handle a merge multiple permsets and profileNames from args and file (permsets from args)', (ctx) => {
.it('will handle a merge multiple permsets and profilenames from args and file (permsets from args)', (ctx) => {
const expected = {
orgId: 'abc123',
permissionSetAssignments: ['permCLI', 'permCLI2'],
fields: {
alias: 'testAlias',
email: '[email protected]',
emailEncodingKey: 'UTF-8',
emailencodingkey: 'UTF-8',
id: '0052D0000043PawWWR',
languageLocaleKey: 'en_US',
lastName: 'User',
localeSidKey: 'en_US',
generatepassword: 'true',
generatePassword: true,
profileId: '12345678',
profileName: 'profileFromArgs',
timeZoneSidKey: 'America/Los_Angeles',
languagelocalekey: 'en_US',
lastname: 'User',
localesidkey: 'en_US',
generatepassword: true,
profileid: '12345678',
profilename: 'profileFromArgs',
timezonesidkey: 'America/Los_Angeles',
username: '[email protected]',
},
};
Expand All @@ -162,24 +161,24 @@ describe('force:user:create', () => {
'[email protected]',
'--definitionfile',
'tempfile.json',
'profileName=profileFromArgs',
'profilename=profileFromArgs',
'[email protected]',
])
.it('will handle a merge multiple permsets and profileNames from args and file (permsets from file)', (ctx) => {
.it('will handle a merge multiple permsets and profilenames from args and file (permsets from file)', (ctx) => {
const expected = {
orgId: 'abc123',
permissionSetAssignments: ['perm1', 'perm2'],
fields: {
alias: 'testAlias',
email: '[email protected]',
emailEncodingKey: 'UTF-8',
emailencodingkey: 'UTF-8',
id: '0052D0000043PawWWR',
languageLocaleKey: 'en_US',
lastName: 'User',
localeSidKey: 'en_US',
profileId: '12345678',
profileName: 'profileFromArgs',
timeZoneSidKey: 'America/Los_Angeles',
languagelocalekey: 'en_US',
lastname: 'User',
localesidkey: 'en_US',
profileid: '12345678',
profilename: 'profileFromArgs',
timezonesidkey: 'America/Los_Angeles',
username: '[email protected]',
},
};
Expand Down Expand Up @@ -208,13 +207,13 @@ describe('force:user:create', () => {
fields: {
alias: 'testAlias',
email: username,
emailEncodingKey: 'UTF-8',
emailencodingkey: 'UTF-8',
id: '0052D0000043PawWWR',
languageLocaleKey: 'en_US',
lastName: 'User',
localeSidKey: 'en_US',
profileId: '00e2D000000bNexWWR',
timeZoneSidKey: 'America/Los_Angeles',
languagelocalekey: 'en_US',
lastname: 'User',
localesidkey: 'en_US',
profileid: '00e2D000000bNexWWR',
timezonesidkey: 'America/Los_Angeles',
username: '[email protected]',
},
};
Expand Down Expand Up @@ -248,15 +247,14 @@ describe('force:user:create', () => {
fields: {
alias: 'testAlias',
email: '[email protected]',
emailEncodingKey: 'UTF-8',
emailencodingkey: 'UTF-8',
id: '0052D0000043PawWWR',
languageLocaleKey: 'en_US',
lastName: 'User',
localeSidKey: 'en_US',
profileId: '00e2D000000bNexWWR',
generatePassword: false,
generatepassword: 'false',
timeZoneSidKey: 'America/Los_Angeles',
languagelocalekey: 'en_US',
lastname: 'User',
localesidkey: 'en_US',
profileid: '00e2D000000bNexWWR',
generatepassword: false,
timezonesidkey: 'America/Los_Angeles',
username: '[email protected]',
},
};
Expand All @@ -267,7 +265,7 @@ describe('force:user:create', () => {

test
.do(async () => {
await prepareStubs({}, { generatepassword: true, profileName: 'System Administrator' });
await prepareStubs({}, { generatepassword: true, profilename: 'System Administrator' });
})
.stdout()
.command([
Expand All @@ -281,10 +279,10 @@ describe('force:user:create', () => {
'[email protected]',
'[email protected]',
'generatepassword=false',
"profileName='Chatter Free User'",
"profilename='Chatter Free User'",
])
// we set generatepassword=false in the varargs, in the definitionfile we have generatepassword=true, so we SHOULD NOT generate a password
// we should override the profileName with 'Chatter Free User'
// we should override the profilename with 'Chatter Free User'
.it(
'will merge fields from the cli args, and the definitionfile correctly, preferring cli args, cli args > file > default',
(ctx) => {
Expand All @@ -294,17 +292,16 @@ describe('force:user:create', () => {
fields: {
alias: 'testAlias',
email: '[email protected]',
emailEncodingKey: 'UTF-8',
emailencodingkey: 'UTF-8',
id: '0052D0000043PawWWR',
languageLocaleKey: 'en_US',
lastName: 'User',
localeSidKey: 'en_US',
generatePassword: false,
generatepassword: 'false',
profileName: "'Chatter Free User'",
// note the new profileId 12345678 -> Chatter Free User from var args
profileId: '12345678',
timeZoneSidKey: 'America/Los_Angeles',
languagelocalekey: 'en_US',
lastname: 'User',
localesidkey: 'en_US',
generatepassword: false,
profilename: "'Chatter Free User'",
// note the new profileid 12345678 -> Chatter Free User from var args
profileid: '12345678',
timezonesidkey: 'America/Los_Angeles',
username: '[email protected]',
},
};
Expand Down

0 comments on commit 8b3a6f9

Please sign in to comment.