Skip to content

Commit c630ff9

Browse files
committed
First commit
1 parent 515b009 commit c630ff9

File tree

4 files changed

+474
-160
lines changed

4 files changed

+474
-160
lines changed

src/m365/spo/commands/tenant/tenant-commandset-add.spec.ts

Lines changed: 105 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,9 @@ import { Logger } from '../../../../cli/Logger.js';
99
import { pid } from '../../../../utils/pid.js';
1010
import { session } from '../../../../utils/session.js';
1111
import { sinonUtil } from '../../../../utils/sinonUtil.js';
12-
import { urlUtil } from '../../../../utils/urlUtil.js';
1312
import commands from '../../commands.js';
14-
import spoListItemAddCommand from '../listitem/listitem-add.js';
15-
import spoListItemListCommand from '../listitem/listitem-list.js';
16-
import spoTenantAppCatalogUrlGetCommand from './tenant-appcatalogurl-get.js';
1713
import command from './tenant-commandset-add.js';
14+
import { spo } from '../../../../utils/spo.js';
1815

1916
describe(commands.TENANT_COMMANDSET_ADD, () => {
2017
const clientSideComponentId = '9748c81b-d72e-4048-886a-e98649543743';
@@ -29,6 +26,19 @@ describe(commands.TENANT_COMMANDSET_ADD, () => {
2926
const solutionResponse = [solution];
3027
const application = { "FileSystemObjectType": 0, "Id": 31, "ServerRedirectedEmbedUri": null, "ServerRedirectedEmbedUrl": "", "SkipFeatureDeployment": true, "ContainsTenantWideExtension": true, "Modified": "2022-11-03T11:26:03", "CheckoutUserId": null, "EditorId": 9 };
3128
const applicationResponse = [application];
29+
const listItemResponse = {
30+
Attachments: false,
31+
AuthorId: 3,
32+
ContentTypeId: '0x0100B21BD271A810EE488B570BE49963EA34',
33+
Created: new Date('2018-03-15T10:43:10Z'),
34+
EditorId: 3,
35+
GUID: 'ea093c7b-8ae6-4400-8b75-e2d01154dffc',
36+
Id: 0,
37+
ID: 0,
38+
Modified: new Date('2018-03-15T10:43:10Z'),
39+
Title: 'listTitle',
40+
RoleAssignments: []
41+
};
3242

3343
let log: string[];
3444
let logger: Logger;
@@ -60,8 +70,9 @@ describe(commands.TENANT_COMMANDSET_ADD, () => {
6070

6171
afterEach(() => {
6272
sinonUtil.restore([
63-
Cli.executeCommand,
64-
Cli.executeCommandWithOutput
73+
spo.getTenantAppCatalogUrl,
74+
spo.addListItem,
75+
spo.getListItems
6576
]);
6677
});
6778

@@ -80,142 +91,120 @@ describe(commands.TENANT_COMMANDSET_ADD, () => {
8091

8192
it('adds a tenant-wide ListView Command Set for lists', async () => {
8293
let executeCommandCalled = false;
83-
sinon.stub(Cli, 'executeCommandWithOutput').callsFake(async (command, args): Promise<any> => {
84-
if (command === spoListItemListCommand) {
85-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/Lists/ComponentManifests`) {
86-
return { 'stdout': JSON.stringify(solutionResponse) };
94+
95+
sinon.stub(spo, 'getTenantAppCatalogUrl').resolves(appCatalogUrl);
96+
sinon.stub(spo, 'getListItems').callsFake(async (url, listTitle, listUrl) => {
97+
if (url === appCatalogUrl) {
98+
if (listUrl === '/sites/apps/Lists/ComponentManifests') {
99+
return solutionResponse;
87100
}
88-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/AppCatalog`) {
89-
return { 'stdout': JSON.stringify(applicationResponse) };
101+
else if (listUrl === '/sites/apps/AppCatalog') {
102+
return applicationResponse;
90103
}
91104
}
92-
if (command === spoTenantAppCatalogUrlGetCommand) {
93-
return { 'stdout': appCatalogUrl };
94-
}
95-
throw 'Invalid request';
96-
});
97105

98-
sinon.stub(Cli, 'executeCommand').callsFake(async (command): Promise<void> => {
99-
if (command === spoListItemAddCommand) {
100-
executeCommandCalled = true;
101-
return;
102-
}
103106
throw 'Invalid request';
104107
});
108+
sinon.stub(spo, 'addListItem').callsFake(async () => {
109+
executeCommandCalled = true;
110+
return listItemResponse;
111+
});
105112

106113
await command.action(logger, { options: { clientSideComponentId: clientSideComponentId, listType: 'List', title: customizerTitle, verbose: true } });
107114
assert.strictEqual(executeCommandCalled, true);
108115
});
109116

110117
it('adds a tenant-wide ListView Command Set for libraries', async () => {
111118
let executeCommandCalled = false;
112-
sinon.stub(Cli, 'executeCommandWithOutput').callsFake(async (command, args): Promise<any> => {
113-
if (command === spoListItemListCommand) {
114-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/Lists/ComponentManifests`) {
115-
return { 'stdout': JSON.stringify(solutionResponse) };
119+
120+
sinon.stub(spo, 'getTenantAppCatalogUrl').resolves(appCatalogUrl);
121+
sinon.stub(spo, 'getListItems').callsFake(async (url, listTitle, listUrl) => {
122+
if (url === appCatalogUrl) {
123+
if (listUrl === '/sites/apps/Lists/ComponentManifests') {
124+
return solutionResponse;
116125
}
117-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/AppCatalog`) {
118-
return { 'stdout': JSON.stringify(applicationResponse) };
126+
else if (listUrl === '/sites/apps/AppCatalog') {
127+
return applicationResponse;
119128
}
120129
}
121-
if (command === spoTenantAppCatalogUrlGetCommand) {
122-
return { 'stdout': appCatalogUrl };
123-
}
124-
throw 'Invalid request';
125-
});
126130

127-
sinon.stub(Cli, 'executeCommand').callsFake(async (command): Promise<void> => {
128-
if (command === spoListItemAddCommand) {
129-
executeCommandCalled = true;
130-
return;
131-
}
132131
throw 'Invalid request';
133132
});
133+
sinon.stub(spo, 'addListItem').callsFake(async () => {
134+
executeCommandCalled = true;
135+
return listItemResponse;
136+
});
134137

135138
await command.action(logger, { options: { clientSideComponentId: clientSideComponentId, listType: 'Library', location: 'ContextMenu', title: customizerTitle, verbose: true } });
136139
assert.strictEqual(executeCommandCalled, true);
137140
});
138141

139142
it('adds a tenant-wide ListView Command Set for the SitePages library', async () => {
140143
let executeCommandCalled = false;
141-
sinon.stub(Cli, 'executeCommandWithOutput').callsFake(async (command, args): Promise<any> => {
142-
if (command === spoListItemListCommand) {
143-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/Lists/ComponentManifests`) {
144-
return { 'stdout': JSON.stringify(solutionResponse) };
144+
145+
sinon.stub(spo, 'getTenantAppCatalogUrl').resolves(appCatalogUrl);
146+
sinon.stub(spo, 'getListItems').callsFake(async (url, listTitle, listUrl) => {
147+
if (url === appCatalogUrl) {
148+
if (listUrl === '/sites/apps/Lists/ComponentManifests') {
149+
return solutionResponse;
145150
}
146-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/AppCatalog`) {
147-
return { 'stdout': JSON.stringify(applicationResponse) };
151+
else if (listUrl === '/sites/apps/AppCatalog') {
152+
return applicationResponse;
148153
}
149154
}
150-
if (command === spoTenantAppCatalogUrlGetCommand) {
151-
return { 'stdout': appCatalogUrl };
152-
}
153-
throw 'Invalid request';
154-
});
155155

156-
sinon.stub(Cli, 'executeCommand').callsFake(async (command): Promise<void> => {
157-
if (command === spoListItemAddCommand) {
158-
executeCommandCalled = true;
159-
return;
160-
}
161156
throw 'Invalid request';
162157
});
158+
sinon.stub(spo, 'addListItem').callsFake(async () => {
159+
executeCommandCalled = true;
160+
return listItemResponse;
161+
});
163162

164163
await command.action(logger, { options: { clientSideComponentId: clientSideComponentId, listType: 'SitePages', location: 'CommandBar', title: customizerTitle, verbose: true } });
165164
assert.strictEqual(executeCommandCalled, true);
166165
});
167166

168167
it('adds a tenant-wide ListView Command Set to a specific webtemplate and location including clientSideComponentProperties', async () => {
169168
let executeCommandCalled = false;
170-
sinon.stub(Cli, 'executeCommandWithOutput').callsFake(async (command, args): Promise<any> => {
171-
if (command === spoListItemListCommand) {
172-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/Lists/ComponentManifests`) {
173-
return { 'stdout': JSON.stringify(solutionResponse) };
169+
170+
sinon.stub(spo, 'getTenantAppCatalogUrl').resolves(appCatalogUrl);
171+
sinon.stub(spo, 'getListItems').callsFake(async (url, listTitle, listUrl) => {
172+
if (url === appCatalogUrl) {
173+
if (listUrl === '/sites/apps/Lists/ComponentManifests') {
174+
return solutionResponse;
174175
}
175-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/AppCatalog`) {
176-
return { 'stdout': JSON.stringify(applicationResponse) };
176+
else if (listUrl === '/sites/apps/AppCatalog') {
177+
return applicationResponse;
177178
}
178179
}
179-
if (command === spoTenantAppCatalogUrlGetCommand) {
180-
return { 'stdout': appCatalogUrl };
181-
}
182-
throw 'Invalid request';
183-
});
184180

185-
sinon.stub(Cli, 'executeCommand').callsFake(async (command): Promise<void> => {
186-
if (command === spoListItemAddCommand) {
187-
executeCommandCalled = true;
188-
return;
189-
}
190181
throw 'Invalid request';
191182
});
183+
sinon.stub(spo, 'addListItem').callsFake(async () => {
184+
executeCommandCalled = true;
185+
return listItemResponse;
186+
});
192187

193188
await command.action(logger, { options: { clientSideComponentId: clientSideComponentId, listType: 'Library', title: customizerTitle, webTemplate: webTemplate, location: 'Both', clientSideComponentProperties: clientSideComponentProperties, verbose: true } });
194189
assert.strictEqual(executeCommandCalled, true);
195190
});
196191

197192
it('throws an error when no app catalog is found', async () => {
198-
sinon.stub(Cli, 'executeCommandWithOutput').callsFake(async (command): Promise<any> => {
199-
if (command === spoTenantAppCatalogUrlGetCommand) {
200-
return { 'stdout': null };
201-
}
202-
throw 'Invalid request';
203-
});
193+
sinon.stub(spo, 'getTenantAppCatalogUrl').resolves(null);
204194

205195
await assert.rejects(command.action(logger, { options: { title: customizerTitle, clientSideComponentId: clientSideComponentId, verbose: true } }),
206196
new CommandError('Cannot add tenant-wide ListView Command Set as app catalog cannot be found'));
207197
});
208198

209199
it('throws an error when specific client side component is not found in manifest list', async () => {
210-
sinon.stub(Cli, 'executeCommandWithOutput').callsFake(async (command, args): Promise<any> => {
211-
if (command === spoListItemListCommand) {
212-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/Lists/ComponentManifests`) {
213-
return { 'stdout': JSON.stringify([]) };
200+
sinon.stub(spo, 'getTenantAppCatalogUrl').resolves(appCatalogUrl);
201+
sinon.stub(spo, 'getListItems').callsFake(async (url, listTitle, listUrl) => {
202+
if (url === appCatalogUrl) {
203+
if (listUrl === '/sites/apps/Lists/ComponentManifests') {
204+
return [];
214205
}
215206
}
216-
if (command === spoTenantAppCatalogUrlGetCommand) {
217-
return { 'stdout': appCatalogUrl };
218-
}
207+
219208
throw 'Invalid request';
220209
});
221210

@@ -224,18 +213,20 @@ describe(commands.TENANT_COMMANDSET_ADD, () => {
224213
});
225214

226215
it('throws an error when the manifest of a specific client side component is not of type ListView Command Set', async () => {
227-
sinon.stub(Cli, 'executeCommandWithOutput').callsFake(async (command, args): Promise<any> => {
228-
if (command === spoListItemListCommand) {
229-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/Lists/ComponentManifests`) {
216+
sinon.stub(spo, 'getTenantAppCatalogUrl').resolves(appCatalogUrl);
217+
sinon.stub(spo, 'getListItems').callsFake(async (url, listTitle, listUrl) => {
218+
if (url === appCatalogUrl) {
219+
if (listUrl === '/sites/apps/Lists/ComponentManifests') {
230220
const faultyClientComponentManifest = "{\"id\":\"6b2a54c5-3317-49eb-8621-1bbb76263629\",\"alias\":\"HelloWorldCommandSet\",\"componentType\":\"Extension\",\"extensionType\":\"FormCustomizer\",\"version\":\"0.0.1\",\"manifestVersion\":2,\"loaderConfig\":{\"internalModuleBaseUrls\":[\"HTTPS://SPCLIENTSIDEASSETLIBRARY/\"],\"entryModuleId\":\"hello-world-command-set\",\"scriptResources\":{\"hello-world-command-set\":{\"type\":\"path\",\"path\":\"hello-world-command-set_b47769f9eca3d3b6c4d5.js\"},\"HelloWorldCommandSetStrings\":{\"type\":\"path\",\"path\":\"HelloWorldCommandSetStrings_en-us_72ca11838ac9bae2790a8692c260e1ac.js\"},\"@microsoft/sp-application-base\":{\"type\":\"component\",\"id\":\"4df9bb86-ab0a-4aab-ab5f-48bf167048fb\",\"version\":\"1.15.2\"},\"@microsoft/sp-core-library\":{\"type\":\"component\",\"id\":\"7263c7d0-1d6a-45ec-8d85-d4d1d234171b\",\"version\":\"1.15.2\"}}},\"mpnId\":\"Undefined-1.15.2\",\"clientComponentDeveloper\":\"\"}";
231221
const solutionDuplicate = { ...solution };
232222
solutionDuplicate.ClientComponentManifest = faultyClientComponentManifest;
233-
return { 'stdout': JSON.stringify([solutionDuplicate]) };
223+
return [solutionDuplicate];
224+
}
225+
else if (listUrl === '/sites/apps/AppCatalog') {
226+
return applicationResponse;
234227
}
235228
}
236-
if (command === spoTenantAppCatalogUrlGetCommand) {
237-
return { 'stdout': appCatalogUrl };
238-
}
229+
239230
throw 'Invalid request';
240231
});
241232

@@ -244,18 +235,17 @@ describe(commands.TENANT_COMMANDSET_ADD, () => {
244235
});
245236

246237
it('throws an error when solution is not found in app catalog', async () => {
247-
sinon.stub(Cli, 'executeCommandWithOutput').callsFake(async (command, args): Promise<any> => {
248-
if (command === spoListItemListCommand) {
249-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/Lists/ComponentManifests`) {
250-
return { 'stdout': JSON.stringify(solutionResponse) };
238+
sinon.stub(spo, 'getTenantAppCatalogUrl').resolves(appCatalogUrl);
239+
sinon.stub(spo, 'getListItems').callsFake(async (url, listTitle, listUrl) => {
240+
if (url === appCatalogUrl) {
241+
if (listUrl === '/sites/apps/Lists/ComponentManifests') {
242+
return solutionResponse;
251243
}
252-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/AppCatalog`) {
253-
return { 'stdout': JSON.stringify([]) };
244+
else if (listUrl === '/sites/apps/AppCatalog') {
245+
return [];
254246
}
255247
}
256-
if (command === spoTenantAppCatalogUrlGetCommand) {
257-
return { 'stdout': appCatalogUrl };
258-
}
248+
259249
throw 'Invalid request';
260250
});
261251

@@ -264,20 +254,19 @@ describe(commands.TENANT_COMMANDSET_ADD, () => {
264254
});
265255

266256
it('throws an error when solution does not contain extension that can be deployed tenant-wide', async () => {
267-
sinon.stub(Cli, 'executeCommandWithOutput').callsFake(async (command, args): Promise<any> => {
268-
if (command === spoListItemListCommand) {
269-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/Lists/ComponentManifests`) {
270-
return { 'stdout': JSON.stringify(solutionResponse) };
257+
sinon.stub(spo, 'getTenantAppCatalogUrl').resolves(appCatalogUrl);
258+
sinon.stub(spo, 'getListItems').callsFake(async (url, listTitle, listUrl) => {
259+
if (url === appCatalogUrl) {
260+
if (listUrl === '/sites/apps/Lists/ComponentManifests') {
261+
return solutionResponse;
271262
}
272-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/AppCatalog`) {
263+
else if (listUrl === '/sites/apps/AppCatalog') {
273264
const faultyApplication = { ...application };
274265
faultyApplication.ContainsTenantWideExtension = false;
275-
return { 'stdout': JSON.stringify([faultyApplication]) };
266+
return [faultyApplication];
276267
}
277268
}
278-
if (command === spoTenantAppCatalogUrlGetCommand) {
279-
return { 'stdout': appCatalogUrl };
280-
}
269+
281270
throw 'Invalid request';
282271
});
283272

@@ -286,20 +275,19 @@ describe(commands.TENANT_COMMANDSET_ADD, () => {
286275
});
287276

288277
it('throws an error when solution is not deployed globally', async () => {
289-
sinon.stub(Cli, 'executeCommandWithOutput').callsFake(async (command, args): Promise<any> => {
290-
if (command === spoListItemListCommand) {
291-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/Lists/ComponentManifests`) {
292-
return { 'stdout': JSON.stringify(solutionResponse) };
278+
sinon.stub(spo, 'getTenantAppCatalogUrl').resolves(appCatalogUrl);
279+
sinon.stub(spo, 'getListItems').callsFake(async (url, listTitle, listUrl) => {
280+
if (url === appCatalogUrl) {
281+
if (listUrl === '/sites/apps/Lists/ComponentManifests') {
282+
return solutionResponse;
293283
}
294-
if (args.options.listUrl === `${urlUtil.getServerRelativeSiteUrl(appCatalogUrl)}/AppCatalog`) {
284+
else if (listUrl === '/sites/apps/AppCatalog') {
295285
const faultyApplication = { ...application };
296286
faultyApplication.SkipFeatureDeployment = false;
297-
return { 'stdout': JSON.stringify([faultyApplication]) };
287+
return [faultyApplication];
298288
}
299289
}
300-
if (command === spoTenantAppCatalogUrlGetCommand) {
301-
return { 'stdout': appCatalogUrl };
302-
}
290+
303291
throw 'Invalid request';
304292
});
305293

0 commit comments

Comments
 (0)