-
Notifications
You must be signed in to change notification settings - Fork 317
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added the spo site get command solving #114
- Loading branch information
1 parent
f561437
commit 77a2265
Showing
5 changed files
with
529 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# spo site get | ||
|
||
Gets information about the specific site collection | ||
|
||
## Usage | ||
|
||
```sh | ||
spo site get [options] | ||
``` | ||
|
||
## Options | ||
|
||
Option|Description | ||
------|----------- | ||
`--help`|output usage information | ||
`-u, --url <url>`|URL of the site to retrieve information for | ||
`-o, --output <output>`|Output type. `json|text`. Default `text` | ||
`--verbose`|Runs command with verbose logging | ||
`--debug`|Runs command with debug logging | ||
|
||
!!! important | ||
Before using this command, connect to a SharePoint Online tenant admin site, using the [spo connect](../connect.md) command. | ||
|
||
## Remarks | ||
|
||
To get information about a site collection, you have to first connect to a tenant admin site using the [spo connect](../connect.md) command, eg. `spo connect https://contoso-admin.sharepoint.com`. If you are connected to a different site and will try to to get site collection information, you will get an error. | ||
|
||
This command can retrieve information for both classic and modern sites. | ||
|
||
## Examples | ||
|
||
Return information about the _https://contoso.sharepoint.com/sites/project-x_ site collection. | ||
|
||
```sh | ||
spo site get -u https://contoso.sharepoint.com/sites/project-x | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,341 @@ | ||
import commands from '../../commands'; | ||
import Command, { CommandValidate, CommandOption, CommandError } from '../../../../Command'; | ||
import config from '../../../../config'; | ||
import * as sinon from 'sinon'; | ||
import appInsights from '../../../../appInsights'; | ||
import auth, { Site } from '../../SpoAuth'; | ||
const command: Command = require('./site-get'); | ||
import * as assert from 'assert'; | ||
import * as request from 'request-promise-native'; | ||
import Utils from '../../../../Utils'; | ||
|
||
describe(commands.SITE_GET, () => { | ||
let vorpal: Vorpal; | ||
let log: any[]; | ||
let cmdInstance: any; | ||
let cmdInstanceLogSpy: sinon.SinonSpy; | ||
let trackEvent: any; | ||
let telemetry: any; | ||
|
||
before(() => { | ||
sinon.stub(auth, 'restoreAuth').callsFake(() => Promise.resolve()); | ||
sinon.stub(auth, 'ensureAccessToken').callsFake(() => { return Promise.resolve('ABC'); }); | ||
sinon.stub(command as any, 'getRequestDigest').callsFake(() => { return { FormDigestValue: 'abc' }; }); | ||
trackEvent = sinon.stub(appInsights, 'trackEvent').callsFake((t) => { | ||
telemetry = t; | ||
}); | ||
}); | ||
|
||
beforeEach(() => { | ||
vorpal = require('../../../../vorpal-init'); | ||
log = []; | ||
cmdInstance = { | ||
log: (msg: string) => { | ||
log.push(msg); | ||
} | ||
}; | ||
cmdInstanceLogSpy = sinon.spy(cmdInstance, 'log'); | ||
auth.site = new Site(); | ||
telemetry = null; | ||
}); | ||
|
||
afterEach(() => { | ||
Utils.restore(vorpal.find); | ||
}); | ||
|
||
after(() => { | ||
Utils.restore([ | ||
appInsights.trackEvent, | ||
auth.ensureAccessToken, | ||
auth.restoreAuth, | ||
(command as any).getRequestDigest | ||
]); | ||
}); | ||
|
||
it('has correct name', () => { | ||
assert.equal(command.name.startsWith(commands.SITE_GET), true); | ||
}); | ||
|
||
it('has a description', () => { | ||
assert.notEqual(command.description, null); | ||
}); | ||
|
||
it('calls telemetry', (done) => { | ||
cmdInstance.action = command.action(); | ||
cmdInstance.action({ options: {} }, () => { | ||
try { | ||
assert(trackEvent.called); | ||
done(); | ||
} | ||
catch (e) { | ||
done(e); | ||
} | ||
}); | ||
}); | ||
|
||
it('logs correct telemetry event', (done) => { | ||
cmdInstance.action = command.action(); | ||
cmdInstance.action({ options: {} }, () => { | ||
try { | ||
assert.equal(telemetry.name, commands.SITE_GET); | ||
done(); | ||
} | ||
catch (e) { | ||
done(e); | ||
} | ||
}); | ||
}); | ||
|
||
it('aborts when not connected to a SharePoint site', (done) => { | ||
auth.site = new Site(); | ||
auth.site.connected = false; | ||
cmdInstance.action = command.action(); | ||
cmdInstance.action({ options: { debug: true } }, () => { | ||
try { | ||
assert(cmdInstanceLogSpy.calledWith(new CommandError('Connect to a SharePoint Online site first'))); | ||
done(); | ||
} | ||
catch (e) { | ||
done(e); | ||
} | ||
}); | ||
}); | ||
|
||
it('aborts when not connected to a SharePoint tenant admin site', (done) => { | ||
auth.site = new Site(); | ||
auth.site.connected = true; | ||
auth.site.url = 'https://contoso.sharepoint.com'; | ||
cmdInstance.action = command.action(); | ||
cmdInstance.action({ options: { debug: true } }, () => { | ||
try { | ||
assert(cmdInstanceLogSpy.calledWith(new CommandError(`https://contoso.sharepoint.com is not a tenant admin site. Connect to your tenant admin site and try again`))); | ||
done(); | ||
} | ||
catch (e) { | ||
done(e); | ||
} | ||
}); | ||
}); | ||
|
||
it('retrieves the information for the specified site', (done) => { | ||
const siteProperties = { | ||
"_ObjectType_": "Microsoft.Online.SharePoint.TenantAdministration.SiteProperties", "_ObjectIdentity_": "2868379e-c0b6-4000-823f-d9e855fd1204|908bed80-a04a-4433-b4a0-883d9847d110:67753f63-bc14-4012-869e-f808a43fe023\nSiteProperties\nhttps%3a%2f%2fm365x324230.sharepoint.com%2fsites%2fcomtest_001", "AllowDownloadingNonWebViewableFiles": true, "AllowEditing": true, "AllowSelfServiceUpgrade": true, "AverageResourceUsage": 0, "CommentsOnSitePagesDisabled": false, "CompatibilityLevel": 15, "ConditionalAccessPolicy": 0, "CurrentResourceUsage": 0, "DenyAddAndCustomizePages": 2, "DisableAppViews": 2, "DisableCompanyWideSharingLinks": 2, "DisableFlows": 2, "HasHolds": false, "LastContentModifiedDate": "\/Date(2017,11,17,4,6,59,233)\/", "Lcid": 1033, "LockIssue": null, "LockState": "Unlock", "NewUrl": "", "Owner": "admin@m365x324230.onmicrosoft.com", "OwnerEmail": "admin@M365x324230.onmicrosoft.com", "PWAEnabled": 0, "RestrictedToRegion": 3, "SandboxedCodeActivationCapability": 2, "SharingAllowedDomainList": "", "SharingBlockedDomainList": "", "SharingCapability": 0, "SharingDomainRestrictionMode": 0, "ShowPeoplePickerSuggestionsForGuestUsers": false, "SiteDefinedSharingCapability": 0, "Status": "Active", "StorageMaximumLevel": 26214400, "StorageQuotaType": null, "StorageUsage": 1, "StorageWarningLevel": 25574400, "Template": "SITEPAGEPUBLISHING#0", "TimeZoneId": 13, "Title": "ComTest 001", "Url": "https:\u002f\u002fm365x324230.sharepoint.com\u002fsites\u002fcomtest_001", "UserCodeMaximumLevel": 300, "UserCodeWarningLevel": 200, "WebsCount": 1 | ||
}; | ||
const response = [ | ||
{ | ||
"SchemaVersion": "15.0.0.0", "LibraryVersion": "16.0.7206.1204", "ErrorInfo": null, "TraceCorrelationId": "2868379e-c0b6-4000-823f-d9e855fd1204" | ||
}, 2, { | ||
"IsNull": false | ||
}, 4, { | ||
"IsNull": false | ||
}, 5, siteProperties | ||
]; | ||
sinon.stub(request, 'post').callsFake((opts) => { | ||
if (opts.url.indexOf(`/_vti_bin/client.svc/ProcessQuery`) > -1) { | ||
if (opts.headers.authorization && | ||
opts.headers.authorization.indexOf('Bearer ') === 0 && | ||
opts.headers['X-RequestDigest'] && | ||
opts.headers['X-RequestDigest'] === 'abc' && | ||
opts.body === `<Request AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="${config.applicationName}" xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009"><Actions><ObjectPath Id="2" ObjectPathId="1" /><ObjectPath Id="4" ObjectPathId="3" /><Query Id="5" ObjectPathId="3"><Query SelectAllProperties="true"><Properties /></Query></Query></Actions><ObjectPaths><Constructor Id="1" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}" /><Method Id="3" ParentId="1" Name="GetSitePropertiesByUrl"><Parameters><Parameter Type="String">https://contoso.sharepoint.com/sites/project-x</Parameter><Parameter Type="Boolean">true</Parameter></Parameters></Method></ObjectPaths></Request>`) { | ||
return Promise.resolve(JSON.stringify(response)); | ||
} | ||
} | ||
|
||
return Promise.reject('Invalid request'); | ||
}); | ||
|
||
auth.site = new Site(); | ||
auth.site.connected = true; | ||
auth.site.url = 'https://contoso-admin.sharepoint.com'; | ||
auth.site.tenantId = 'abc'; | ||
cmdInstance.action = command.action(); | ||
cmdInstance.action({ options: { debug: false, url: 'https://contoso.sharepoint.com/sites/project-x' } }, () => { | ||
const expected = siteProperties; | ||
delete expected._ObjectIdentity_; | ||
delete expected._ObjectType_; | ||
try { | ||
assert(cmdInstanceLogSpy.calledWith(expected)); | ||
done(); | ||
} | ||
catch (e) { | ||
done(e); | ||
} | ||
finally { | ||
Utils.restore(request.post); | ||
} | ||
}); | ||
}); | ||
|
||
it('retrieves the information for the specified site (debug)', (done) => { | ||
const siteProperties = { | ||
"_ObjectType_": "Microsoft.Online.SharePoint.TenantAdministration.SiteProperties", "_ObjectIdentity_": "2868379e-c0b6-4000-823f-d9e855fd1204|908bed80-a04a-4433-b4a0-883d9847d110:67753f63-bc14-4012-869e-f808a43fe023\nSiteProperties\nhttps%3a%2f%2fm365x324230.sharepoint.com%2fsites%2fcomtest_001", "AllowDownloadingNonWebViewableFiles": true, "AllowEditing": true, "AllowSelfServiceUpgrade": true, "AverageResourceUsage": 0, "CommentsOnSitePagesDisabled": false, "CompatibilityLevel": 15, "ConditionalAccessPolicy": 0, "CurrentResourceUsage": 0, "DenyAddAndCustomizePages": 2, "DisableAppViews": 2, "DisableCompanyWideSharingLinks": 2, "DisableFlows": 2, "HasHolds": false, "LastContentModifiedDate": "\/Date(2017,11,17,4,6,59,233)\/", "Lcid": 1033, "LockIssue": null, "LockState": "Unlock", "NewUrl": "", "Owner": "admin@m365x324230.onmicrosoft.com", "OwnerEmail": "admin@M365x324230.onmicrosoft.com", "PWAEnabled": 0, "RestrictedToRegion": 3, "SandboxedCodeActivationCapability": 2, "SharingAllowedDomainList": "", "SharingBlockedDomainList": "", "SharingCapability": 0, "SharingDomainRestrictionMode": 0, "ShowPeoplePickerSuggestionsForGuestUsers": false, "SiteDefinedSharingCapability": 0, "Status": "Active", "StorageMaximumLevel": 26214400, "StorageQuotaType": null, "StorageUsage": 1, "StorageWarningLevel": 25574400, "Template": "SITEPAGEPUBLISHING#0", "TimeZoneId": 13, "Title": "ComTest 001", "Url": "https:\u002f\u002fm365x324230.sharepoint.com\u002fsites\u002fcomtest_001", "UserCodeMaximumLevel": 300, "UserCodeWarningLevel": 200, "WebsCount": 1 | ||
}; | ||
const response = [ | ||
{ | ||
"SchemaVersion": "15.0.0.0", "LibraryVersion": "16.0.7206.1204", "ErrorInfo": null, "TraceCorrelationId": "2868379e-c0b6-4000-823f-d9e855fd1204" | ||
}, 2, { | ||
"IsNull": false | ||
}, 4, { | ||
"IsNull": false | ||
}, 5, siteProperties | ||
]; | ||
sinon.stub(request, 'post').callsFake((opts) => { | ||
if (opts.url.indexOf(`/_vti_bin/client.svc/ProcessQuery`) > -1) { | ||
if (opts.headers.authorization && | ||
opts.headers.authorization.indexOf('Bearer ') === 0 && | ||
opts.headers['X-RequestDigest'] && | ||
opts.headers['X-RequestDigest'] === 'abc' && | ||
opts.body === `<Request AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="${config.applicationName}" xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009"><Actions><ObjectPath Id="2" ObjectPathId="1" /><ObjectPath Id="4" ObjectPathId="3" /><Query Id="5" ObjectPathId="3"><Query SelectAllProperties="true"><Properties /></Query></Query></Actions><ObjectPaths><Constructor Id="1" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}" /><Method Id="3" ParentId="1" Name="GetSitePropertiesByUrl"><Parameters><Parameter Type="String">https://contoso.sharepoint.com/sites/project-x</Parameter><Parameter Type="Boolean">true</Parameter></Parameters></Method></ObjectPaths></Request>`) { | ||
return Promise.resolve(JSON.stringify(response)); | ||
} | ||
} | ||
|
||
return Promise.reject('Invalid request'); | ||
}); | ||
|
||
auth.site = new Site(); | ||
auth.site.connected = true; | ||
auth.site.url = 'https://contoso-admin.sharepoint.com'; | ||
auth.site.tenantId = 'abc'; | ||
cmdInstance.action = command.action(); | ||
cmdInstance.action({ options: { debug: true, url: 'https://contoso.sharepoint.com/sites/project-x' } }, () => { | ||
const expected = siteProperties; | ||
delete expected._ObjectIdentity_; | ||
delete expected._ObjectType_; | ||
try { | ||
assert(cmdInstanceLogSpy.calledWith(expected)); | ||
done(); | ||
} | ||
catch (e) { | ||
done(e); | ||
} | ||
finally { | ||
Utils.restore(request.post); | ||
} | ||
}); | ||
}); | ||
|
||
it('correctly handles error when getting information for a site that doesn\'t exist', (done) => { | ||
Utils.restore(request.post); | ||
sinon.stub(request, 'post').callsFake((opts) => { | ||
if (opts.url.indexOf('/_vti_bin/client.svc/ProcessQuery') > -1) { | ||
return Promise.resolve(JSON.stringify([ | ||
{ | ||
"SchemaVersion": "15.0.0.0", "LibraryVersion": "16.0.7206.1204", "ErrorInfo": { | ||
"ErrorMessage": "Cannot get site https:\u002f\u002fcontoso.sharepoint.com\u002fsites\u002fproject-x.", "ErrorValue": null, "TraceCorrelationId": "1b68379e-2051-4000-8242-711d8fb38a57", "ErrorCode": -1, "ErrorTypeName": "Microsoft.Online.SharePoint.Common.SpoNoSiteException" | ||
}, "TraceCorrelationId": "1b68379e-2051-4000-8242-711d8fb38a57" | ||
} | ||
])); | ||
} | ||
|
||
return Promise.reject('Invalid request'); | ||
}); | ||
|
||
auth.site = new Site(); | ||
auth.site.connected = true; | ||
auth.site.url = 'https://contoso-admin.sharepoint.com'; | ||
auth.site.tenantId = 'abc'; | ||
cmdInstance.action = command.action(); | ||
cmdInstance.action({ options: { debug: true, url: 'https://contoso.sharepoint.com/sites/project-x' } }, () => { | ||
try { | ||
assert(cmdInstanceLogSpy.calledWith(new CommandError('Cannot get site https://contoso.sharepoint.com/sites/project-x.'))); | ||
done(); | ||
} | ||
catch (e) { | ||
done(e); | ||
} | ||
finally { | ||
Utils.restore(request.post); | ||
} | ||
}); | ||
}); | ||
|
||
it('supports debug mode', () => { | ||
const options = (command.options() as CommandOption[]); | ||
let containsDebugOption = false; | ||
options.forEach(o => { | ||
if (o.option === '--debug') { | ||
containsDebugOption = true; | ||
} | ||
}); | ||
assert(containsDebugOption); | ||
}); | ||
|
||
it('supports specifying URL', () => { | ||
const options = (command.options() as CommandOption[]); | ||
let containsTypeOption = false; | ||
options.forEach(o => { | ||
if (o.option.indexOf('<url>') > -1) { | ||
containsTypeOption = true; | ||
} | ||
}); | ||
assert(containsTypeOption); | ||
}); | ||
|
||
it('fails validation if the url option not specified', () => { | ||
const actual = (command.validate() as CommandValidate)({ options: { } }); | ||
assert.notEqual(actual, true); | ||
}); | ||
|
||
it('fails validation if the url option is not a valid SharePoint site URL', () => { | ||
const actual = (command.validate() as CommandValidate)({ options: { url: 'foo' } }); | ||
assert.notEqual(actual, true); | ||
}); | ||
|
||
it('passes validation if the url option is a valid SharePoint site URL', () => { | ||
const actual = (command.validate() as CommandValidate)({ options: { url: 'https://contoso.sharepoint.com' } }); | ||
assert(actual); | ||
}); | ||
|
||
it('has help referring to the right command', () => { | ||
const cmd: any = { | ||
log: (msg: string) => { }, | ||
prompt: () => { }, | ||
helpInformation: () => { } | ||
}; | ||
const find = sinon.stub(vorpal, 'find').callsFake(() => cmd); | ||
cmd.help = command.help(); | ||
cmd.help({}, () => { }); | ||
assert(find.calledWith(commands.SITE_GET)); | ||
}); | ||
|
||
it('has help with examples', () => { | ||
const _log: string[] = []; | ||
const cmd: any = { | ||
log: (msg: string) => { | ||
_log.push(msg); | ||
}, | ||
prompt: () => { }, | ||
helpInformation: () => { } | ||
}; | ||
sinon.stub(vorpal, 'find').callsFake(() => cmd); | ||
cmd.help = command.help(); | ||
cmd.help({}, () => { }); | ||
let containsExamples: boolean = false; | ||
_log.forEach(l => { | ||
if (l && l.indexOf('Examples:') > -1) { | ||
containsExamples = true; | ||
} | ||
}); | ||
Utils.restore(vorpal.find); | ||
assert(containsExamples); | ||
}); | ||
|
||
it('correctly handles lack of valid access token', (done) => { | ||
Utils.restore(auth.ensureAccessToken); | ||
sinon.stub(auth, 'ensureAccessToken').callsFake(() => { return Promise.reject(new Error('Error getting access token')); }); | ||
auth.site = new Site(); | ||
auth.site.connected = true; | ||
auth.site.url = 'https://contoso-admin.sharepoint.com'; | ||
cmdInstance.action = command.action(); | ||
cmdInstance.action({ options: { debug: true } }, () => { | ||
try { | ||
assert(cmdInstanceLogSpy.calledWith(new CommandError('Error getting access token'))); | ||
done(); | ||
} | ||
catch (e) { | ||
done(e); | ||
} | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.