diff --git a/src/utils/spo.spec.ts b/src/utils/spo.spec.ts index 9be48b98cf2..a2ae2f9a7a6 100644 --- a/src/utils/spo.spec.ts +++ b/src/utils/spo.spec.ts @@ -3030,6 +3030,86 @@ describe('utils/spo', () => { ); }); + it('correctly re-polls when JobFinishedObjectInfo not present when using getCopyJobResult', async () => { + const postStub = sinon.stub(request, 'post').callsFake(async (opts) => { + if (opts.url === 'https://contoso.sharepoint.com/sites/sales/_api/Site/GetCopyJobProgress') { + if (postStub.callCount < 5) { + return { + JobState: 4, + Logs: [] + }; + } + + if (postStub.callCount === 5) { + return { + JobState: 4, + Logs: [ + JSON.stringify({ + Event: 'JobStart', + JobId: 'fb4cc143-383c-4da0-bd91-02d2acbb01c7', + Time: '08/10/2024 16:30:39.004', + SiteId: '53dec431-9d4f-415b-b12b-010259d5b4e1', + WebId: 'af102f32-b389-49dc-89bf-d116a17e0aa6', + DBId: '5a926054-85d7-4cf6-85f0-c38fa01c4d39', + FarmId: '823af112-cd95-49a2-adf5-eccb09c8ba5d', + ServerId: 'a6145d7e-1b85-4124-895e-b1e618bfe5ae', + SubscriptionId: '18c58817-3bc9-489d-ac63-f7264fb357e5', + TotalRetryCount: '0', + MigrationType: 'Copy', + MigrationDirection: 'Import', + CorrelationId: 'd8f444a1-10a8-9000-862c-0bad6eff1006' + }) + ] + }; + } + + if (postStub.callCount === 6) { + return { + JobState: 0, + Logs: [] + }; + } + + return { + JobState: 0, + Logs: [ + JSON.stringify({ + Event: 'JobEnd', + JobId: 'fb4cc143-383c-4da0-bd91-02d2acbb01c7', + Time: '08/10/2024 16:30:39.008', + TotalRetryCount: '0', + MigrationType: 'Copy', + MigrationDirection: 'Import', + CorrelationId: 'd8f444a1-10a8-9000-862c-0bad6eff1006' + }), + JSON.stringify({ + Event: 'JobFinishedObjectInfo', + JobId: '6d1eda82-0d1c-41eb-ab05-1d9cd4afe786', + Time: '08/10/2024 18:59:40.145', + SourceObjectFullUrl: 'https://contoso.sharepoint.com/sites/marketing/Shared Documents/Icons/Company.png', + TargetServerUrl: 'https://contoso.sharepoint.com', + TargetSiteId: '794dada8-4389-45ce-9559-0de74bf3554a', + TargetWebId: '8de9b4d3-3c30-4fd0-a9d7-2452bd065555', + TargetListId: '44b336a5-e397-4e22-a270-c39e9069b123', + TargetObjectUniqueId: '15488d89-b82b-40be-958a-922b2ed79383', + TargetObjectSiteRelativeUrl: 'Shared Documents/Icons/Company.png', + CorrelationId: '5efd44a1-c034-9000-9692-4e1a1b3ca33b' + }) + ] + }; + } + + throw 'Invalid request: ' + opts.url; + }); + + await spo.getCopyJobResult('https://contoso.sharepoint.com/sites/sales', copyJobInfo); + + const postRequests = postStub.getCalls(); + postRequests.forEach((request) => + assert.deepStrictEqual(request.args[0].data, { copyJobInfo: copyJobInfo }) + ); + }); + it('correctly returns result when using getCopyJobResult', async () => { sinon.stub(request, 'post').callsFake(async (opts) => { if (opts.url === 'https://contoso.sharepoint.com/sites/sales/_api/Site/GetCopyJobProgress') { diff --git a/src/utils/spo.ts b/src/utils/spo.ts index 38d33c35fa5..86c7ccb05ae 100644 --- a/src/utils/spo.ts +++ b/src/utils/spo.ts @@ -2210,7 +2210,16 @@ export const spo = { } // Get the destination object information - const objectInfo = logs.find(l => l.Event === 'JobFinishedObjectInfo') as CopyJobObjectInfo; + let objectInfo = logs.find(l => l.Event === 'JobFinishedObjectInfo') as CopyJobObjectInfo; + + // In rare cases, the object info may not be available yet + if (!objectInfo) { + // By doing a final poll, we can get the object info + progress = await request.post<{ JobState: number; Logs: string[] }>(requestOptions); + const newLogs = progress.Logs?.map(l => JSON.parse(l)); + objectInfo = newLogs.find(l => l.Event === 'JobFinishedObjectInfo') as CopyJobObjectInfo; + } + return objectInfo; },