START_EVENT 2025-11-13 (C) Questetra, Inc. (MIT License) 3 2 This item starts a process when a file has been uploaded on the specified OneDrive folder. このアイテムは、OneDrive の指定フォルダにファイルがアップロードされると、プロセスを開始します。 https://support.questetra.com/bpmn-icons/start-event-onedrive-file-uploaded/ https://support.questetra.com/ja/bpmn-icons/start-event-onedrive-file-uploaded/ iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADXUlEQVRYR8WXW0hUURSG/33GbC5e 8pJJF6nM6YKUmsFAIAZSONOM4FtqL/mQVg9GhXR5iCIiEAqF9KEMsvKpi06OZoRPGaRmVoSGU4om aqaMzeXYOLPjTJ7R41w8k8bZLwNn1r/Wt9dee+29CSQeRHR8vVEpd7vzGTAHKKXpADYDiJnTTwEY IIR0u+FuYxnmCYx6uxjfSwKotE2JbuoqB0EJALkYpwBYUNQwRHbDZtKNBtMEBVBqG0ooSAUAlcjA i81sBPSs3ZRXE0gfEECuM94mlJb+Y2CBjBJSzTbpT/jz5RdAoTU+BGjBSgSf90EeOUz6wsU+fQBW cuaLg/nLhABgbs2rV3bmQm8EtHRhTXgBPNUOV/8yCk4st42BbBu/O7wAitzGmyAoE+tlWXYUtxzN htOcj78AeqNS4aI/Q9jneH5Ng0x1DCLkMlhZFz59m0ZZ9UfPr4jBOmQkjmtWHgC5rqGIUFIXTHih QI3UzVHoH7HhsCYROzZF+JgPjNqxq/iViPgAJfQo25T3wAOg1BnvUkqP+VNGKsLQXpmF5PXCXmR1 zKJvyAqL3Yn4qHCoN0ZCHs6gvm0YxRXdS0IQQmrtTfpiD4BC2/gOANfffUbjVQ1yMtYKvnNZGJlg kZESDeVqGSy2WbzoHPdkpdtswcnKniUBAHQ7TIYMHmBywcEiEPfey0FSgsL7zWJzosc8jazdcQI7 l5tiwvIbUaowTE47UfXMjMqnX4OBTDlMhlgegC62TNmgwp0z6UhLjsaqMMbzN5f25o4x5O5bhwhF WNBZ2mdcyDn3Gu/NloB2DpOBBAToqs7GzqRIr/j7BIu+4V9I2xqN2KhwMSlGbcsgTlV9EAXgswSW Bp135pQCrV3jOJSZICowb2RjXWjtHEfh9U5/OsES+BThj8daqOQyb+q/DFuRkbImJADOmKuNg+Xt ePOZm6NgzBehv21YfzETek0iGIZgxun2OMjeEx8yACfIv/wWLR1jAq1gGwZqROePqLE/NRZjUzOo ezmE++V7ER8tbv35aFzm0o63+YALGlEorfhS0XZsSVSKysTgmANX6nr92QpbMWch7WHEncFSH8dc FiS9kPALJemVjIeQ9FL6PzIR8rWch5D0YcJDSPo0E3QQqR6nolreMoz+ACVfiTBvFfnjAAAAAElF TkSuQmCC { const oauth2 = httpClient.createAuthSettingOAuth2( 'OneDrive', 'https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize', 'https://login.microsoftonline.com/organizations/oauth2/v2.0/token', 'https://graph.microsoft.com/Files.ReadWrite.All offline_access', 'client_id', 'client_secret', 'access_token' ); configs.putObject('conf_OAuth2', oauth2); configs.put('conf_FolderUrl', folderUrl); }; /** * URL からドライブアイテムの情報を取得する GET リクエストのテスト * @param {Object} request * @param request.url * @param request.method * @param request.headers * @param category * @param limit * @param timestampLowerLimit */ const assertGetRequest = ({ url, method, headers }, sharingUrl) => { const encodedUrl = encodeSharingUrl(sharingUrl); const expectedUrl = `${GRAPH_URI}shares/${encodedUrl}/driveItem` + `?${generateQueryString('select', 'id,parentReference/driveId,folder')}`; expect(url).toEqual(expectedUrl); expect(method).toEqual('GET'); expect(headers['Authorization']).toEqual('Bearer access_token'); }; /** * ドライブアイテム取得の GET リクエストのレスポンスを準備 * @param driveId * @param id * @param childCount * @return {Object} responseObj */ const prepareDriveItemResponse = (driveId, id, childCount = undefined) => { const driveItem = { id, parentReference: { driveId } }; if (childCount !== undefined) { // フォルダの場合のみ存在するプロパティ Object.assign(driveItem, { folder: { childCount } }); } return JSON.stringify(driveItem); }; /** * ドライブアイテム一覧を取得する GET リクエストのテスト * @param {Object} request * @param request.url * @param request.method * @param request.headers * @param category * @param limit * @param timestampLowerLimit */ const assertListRequest = ({ url, method, headers }, drivePath, folderId) => { const expectedUrl = `https://graph.microsoft.com/v1.0/${drivePath}/items/${folderId}/children` + `?${generateQueryString('$top', LIMIT)}` + `&${generateQueryString('$select', 'id,createdDateTime,file,webUrl')}`; expect(url).toEqual(expectedUrl); expect(method).toEqual('GET'); expect(headers['Authorization']).toEqual('Bearer access_token'); }; /** * クエリパラメータのテスト用の文字列を生成する * @param key * @param value * @returns {String} */ const generateQueryString = (key, value) => { const encodedKey = encodeURIComponent(key); const encodedValue = encodeURIComponent(value); return `${encodedKey}=${encodedValue}`; }; /** * 返り値の file のテスト * @param file * @param id * @param timestamp * @param url */ const assertFile = (file, id, timestamp, url) => { expect(file.id).toEqual(id); expect(file.timestamp).toEqual(timestamp); expect(file.url).toEqual(url); }; /** * 正常系のテストケース */ test('Success', () => { const response = { "value": [ // 作成日順とは限らない { "id": "12345", "createdDateTime": "2012-12-12T12:00:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file1.pdf", "file" : { "mimeType": "application/pdf" } }, { "id": "23456", "createdDateTime": "2012-12-12T10:30:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file2.txt", "file" : { "mimeType": "text/plain" } }, { "id": "34567", "createdDateTime": "2012-12-25T10:00:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file3.pdf", "file" : { "mimeType": "application/pdf" } } ] }; const folderUrl = 'https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder'; prepareConfigs(folderUrl); const limit = 3; const timestampLowerLimit = dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T00:00:00+09:00'); let reqCount = 0; const driveId = 'driveId-1'; const folderId = 'folderId-1'; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertGetRequest(request, folderUrl); reqCount++; return httpClient.createHttpResponse(200, 'application/json', prepareDriveItemResponse(driveId, folderId, 3)); } assertListRequest(request, `drives/${driveId}`, folderId); return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(response)); }); const result = list(limit, timestampLowerLimit); expect(result.length).toEqual(3); // 作成日の降順で返される assertFile(result[0], '34567', dateFormatter.parse(DATETIME_FORMAT, '2012-12-25T10:00:00Z'), 'https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file3.pdf'); assertFile(result[1], '12345', dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T12:00:00Z'), 'https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file1.pdf'); assertFile(result[2], '23456', dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T10:30:00Z'), 'https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file2.txt'); }); /** * 正常系のテストケース * フォルダ URL の指定が空で、ルートフォルダが対象になる場合 */ test('Success - Root Folder', () => { const response = { "value": [ // 作成日順とは限らない { "id": "12345", "createdDateTime": "2012-12-12T12:00:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/file1.pdf", "file" : { "mimeType": "application/pdf" } }, { "id": "23456", "createdDateTime": "2012-12-12T10:30:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/file2.txt", "file" : { "mimeType": "text/plain" } }, { "id": "34567", "createdDateTime": "2012-12-25T10:00:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/file3.pdf", "file" : { "mimeType": "application/pdf" } } ] }; prepareConfigs(''); const limit = 3; const timestampLowerLimit = dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T00:00:00+09:00'); httpClient.setRequestHandler((request) => { assertListRequest(request, 'me/drive', 'root'); return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(response)); }); const result = list(limit, timestampLowerLimit); expect(result.length).toEqual(3); // 作成日の降順で返される assertFile(result[0], '34567', dateFormatter.parse(DATETIME_FORMAT, '2012-12-25T10:00:00Z'), 'https://test-my.sharepoint.com/personal/aaa/Documents/file3.pdf'); assertFile(result[1], '12345', dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T12:00:00Z'), 'https://test-my.sharepoint.com/personal/aaa/Documents/file1.pdf'); assertFile(result[2], '23456', dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T10:30:00Z'), 'https://test-my.sharepoint.com/personal/aaa/Documents/file2.txt'); }); /** * 正常系のテストケース * レスポンスにファイルでないアイテムが含まれる場合、結果から除かれる */ test('Success - response includes an item which is not a file', () => { const response = { "value": [ // 作成日順とは限らない { "id": "12345", "createdDateTime": "2022-12-12T12:00:00Z", "webUrl": "https://test-my.sharepoint.com/personal/bbb/Documents/TestFolder2/file1.pdf", "file" : { "mimeType": "application/pdf" } }, { "id": "23456", "createdDateTime": "2022-12-12T10:30:00Z", "webUrl": "https://test-my.sharepoint.com/personal/bbb/Documents/TestFolder2/Folder", "folder" : { "childCount": 0 } }, { "id": "34567", "createdDateTime": "2022-12-25T10:00:00Z", "webUrl": "https://test-my.sharepoint.com/personal/bbb/Documents/TestFolder2/file3.pdf", "file" : { "mimeType": "application/pdf" } } ] }; const folderUrl = 'https://test-my.sharepoint.com/personal/bbb/Documents/TestFolder2'; prepareConfigs(folderUrl); const limit = 3; const timestampLowerLimit = dateFormatter.parse(DATETIME_FORMAT, '2022-01-01T00:00:00+09:00'); let reqCount = 0; const driveId = 'driveId-2'; const folderId = 'folderId-2'; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertGetRequest(request, folderUrl); reqCount++; return httpClient.createHttpResponse(200, 'application/json', prepareDriveItemResponse(driveId, folderId, 3)); } assertListRequest(request, `drives/${driveId}`, folderId); return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(response)); }); const result = list(limit, timestampLowerLimit); expect(result.length).toEqual(2); // ファイル以外のアイテムは除かれる // 作成日の降順で返される assertFile(result[0], '34567', dateFormatter.parse(DATETIME_FORMAT, '2022-12-25T10:00:00Z'), 'https://test-my.sharepoint.com/personal/bbb/Documents/TestFolder2/file3.pdf'); assertFile(result[1], '12345', dateFormatter.parse(DATETIME_FORMAT, '2022-12-12T12:00:00Z'), 'https://test-my.sharepoint.com/personal/bbb/Documents/TestFolder2/file1.pdf'); }); /** * 正常系のテストケース * レスポンスに timestampLowerLimit より前に作成されたファイルが含まれる場合、結果から除かれる */ test('Success - response includes an item created before timestampLowerLimit', () => { const response = { "value": [ // 作成日順とは限らない { "id": "12345", "createdDateTime": "2012-12-11T00:00:00Z", // timestampLowerLimit より前 "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file1.pdf", "file" : { "mimeType": "application/pdf" } }, { "id": "23456", "createdDateTime": "2012-12-12T10:30:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file2.txt", "file" : { "mimeType": "text/plain" } }, { "id": "34567", "createdDateTime": "2012-12-25T10:00:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file3.pdf", "file" : { "mimeType": "application/pdf" } } ] }; const folderUrl = 'https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder'; prepareConfigs(folderUrl); const limit = 3; const timestampLowerLimit = dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T00:00:00+09:00'); let reqCount = 0; const driveId = 'driveId-3'; const folderId = 'folderId-3'; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertGetRequest(request, folderUrl); reqCount++; return httpClient.createHttpResponse(200, 'application/json', prepareDriveItemResponse(driveId, folderId, 3)); } assertListRequest(request, `drives/${driveId}`, folderId); return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(response)); }); const result = list(limit, timestampLowerLimit); expect(result.length).toEqual(2); // timestampLowerLimit より前のファイルは除かれる // 作成日の降順で返される assertFile(result[0], '34567', dateFormatter.parse(DATETIME_FORMAT, '2012-12-25T10:00:00Z'), 'https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file3.pdf'); assertFile(result[1], '23456', dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T10:30:00Z'), 'https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file2.txt'); }); /** * 正常系のテストケース * レスポンスに含まれるファイル件数が limit を超える */ test('Success - response includes more files than limit', () => { const response = { "value": [ // 作成日順とは限らない { "id": "12345", "createdDateTime": "2012-12-12T12:00:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file1.pdf", "file" : { "mimeType": "application/pdf" } }, { "id": "23456", "createdDateTime": "2012-12-12T10:30:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file2.txt", "file" : { "mimeType": "text/plain" } }, { "id": "34567", "createdDateTime": "2012-12-25T10:00:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file3.pdf", "file" : { "mimeType": "application/pdf" } }, { "id": "45678", "createdDateTime": "2012-12-30T10:00:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file4.pdf", "file" : { "mimeType": "application/pdf" } } ] }; const folderUrl = 'https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder'; prepareConfigs(folderUrl); const limit = 2; const timestampLowerLimit = dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T00:00:00+09:00'); let reqCount = 0; const driveId = 'driveId-1'; const folderId = 'folderId-1'; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertGetRequest(request, folderUrl); reqCount++; return httpClient.createHttpResponse(200, 'application/json', prepareDriveItemResponse(driveId, folderId, 3)); } assertListRequest(request, `drives/${driveId}`, folderId); return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(response)); }); const result = list(limit, timestampLowerLimit); expect(result.length).toEqual(2); // limit 件数までしか返されない // 作成日の降順で返される assertFile(result[0], '45678', dateFormatter.parse(DATETIME_FORMAT, '2012-12-30T10:00:00Z'), 'https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file4.pdf'); assertFile(result[1], '34567', dateFormatter.parse(DATETIME_FORMAT, '2012-12-25T10:00:00Z'), 'https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file3.pdf'); }); /** * 異常系のテストケース * ドライブアイテム取得の GET リクエストで 403 エラー */ test('Fail in get drive item request', () => { const folderUrl = 'https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder'; prepareConfigs(folderUrl); const limit = 3; const timestampLowerLimit = dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T00:00:00+09:00'); httpClient.setRequestHandler((request) => { assertGetRequest(request, folderUrl); return httpClient.createHttpResponse(403, 'application/json', '{}'); }); try { list(limit, timestampLowerLimit); fail(); } catch (e) { expect(e.toString()).toEqual('Failed to get drive item. status: 403'); } }); /** * 異常系のテストケース * フォルダ URL として、ファイル URL を指定した場合 */ test('Fail - specified URL is not a folder', () => { const folderUrl = 'https://test-my.sharepoint.com/personal/aaa/Documents/file.txt'; prepareConfigs(folderUrl); const limit = 3; const timestampLowerLimit = dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T00:00:00+09:00'); httpClient.setRequestHandler((request) => { assertGetRequest(request, folderUrl); return httpClient.createHttpResponse(200, 'application/json', prepareDriveItemResponse('driveId-1', 'fileId-1')); }); try { list(limit, timestampLowerLimit); fail(); } catch (e) { expect(e.toString()).toEqual('The specified URL is not a folder.'); } }); /** * 正常系のテストケース * フォルダ内のドライブアイテム一覧取得の GET リクエストで 403 エラー */ test('Fail in get children request', () => { prepareConfigs(''); const limit = 3; const timestampLowerLimit = dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T00:00:00+09:00'); httpClient.setRequestHandler((request) => { assertListRequest(request, 'me/drive', 'root'); return httpClient.createHttpResponse(403, 'application/json', '{}'); }); try { list(limit, timestampLowerLimit); fail(); } catch (e) { expect(e.toString()).toEqual('Failed to get children of the folder. status: 403'); } }); /** * 異常系のテストケース * レスポンスに次のページがあることを示すプロパティがある場合 */ test('Fail - response indicates there are more items', () => { const response = { "value": [ // 実際には 1000 件のアイテムを含むが、省略 { "id": "12345", "createdDateTime": "2012-12-12T12:00:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/file1.pdf", "file" : { "mimeType": "application/pdf" } } ], "@odata.nextLink": "https://graph.microsoft.com/v1.0/me/root/children?$top=1000&$select=id,createdDateTime,file,webUrl&$skip=1000" }; prepareConfigs(''); const limit = 3; const timestampLowerLimit = dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T00:00:00+09:00'); httpClient.setRequestHandler((request) => { assertListRequest(request, 'me/drive', 'root'); return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(response)); }); try { list(limit, timestampLowerLimit); fail(); } catch (e) { expect(e.toString()).toEqual(`More than ${LIMIT} items are in the specified folder.`); } }); /** * 正常系のテストケース * プロセス開始済みのファイルを含むレスポンス */ test('Success - response includes files that are already processed', () => { const response = { "value": [ // 作成日順とは限らない { "id": "12345", // プロセス開始済み "createdDateTime": "2012-12-12T12:00:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file1.pdf", "file" : { "mimeType": "application/pdf" } }, { "id": "23456", "createdDateTime": "2012-12-12T10:30:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file2.txt", "file" : { "mimeType": "text/plain" } }, { "id": "34567", // プロセス開始済み "createdDateTime": "2012-12-25T10:00:00Z", "webUrl": "https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file3.pdf", "file" : { "mimeType": "application/pdf" } } ] }; const folderUrl = 'https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder'; prepareConfigs(folderUrl); const limit = 3; const timestampLowerLimit = dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T00:00:00+09:00'); // engine.isProcessStarted のモック設定 engine.addProcessStartedSet('12345'); // 1 つ目のファイル ID をプロセス開始済みにセット engine.addProcessStartedSet('34567'); // 3 つ目のファイル ID をプロセス開始済みにセット let reqCount = 0; const driveId = 'driveId-1'; const folderId = 'folderId-1'; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertGetRequest(request, folderUrl); reqCount++; return httpClient.createHttpResponse(200, 'application/json', prepareDriveItemResponse(driveId, folderId, 3)); } assertListRequest(request, `drives/${driveId}`, folderId); return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(response)); }); const result = list(limit, timestampLowerLimit); expect(result.length).toEqual(1); // プロセス開始済みのファイルは除外される // プロセス未開始のファイルのみが返される assertFile(result[0], '23456', dateFormatter.parse(DATETIME_FORMAT, '2012-12-12T10:30:00Z'), 'https://test-my.sharepoint.com/personal/aaa/Documents/TestFolder/file2.txt'); }); ]]>