Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 23 additions & 31 deletions src/m365/spo/commands/hubsite/hubsite-get.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { pid } from '../../../../utils/pid.js';
import { session } from '../../../../utils/session.js';
import { sinonUtil } from '../../../../utils/sinonUtil.js';
import commands from '../../commands.js';
import spoListItemListCommand from '../listitem/listitem-list.js';
import command from './hubsite-get.js';
import { spo } from '../../../../utils/spo.js';

describe(commands.HUBSITE_GET, () => {
const validId = '9ff01368-1183-4cbb-82f2-92e7e9a3f4ce';
Expand Down Expand Up @@ -60,7 +60,7 @@ describe(commands.HUBSITE_GET, () => {
afterEach(() => {
sinonUtil.restore([
request.get,
Cli.executeCommandWithOutput
spo.getListItems
]);
});

Expand Down Expand Up @@ -222,36 +222,28 @@ describe(commands.HUBSITE_GET, () => {
throw 'Invalid request';
});

sinon.stub(Cli, 'executeCommandWithOutput').callsFake(async (command): Promise<any> => {
if (command === spoListItemListCommand) {
return {
stdout: JSON.stringify([
{
Title: "Lucky Charms",
SiteId: "c08c7be1-4b97-4caa-b88f-ec91100d7774",
SiteUrl: "https://contoso.sharepoint.com/sites/LuckyCharms"
},
{
Title: "Great Mates",
SiteId: "7c371590-d9dd-4eb1-beb3-20f3613fdd9a",
SiteUrl: "https://contoso.sharepoint.com/sites/GreatMates"
},
{
Title: "Life and Music",
SiteId: "dd007944-c7f9-4742-8c21-de8a7718696f",
SiteUrl: "https://contoso.sharepoint.com/sites/LifeAndMusic"
},
{
Title: "Leadership Connection",
SiteId: "ee8b42c3-3e6f-4822-87c1-c21ad666046b",
SiteUrl: "https://contoso.sharepoint.com/sites/leadership-connection"
}
]
)
};
sinon.stub(spo, 'getListItems').resolves([
{
Title: "Lucky Charms",
SiteId: "c08c7be1-4b97-4caa-b88f-ec91100d7774",
SiteUrl: "https://contoso.sharepoint.com/sites/LuckyCharms"
},
{
Title: "Great Mates",
SiteId: "7c371590-d9dd-4eb1-beb3-20f3613fdd9a",
SiteUrl: "https://contoso.sharepoint.com/sites/GreatMates"
},
{
Title: "Life and Music",
SiteId: "dd007944-c7f9-4742-8c21-de8a7718696f",
SiteUrl: "https://contoso.sharepoint.com/sites/LifeAndMusic"
},
{
Title: "Leadership Connection",
SiteId: "ee8b42c3-3e6f-4822-87c1-c21ad666046b",
SiteUrl: "https://contoso.sharepoint.com/sites/leadership-connection"
}
throw 'Invalid request';
});
]);

await command.action(logger, { options: { id: 'ee8b42c3-3e6f-4822-87c1-c21ad666046b', includeAssociatedSites: true, output: 'json' } });
assert(loggerLogSpy.calledWith({
Expand Down
21 changes: 2 additions & 19 deletions src/m365/spo/commands/hubsite/hubsite-get.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { Cli, CommandOutput } from '../../../../cli/Cli.js';
import { Cli } from '../../../../cli/Cli.js';
import { Logger } from '../../../../cli/Logger.js';
import Command from '../../../../Command.js';
import GlobalOptions from '../../../../GlobalOptions.js';
import request, { CliRequestOptions } from '../../../../request.js';
import { spo } from '../../../../utils/spo.js';
import { validation } from '../../../../utils/validation.js';
import SpoCommand from '../../../base/SpoCommand.js';
import commands from '../../commands.js';
import spoListItemListCommand, { Options as SpoListItemListCommandOptions } from '../listitem/listitem-list.js';
import { AssociatedSite } from './AssociatedSite.js';
import { HubSite } from './HubSite.js';

Expand Down Expand Up @@ -91,8 +89,7 @@ class SpoHubSiteGetCommand extends SpoCommand {

if (args.options.includeAssociatedSites === true && args.options.output && !Cli.shouldTrimOutput(args.options.output)) {
const spoAdminUrl = await spo.getSpoAdminUrl(logger, this.debug);
const associatedSitesCommandOutput = await this.getAssociatedSites(spoAdminUrl, hubSite.SiteId, logger, args);
const associatedSites: AssociatedSite[] = JSON.parse((associatedSitesCommandOutput as CommandOutput).stdout) as AssociatedSite[];
const associatedSites: AssociatedSite[] = await spo.getListItems(spoAdminUrl, 'DO_NOT_DELETE_SPLIST_TENANTADMIN_AGGREGATED_SITECOLLECTIONS', `HubSiteId eq '${hubSite.SiteId}'`, 'Title,SiteUrl,SiteId', logger, this.verbose);
hubSite.AssociatedSites = associatedSites.filter(s => s.SiteId !== hubSite.SiteId);
}

Expand All @@ -103,20 +100,6 @@ class SpoHubSiteGetCommand extends SpoCommand {
}
}

private async getAssociatedSites(spoAdminUrl: string, hubSiteId: string, logger: Logger, args: CommandArgs): Promise<CommandOutput> {
const options: SpoListItemListCommandOptions = {
output: 'json',
debug: args.options.debug,
verbose: args.options.verbose,
listTitle: 'DO_NOT_DELETE_SPLIST_TENANTADMIN_AGGREGATED_SITECOLLECTIONS',
webUrl: spoAdminUrl,
filter: `HubSiteId eq '${hubSiteId}'`,
fields: 'Title,SiteUrl,SiteId'
};

return Cli.executeCommandWithOutput(spoListItemListCommand as Command, { options: { ...options, _: [] } });
}

private async getHubSiteById(spoUrl: string, options: Options): Promise<HubSite> {
const requestOptions: CliRequestOptions = {
url: `${spoUrl}/_api/hubsites/getbyid('${options.id}')`,
Expand Down
89 changes: 89 additions & 0 deletions src/utils/spo.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2016,4 +2016,93 @@ describe('utils/spo', () => {
const actual = await spo.getWeb('https://contoso.sharepoint.com', logger, true);
assert.deepStrictEqual(actual, webResponse);
});


it(`gets listitem instances succesfully with filter en fields selection`, async () => {
const listTitle = 'Demo List';
const filter = `Title eq 'Demo list item'`;
const fields = 'Title,ListItemAllFields/ID';
const listItemResponse = {
value:
[{
"Attachments": false,
"AuthorId": 3,
"ContentTypeId": "0x0100B21BD271A810EE488B570BE49963EA34",
"Created": "2018-08-15T13:43:12Z",
"EditorId": 3,
"GUID": "2b6bd9e0-3c43-4420-891e-20053e3c4664",
"Id": 1,
"ID": 1,
"Modified": "2018-08-15T13:43:12Z",
"Title": "Example item 1"
},
{
"Attachments": false,
"AuthorId": 3,
"ContentTypeId": "0x0100B21BD271A810EE488B570BE49963EA34",
"Created": "2018-08-15T13:44:10Z",
"EditorId": 3,
"GUID": "47c5fc61-afb7-4081-aa32-f4386b8a86ea",
"Id": 2,
"ID": 2,
"Modified": "2018-08-15T13:44:10Z",
"Title": "Example item 2"
}]
};

sinon.stub(request, 'get').callsFake(async (opts) => {
if (opts.url === `${webUrl}/_api/web/lists/getByTitle('${formatting.encodeQueryParameter(listTitle)}')/items?$top=5000&$filter=Title%20eq%20'Demo%20list%20item'&$expand=ListItemAllFields&$select=Title%2CListItemAllFields%2FID`) {
return listItemResponse;
}

throw 'Invalid request';
});


const actual = await spo.getListItems(webUrl, listTitle, filter, fields, logger, true);
assert.strictEqual(actual, listItemResponse.value);
});

it(`gets listitem instances succesfully`, async () => {
const listTitle = 'Demo List';
const listItemResponse = {
value:
[{
"Attachments": false,
"AuthorId": 3,
"ContentTypeId": "0x0100B21BD271A810EE488B570BE49963EA34",
"Created": "2018-08-15T13:43:12Z",
"EditorId": 3,
"GUID": "2b6bd9e0-3c43-4420-891e-20053e3c4664",
"Id": 1,
"ID": 1,
"Modified": "2018-08-15T13:43:12Z",
"Title": "Example item 1"
},
{
"Attachments": false,
"AuthorId": 3,
"ContentTypeId": "0x0100B21BD271A810EE488B570BE49963EA34",
"Created": "2018-08-15T13:44:10Z",
"EditorId": 3,
"GUID": "47c5fc61-afb7-4081-aa32-f4386b8a86ea",
"Id": 2,
"ID": 2,
"Modified": "2018-08-15T13:44:10Z",
"Title": "Example item 2"
}]
};

sinon.stub(request, 'get').callsFake(async (opts) => {
if (opts.url === `${webUrl}/_api/web/lists/getByTitle('${formatting.encodeQueryParameter(listTitle)}')/items?$top=5000`) {
return listItemResponse;
}

throw 'Invalid request';
});


const actual = await spo.getListItems(webUrl, listTitle);
assert.strictEqual(actual, listItemResponse.value);
});
});
37 changes: 37 additions & 0 deletions src/utils/spo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { SiteProperties } from '../m365/spo/commands/site/SiteProperties.js';
import { aadGroup } from './aadGroup.js';
import { SharingCapabilities } from '../m365/spo/commands/site/SharingCapabilities.js';
import { WebProperties } from '../m365/spo/commands/web/WebProperties.js';
import { ListItemInstance } from '../m365/spo/commands/listitem/ListItemInstance.js';

export interface ContextInfo {
FormDigestTimeoutSeconds: number;
Expand Down Expand Up @@ -1453,5 +1454,41 @@ export const spo = {
const webProperties: WebProperties = await request.get<WebProperties>(requestOptions);

return webProperties;
},

/**
* Get the listitems of a SharePoint list.
* Returns an array of ListItemInstance or an array with the field properties if supplied
* @param webUrl Web url
* @param listTitle The title of the list
* @param filter The filter on which the listitems should be filtered
* @param fields A comma seperated string of the fields it should return
* @param logger The logger object
* @param verbose If the function is executed in verbose mode
*/
async getListItems(webUrl: string, listTitle: string, filter?: string, fields?: string, logger?: Logger, verbose?: boolean): Promise<any> {
if (verbose && logger) {
logger.logToStderr(`Retrieving the listitems for the list ${listTitle}`);
}
const listApiUrl = `${webUrl}/_api/web/lists/getByTitle('${formatting.encodeQueryParameter(listTitle)}')`;
const fieldsArray: string[] = fields ? fields.split(",") : [];
const fieldsWithSlash: string[] = fieldsArray.filter(item => item.includes('/'));
const fieldsToExpand: string[] = fieldsWithSlash.map(e => e.split('/')[0]);
const expandFieldsArray: string[] = fieldsToExpand.filter((item, pos) => fieldsToExpand.indexOf(item) === pos);
const queryParams = [`$top=5000`];

if (filter) {
queryParams.push(`$filter=${encodeURIComponent(filter)}`);
}

if (expandFieldsArray.length > 0) {
queryParams.push(`$expand=${expandFieldsArray.join(",")}`);
}

if (fieldsArray.length > 0) {
queryParams.push(`$select=${formatting.encodeQueryParameter(fieldsArray.join(","))}`);
}

return await odata.getAllItems<ListItemInstance>(`${listApiUrl}/items?${queryParams.join('&')}`);
}
};