Skip to content

Commit

Permalink
feat: update app:create to take an --appdescription flags (#249)
Browse files Browse the repository at this point in the history
feat: update autoinstall:app:create to take --appname and --appdescription flags
  • Loading branch information
aarondailsf2023 authored Mar 24, 2023
1 parent 821380e commit d6746cd
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 15 deletions.
21 changes: 12 additions & 9 deletions command-snapshot.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"flags": [
"allevents",
"apiversion",
"appdescription",
"appname",
"async",
"definitionfile",
Expand Down Expand Up @@ -81,6 +82,8 @@
"plugin": "@salesforce/analytics",
"flags": [
"apiversion",
"appdescription",
"appname",
"async",
"json",
"loglevel",
Expand Down Expand Up @@ -238,7 +241,7 @@
{
"command": "analytics:template:create",
"plugin": "@salesforce/analytics",
"flags": ["apiversion", "description", "folderid", "json", "label", "loglevel", "targetusername", "recipeids"]
"flags": ["apiversion", "description", "folderid", "json", "label", "loglevel", "recipeids", "targetusername"]
},
{
"command": "analytics:template:delete",
Expand All @@ -250,6 +253,11 @@
"plugin": "@salesforce/analytics",
"flags": ["apiversion", "json", "loglevel", "targetusername", "templateid", "templatename"]
},
{
"command": "analytics:template:lint",
"plugin": "@salesforce/analytics",
"flags": ["apiversion", "json", "loglevel", "targetusername", "templateid", "templatename"]
},
{
"command": "analytics:template:list",
"plugin": "@salesforce/analytics",
Expand All @@ -271,20 +279,15 @@
"folderid",
"json",
"loglevel",
"recipeids",
"targetusername",
"templateid",
"templatename",
"recipeids"
"templatename"
]
},
{
"command": "analytics:template:lint",
"plugin": "@salesforce/analytics",
"flags": ["loglevel", "targetusername", "apiversion", "json", "templateid", "templatename"]
},
{
"command": "analytics:template:validate",
"plugin": "@salesforce/analytics",
"flags": ["loglevel", "targetusername", "apiversion", "json", "templateid", "templatename", "valuesfile"]
"flags": ["apiversion", "json", "loglevel", "targetusername", "templateid", "templatename", "valuesfile"]
}
]
2 changes: 2 additions & 0 deletions messages/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
"templatenameFlagLongDescription": "The name of the Analytics template.",
"appnameFlagDescription": "app name",
"appnameFlagLongDescription": "The name of the created app.",
"appdescriptionFlagDescription": "app description",
"appdescriptionFlagLongDescription": "The description of the created app.",
"applogFlagDescription": "specify to include app creation log details",
"applogFlagLongDescription": "Specify to include app creation log details.",
"appCreateAsyncDescription": "create app asynchronously",
Expand Down
4 changes: 4 additions & 0 deletions messages/autoinstall.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
"autoinstallidFlagLongDescription": "ID of the auto-install request.",
"applogFlagDescription": "specify to include app creation log details",
"applogFlagLongDescription": "Specify to include app creation log details.",
"appnameFlagDescription": "app name",
"appnameFlagLongDescription": "The name of the created app.",
"appdescriptionFlagDescription": "app description",
"appdescriptionFlagLongDescription": "The description of the created app.",
"displayLogHeader": "App Log",
"displayNoLogAvailable": "No app log available.",
"displayDateFormat": "YYYY-MM-DD HH:mm:ss",
Expand Down
7 changes: 6 additions & 1 deletion src/commands/analytics/app/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ export default class Create extends SfdxCommand {
description: messages.getMessage('appnameFlagDescription'),
longDescription: messages.getMessage('appnameFlagLongDescription')
}),
appdescription: flags.string({
description: messages.getMessage('appdescriptionFlagDescription'),
longDescription: messages.getMessage('appdescriptionFlagLongDescription')
}),
async: flags.boolean({
char: 'a',
description: messages.getMessage('appCreateAsyncDescription'),
Expand Down Expand Up @@ -108,7 +112,7 @@ export default class Create extends SfdxCommand {
throw new SfdxError(`Template '${this.flags.templateid || this.flags.templatename}' not found.`);
}
return {
description: matchedTemplate.description,
description: (this.flags.appdescription || matchedTemplate.description) as string,
label: (this.flags.appname || matchedTemplate.label) as string,
templateSourceId: matchedTemplate.id,
assetIcon: '16.png',
Expand Down Expand Up @@ -138,6 +142,7 @@ export default class Create extends SfdxCommand {
body.name = (body.name || this.flags.appname) as string;
body.label = (body.label || this.flags.appname) as string;
}
body.description = (body.description ?? this.flags.appdescription) as string;
return body;
} else {
throw new SfdxError(
Expand Down
21 changes: 19 additions & 2 deletions src/commands/analytics/autoinstall/app/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { flags, SfdxCommand } from '@salesforce/command';
import { Messages, Org, SfdxError } from '@salesforce/core';

import AutoInstall from '../../../../lib/analytics/autoinstall/autoinstall';
import AutoInstall, { AutoInstallCreateAppConfigurationBody } from '../../../../lib/analytics/autoinstall/autoinstall';
import {
DEF_APP_CREATE_UPDATE_TIMEOUT,
DEF_POLLING_INTERVAL,
Expand Down Expand Up @@ -40,6 +40,14 @@ export default class Create extends SfdxCommand {
longDescription: messages.getMessage('templatenameFlagLongDescription'),
exclusive: ['templateid']
}),
appname: flags.string({
description: messages.getMessage('appnameFlagDescription'),
longDescription: messages.getMessage('appnameFlagLongDescription')
}),
appdescription: flags.string({
description: messages.getMessage('appdescriptionFlagDescription'),
longDescription: messages.getMessage('appdescriptionFlagLongDescription')
}),
noenqueue: flags.boolean({
description: messages.getMessage('noenqueueFlagDescription'),
longDescription: messages.getMessage('noenqueueFlagLongDescription'),
Expand Down Expand Up @@ -75,8 +83,17 @@ export default class Create extends SfdxCommand {
if (!templateInput) {
throw new SfdxError(messages.getMessage('missingRequiredField'));
}

const autoinstall = new AutoInstall(this.org as Org);
const autoInstallId = await autoinstall.create(templateInput, !this.flags.noenqueue);

const appConfiguration: AutoInstallCreateAppConfigurationBody = {
appName: this.flags.appname as string,
appLabel: this.flags.appname as string,
appDescription: this.flags.appdescription as string
};

const autoInstallId = await autoinstall.create(templateInput, appConfiguration, !this.flags.noenqueue);

// they did't enqueue or said they don't want to wait, so just return now
if (this.flags.noenqueue || this.flags.async || this.flags.wait <= 0) {
this.ux.log(messages.getMessage('appCreateRequestSuccess', [autoInstallId]));
Expand Down
17 changes: 15 additions & 2 deletions src/lib/analytics/autoinstall/autoinstall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ export type AutoInstallRequestType = Record<string, unknown> & {
};
};

export type AutoInstallCreateAppConfigurationBody = {
appName?: string;
appLabel?: string;
appDescription?: string;
};

function isFinishedRequest(r: AutoInstallRequestType): boolean {
const status = r.requestStatus?.toLocaleLowerCase();
return status === 'cancelled' || status === 'success' || status === 'failed';
Expand Down Expand Up @@ -126,11 +132,18 @@ export default class AutoInstall {
return fetchAllPages<AutoInstallRequestType>(this.connection, this.autoInstallUrl + '?pageSize=200', 'requests');
}

public create(templateApiName: string, enqueue = true): Promise<string | undefined> {
public create(
templateApiName: string,
appConfiguration: AutoInstallCreateAppConfigurationBody,
enqueue = true
): Promise<string | undefined> {
const body = JSON.stringify({
templateApiName,
requestStatus: enqueue ? enqueuedStatus : newStatus,
requestType: createType
requestType: createType,
configuration: {
appConfiguration
}
});
return this.performPost(body);
}
Expand Down
43 changes: 43 additions & 0 deletions test/commands/app/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,49 @@ describe('analytics:app:create', () => {
});
});

test
.withOrg({ username: '[email protected]' }, true)
.withConnectionRequest(request => {
request = ensureJsonMap(request);
if (request.method === 'GET') {
// call for all templates
return Promise.resolve({
templates: [testTemplateJson, sustainabilityTemplateJson]
});
}
if (request.method === 'POST') {
saveOffRequestBody(request.body as string);
return Promise.resolve({ id: appId });
}
return Promise.reject();
})
.stdout()
.command([
'analytics:app:create',
'--templatename',
'Sustainability',
'--appname',
'customname',
'--appdescription',
'customdesc',
'--async'
])
.it(
'runs analytics:app:create --templatename Sustainability --appname customname --appdescription customdesc --async',
ctx => {
expect(ctx.stdout).to.contain(messages.getMessage('createAppSuccessAsync', [appId]));
expect(requestBody, 'requestBody').to.not.be.undefined;
expect(requestBody, 'requestBody').to.include({
// request body should have values from the templates GET
templateSourceId: sustainabilityTemplateJson.id,
// but name and label should come from the cli arg
label: 'customname',
name: 'customname',
description: 'customdesc'
});
}
);

test
.withOrg({ username: '[email protected]' }, true)
.withConnectionRequest(request => {
Expand Down
41 changes: 40 additions & 1 deletion test/commands/autoinstall/app/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { UX } from '@salesforce/command';
import * as core from '@salesforce/core';
import { expect, test } from '@salesforce/command/lib/test';
import { SfdxError } from '@salesforce/core';
import { JsonMap } from '@salesforce/ts-types';
import { AnyJson, ensureJsonMap, ensureString, JsonMap } from '@salesforce/ts-types';
import { AutoInstallRequestType, AutoInstallStatus } from '../../../../src/lib/analytics/autoinstall/autoinstall';

core.Messages.importMessagesDirectory(__dirname);
Expand All @@ -32,10 +32,21 @@ function stubTimeout(callback?: () => unknown) {
}

describe('analytics:autoinstall:app:create', () => {
let requestBody: AnyJson | undefined;
function saveOffRequestBody(json: string | undefined) {
requestBody = undefined;
try {
requestBody = json && (JSON.parse(json) as AnyJson);
} catch (e) {
expect.fail('Error parsing request body: ' + (e instanceof Error ? e.message : String(e)));
}
}

// use this so we can have return different values from withConnectionRequest() to simulate polling
let requestNum: number;
beforeEach(() => {
requestNum = 0;
requestBody = undefined;
});

test
Expand Down Expand Up @@ -261,4 +272,32 @@ describe('analytics:autoinstall:app:create', () => {
.it('runs analytics:autoinstall:app:create with error during polling', ctx => {
expect(ctx.stderr).to.contain('expected error in polling');
});

// Test that --appname and --appdescription values appear in the request body
test
.withOrg({ username: '[email protected]' }, true)
.withConnectionRequest(async request => {
request = ensureJsonMap(request);
saveOffRequestBody(ensureString(request.body));
return requestWithStatus('New');
})
.stdout()
.command([
'analytics:autoinstall:app:create',
'--async',
'-n',
'abc',
'--appname',
'customname',
'--appdescription',
'customdesc'
])
.it('runs analytics:autoinstall:app:create --async --appname customname --appdescription customdesc', ctx => {
expect(ctx.stdout).to.contain(messages.getMessage('appCreateRequestSuccess', ['0UZxx0000004FzkGAE']));
expect(requestBody, 'requestBody').to.have.nested.include({
'configuration.appConfiguration.appLabel': 'customname',
'configuration.appConfiguration.appName': 'customname',
'configuration.appConfiguration.appDescription': 'customdesc'
});
});
});

0 comments on commit d6746cd

Please sign in to comment.