1
+ import * as assert from 'assert' ;
2
+ import * as sinon from 'sinon' ;
3
+ import appInsights from '../../../../appInsights' ;
4
+ import auth from '../../../../Auth' ;
5
+ import { Cli } from '../../../../cli/Cli' ;
6
+ import { CommandInfo } from '../../../../cli/CommandInfo' ;
7
+ import { Logger } from '../../../../cli/Logger' ;
8
+ import Command , { CommandError } from '../../../../Command' ;
9
+ import request from '../../../../request' ;
10
+ import { pid } from '../../../../utils/pid' ;
11
+ import { sinonUtil } from '../../../../utils/sinonUtil' ;
12
+ import commands from '../../commands' ;
13
+ const command : Command = require ( './listitem-record-unlock' ) ;
14
+
15
+ describe ( commands . LISTITEM_RECORD_UNLOCK , ( ) => {
16
+ let log : any [ ] ;
17
+ let logger : Logger ;
18
+ let commandInfo : CommandInfo ;
19
+ const listUrl = "/MyLibrary" ;
20
+ const listTitle = "MyLibrary" ;
21
+ const listId = "cc27a922-8224-4296-90a5-ebbc54da2e85" ;
22
+ const webUrl = "https://contoso.sharepoint.com" ;
23
+ const listResponse = {
24
+ "RootFolder" : {
25
+ "Exists" : true ,
26
+ "IsWOPIEnabled" : false ,
27
+ "ItemCount" : 0 ,
28
+ "Name" : listTitle ,
29
+ "ProgID" : null ,
30
+ "ServerRelativeUrl" : listUrl ,
31
+ "TimeCreated" : "2019-01-11T10:03:19Z" ,
32
+ "TimeLastModified" : "2019-01-11T10:03:20Z" ,
33
+ "UniqueId" : listId ,
34
+ "WelcomePage" : ""
35
+ }
36
+ } ;
37
+
38
+ before ( ( ) => {
39
+ sinon . stub ( auth , 'restoreAuth' ) . callsFake ( ( ) => Promise . resolve ( ) ) ;
40
+ sinon . stub ( appInsights , 'trackEvent' ) . callsFake ( ( ) => { } ) ;
41
+ auth . service . connected = true ;
42
+ commandInfo = Cli . getCommandInfo ( command ) ;
43
+ } ) ;
44
+
45
+ beforeEach ( ( ) => {
46
+ log = [ ] ;
47
+ logger = {
48
+ log : ( msg : string ) => {
49
+ log . push ( msg ) ;
50
+ } ,
51
+ logRaw : ( msg : string ) => {
52
+ log . push ( msg ) ;
53
+ } ,
54
+ logToStderr : ( msg : string ) => {
55
+ log . push ( msg ) ;
56
+ }
57
+ } ;
58
+ } ) ;
59
+
60
+ afterEach ( ( ) => {
61
+ sinonUtil . restore ( [
62
+ request . get ,
63
+ request . post
64
+ ] ) ;
65
+ } ) ;
66
+
67
+ after ( ( ) => {
68
+ sinonUtil . restore ( [
69
+ auth . restoreAuth ,
70
+ appInsights . trackEvent ,
71
+ pid . getProcessName
72
+ ] ) ;
73
+ auth . service . connected = false ;
74
+ } ) ;
75
+
76
+ it ( 'has correct name' , ( ) => {
77
+ assert . strictEqual ( command . name , commands . LISTITEM_RECORD_UNLOCK ) ;
78
+ } ) ;
79
+
80
+ it ( 'has a description' , ( ) => {
81
+ assert . notStrictEqual ( command . description , null ) ;
82
+ } ) ;
83
+
84
+ it ( 'unlocks a list item based on listUrl (debug)' , async ( ) => {
85
+ sinon . stub ( request , 'post' ) . callsFake ( async ( opts ) => {
86
+ if ( opts . url === `https://contoso.sharepoint.com/_api/SP.CompliancePolicy.SPPolicyStoreProxy.UnlockRecordItem()` ) {
87
+ return ;
88
+ }
89
+
90
+ throw 'Invalid request' ;
91
+ } ) ;
92
+
93
+ await assert . doesNotReject ( command . action ( logger , {
94
+ options : {
95
+ verbose : true ,
96
+ listUrl : listUrl ,
97
+ webUrl : webUrl ,
98
+ listItemId : 1
99
+ }
100
+ } ) ) ;
101
+ } ) ;
102
+
103
+ it ( 'unlocks a list item based on listTitle' , async ( ) => {
104
+ sinon . stub ( request , 'get' ) . callsFake ( async ( opts ) => {
105
+ if ( opts . url === `https://contoso.sharepoint.com/_api/web/lists/getByTitle('${ listTitle } ')/?$expand=RootFolder&$select=RootFolder` ) {
106
+ return listResponse ;
107
+ }
108
+
109
+ throw 'Invalid request' ;
110
+ } ) ;
111
+
112
+ sinon . stub ( request , 'post' ) . callsFake ( async ( opts ) => {
113
+ if ( opts . url === `https://contoso.sharepoint.com/_api/SP.CompliancePolicy.SPPolicyStoreProxy.UnlockRecordItem()` ) {
114
+ return ;
115
+ }
116
+
117
+ throw 'Invalid request' ;
118
+ } ) ;
119
+
120
+ await assert . doesNotReject ( command . action ( logger , {
121
+ options : {
122
+ listTitle : listTitle ,
123
+ webUrl : webUrl ,
124
+ listItemId : 1
125
+ }
126
+ } ) ) ;
127
+ } ) ;
128
+
129
+ it ( 'unlocks a list item based on listId' , async ( ) => {
130
+ sinon . stub ( request , 'get' ) . callsFake ( async ( opts ) => {
131
+ if ( opts . url === `https://contoso.sharepoint.com/_api/web/lists(guid'${ listId } ')/?$expand=RootFolder&$select=RootFolder` ) {
132
+ return listResponse ;
133
+ }
134
+
135
+ throw 'Invalid request' ;
136
+ } ) ;
137
+
138
+ sinon . stub ( request , 'post' ) . callsFake ( async ( opts ) => {
139
+ if ( opts . url === `https://contoso.sharepoint.com/_api/SP.CompliancePolicy.SPPolicyStoreProxy.UnlockRecordItem()` ) {
140
+ return ;
141
+ }
142
+
143
+ throw 'Invalid request' ;
144
+ } ) ;
145
+
146
+ await assert . doesNotReject ( command . action ( logger , {
147
+ options : {
148
+ listId : listId ,
149
+ webUrl : webUrl ,
150
+ listItemId : 1
151
+ }
152
+ } ) ) ;
153
+ } ) ;
154
+
155
+ it ( 'correctly handles API OData error' , async ( ) => {
156
+ const errorMessage = 'Something went wrong' ;
157
+
158
+ sinon . stub ( request , 'post' ) . callsFake ( async ( ) => { throw { error : { error : { message : errorMessage } } } ; } ) ;
159
+
160
+ await assert . rejects ( command . action ( logger , {
161
+ options : {
162
+ listUrl : listUrl ,
163
+ webUrl : webUrl ,
164
+ listItemId : 1
165
+ }
166
+ } ) , new CommandError ( errorMessage ) ) ;
167
+ } ) ;
168
+
169
+ it ( 'fails validation if both id and title options are not passed' , async ( ) => {
170
+ const actual = await command . validate ( { options : { webUrl : webUrl , listItemId : 1 } } , commandInfo ) ;
171
+ assert . notStrictEqual ( actual , true ) ;
172
+ } ) ;
173
+
174
+ it ( 'fails validation if the url option is not a valid SharePoint site URL' , async ( ) => {
175
+ const actual = await command . validate ( { options : { webUrl : 'foo' , listItemId : 1 , listTitle : listTitle } } , commandInfo ) ;
176
+ assert . notStrictEqual ( actual , true ) ;
177
+ } ) ;
178
+
179
+ it ( 'passes validation if the url option is a valid SharePoint site URL' , async ( ) => {
180
+ const actual = await command . validate ( { options : { webUrl : webUrl , listId : listId , listItemId : 1 } } , commandInfo ) ;
181
+ assert ( actual ) ;
182
+ } ) ;
183
+
184
+ it ( 'fails validation if the id option is not a valid GUID' , async ( ) => {
185
+ const actual = await command . validate ( { options : { webUrl : webUrl , listId : '12345' , listItemId : 1 } } , commandInfo ) ;
186
+ assert . notStrictEqual ( actual , true ) ;
187
+ } ) ;
188
+
189
+ it ( 'passes validation if the id option is a valid GUID' , async ( ) => {
190
+ const actual = await command . validate ( { options : { webUrl : webUrl , listId : listId , listItemId : 1 } } , commandInfo ) ;
191
+ assert ( actual ) ;
192
+ } ) ;
193
+
194
+ it ( 'fails validation if both id and title options are passed' , async ( ) => {
195
+ const actual = await command . validate ( { options : { webUrl : webUrl , listId : listId , listTitle : listTitle , listItemId : 1 } } , commandInfo ) ;
196
+ assert . notStrictEqual ( actual , true ) ;
197
+ } ) ;
198
+
199
+ it ( 'fails validation if id is not passed' , async ( ) => {
200
+ const actual = await command . validate ( { options : { webUrl : webUrl } } , commandInfo ) ;
201
+ assert . notStrictEqual ( actual , true ) ;
202
+ } ) ;
203
+
204
+ it ( 'fails validation if id is not a number' , async ( ) => {
205
+ const actual = await command . validate ( { options : { webUrl : webUrl , listItemId : 'abc' , listTitle : listTitle } } , commandInfo ) ;
206
+ assert . notStrictEqual ( actual , true ) ;
207
+ } ) ;
208
+ } ) ;
0 commit comments