2024-02-09
(C) Questetra, Inc. (MIT License)
3
2
This item searches list items in the specified list on Microsoft Lists.
この工程は、Microsoft Lists の指定リスト内のリストアイテムを検索します。
https://support.questetra.com/bpmn-icons/service-task-microsoft-lists-listitem-search/
https://support.questetra.com/ja/bpmn-icons/service-task-microsoft-lists-listitem-search/
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAABFlJREFUWEfF
l3tsU3UUx7/nrqVlbPiAZbjhhhLCdAYXxKBolKi49VZ0+KiKYbgIoa1mwbJuREKCJurWLghlrh1O
EFgwARPjY+0GkqB/CD7+mDMb8lhSjchkKDKY69b1HtLbdbCtt/dmML1/3dyex+c8fud3SvifH9Lq
v6Fw881hXeRxgJcw406AbiHiDFmfcZaBLoDaCTigj6R8tarF8bcW26oAHz5Znd4fEd4C82tEpNNi
lJkHAfIMsuHNskBZTzIdRQAGk090rwShCqBMLY5HyzBzF0GosPrXNRKIE9lQBKgT3U4CqkFQzVJS
OAYzwWFvcm7RBLDvuX0p53qDO4ioZDxRK+kwsGV6am65Zb8lcrXMmOjqzO61BLx3PZ3HbTHw+uhM
jADwiTVLJJKaCSRMDABLBEG0NZW3xO0PA+xcvMkYmpIaTNZwt86fhQfXPAqQelv8e74Xn1V+PDYO
xpm+8ymzHUccfdEfhy15Rdd6EL2rFHnOgttQuKEY39QewO+tv8piUkQCS1eam4SYOSLC895S7Hyh
NqG5q0sha0SPnFd0/0FEMxJpxJ0frPoCwe9OaapOyW4bdpd4E8syzlj95dnRoykD1Jmq7yNBOJJI
OnteDpa+bcHJwx043fabJudRoUWrH8EOi0dRniXpfnug8mgMwOyuIqAykXTRxmLcNHMaLp7tgaAT
kJmXhdM/jQRhSQIJI/t2ZkEuthdvVgYAqu1NzvUxANF1mIgeTiRt2rgMnd+ewIlD7TBOnYxnt65A
Y+l21Uy8vPdVfLT8fWUA5q/t/orFcYBfiGjufwxw3O6vyJMBvKLrHxDdoASQNS8H4dAAhBQBxvTJ
6L8UUs2AIc0I39IaZTnmCzZ/xY1DGXCHiGBQAgj+0IljzW1Iy0hHsetFTSVYscuKPSt9mgGCRMjV
BrAcjaX1qhlQA2DmKyWoE91HibBQCUCfOgndJ7swKc2IOQ/lod3fqgqQby5AwzNbtTWhV3T7QFij
BGBIN+Kv4DnojXrc/sAcHD/UkRQg77F89F/qVx5EselXb/M7rXIP+ERXERMFtJ2CkqQlKNzwFGbc
kY29qxsQ7htQBCVmk9Vf0SwDeEweg55CfyY6CdE5EPy+E8da2lTnQHRoZc7NUnXOjJ7pU3ozLPs3
DQxfRkrT8O6n78V8y0JEwhH5ktEZdAiHwrHIovdQ1AID0YtooLcfn6zdkzTyITV5CkbfhwE8Js9U
HYVOEVFs052gh5m7DTqe/crnlRdHAMgDyVxTyJD8E7mQCCwUWf3lB+Pxjdks1PaCa0mM6koWN+4V
XR+AaNW1OBujO3TsRn9X3K28pup1IMF9PdZyMMpsAWfC9Sjpcud9wr0MjG0AsseVDeYgBHLYvnR+
qqSvul3W31OvlzIvvARQGYAC1YywfDhbQVw7LXXWrtH/AzSXIBGxx/ROhp50ZgYWALiLiPKH5kEH
g38m4McwDzaVBd7o1pox1QxoNTReucsdycEwUqG3yAAAAABJRU5ErkJggg==
{
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/Sites.ReadWrite.All offline_access',
'client_id',
'client_secret',
'access_token'
);
configs.putObject('conf_OAuth2', oauth2);
configs.put('conf_SiteUrl', siteUrl);
configs.put('conf_ListTitle', listTitle);
configs.put('conf_Filter', filter);
configs.put('conf_ColumnName1', columnName1);
configs.put('conf_ColumnName2', columnName2);
// 文字型データ項目(複数行)を準備
const idDef = engine.createDataDefinition('リストアイテム ID', 1, 'q_listitemIds', 'STRING_TEXTAREA');
const column1Def = engine.createDataDefinition('値_1', 2, 'q_columnValues1', 'STRING_TEXTAREA');
const column2Def = engine.createDataDefinition('値_2', 3, 'q_columnValues2', 'STRING_TEXTAREA');
engine.setData(idDef, '事前\n文字列');
engine.setData(column1Def, '事前\n文字列');
engine.setData(column2Def, '事前\n文字列');
configs.putObject('conf_Ids', idDef);
configs.putObject('conf_ColumnValues1', column1Def);
configs.putObject('conf_ColumnValues2', column2Def);
return {idDef, column1Def, column2Def};
};
/**
* 異常系のテスト
* @param errorMsg
*/
const assertError = (errorMsg) => {
let failed = false;
try {
main();
} catch (e) {
failed = true;
expect(e.message).toEqual(errorMsg);
}
if (!failed) {
fail('No error was thrown.');
}
};
/**
* 保存先データ項目が一つも設定されておらずエラーになる場合
*/
test('No data item to save the result', () => {
const siteUrl = 'https://test-my.sharepoint.com/personal/user_test_onmicrosoft_com';
const listTitle = 'リスト 1';
const filter = "fields/Title eq 'リストアイテムのタイトル'";
prepareConfigs(siteUrl, listTitle, filter, '', '');
configs.put('conf_Ids', '');
configs.put('conf_ColumnValues1', '');
configs.put('conf_ColumnValues2', '');
assertError('No data item to save the result.');
});
/**
* 列 1 の名前が空なのに保存先データ項目が設定されていてエラーになる場合
*/
test('ColumnName1 is empty but the data item to save the values is set', () => {
const siteUrl = 'https://test-my.sharepoint.com/personal/user_test_onmicrosoft_com';
const listTitle = 'リスト 1';
const filter = "fields/Title eq 'リストアイテムのタイトル'";
prepareConfigs(siteUrl, listTitle, filter, '', '列 2');
assertError('Name and data item for Column 1 must be specified at the same time.');
});
/**
* 列 2 の名前が空なのに保存先データ項目が設定されていてエラーになる場合
*/
test('ColumnName2 is empty but the data item to save the values is set', () => {
const siteUrl = 'https://test-my.sharepoint.com/personal/user_test_onmicrosoft_com';
const listTitle = 'リスト 1';
const filter = "fields/Title eq 'リストアイテムのタイトル'";
prepareConfigs(siteUrl, listTitle, filter, '列 1', '');
assertError('Name and data item for Column 2 must be specified at the same time.');
});
/**
* 列 1 の名前が設定されているのに保存先データ項目が設定されておらずエラーになる場合
*/
test('Data item to save the values of Column 1 is not set', () => {
const siteUrl = 'https://test-my.sharepoint.com/personal/user_test_onmicrosoft_com';
const listTitle = 'リスト 1';
const filter = "fields/Title eq 'リストアイテムのタイトル'";
prepareConfigs(siteUrl, listTitle, filter, '列 1', '列 2');
configs.put('conf_ColumnValues1', '');
assertError('Name and data item for Column 1 must be specified at the same time.');
});
/**
* 列 2 の名前が設定されているのに保存先データ項目が設定されておらずエラーになる場合
*/
test('Data item to save the values of Column 2 is not set', () => {
const siteUrl = 'https://test-my.sharepoint.com/personal/user_test_onmicrosoft_com';
const listTitle = 'リスト 1';
const filter = "fields/Title eq 'リストアイテムのタイトル'";
prepareConfigs(siteUrl, listTitle, filter, '列 1', '列 2');
configs.put('conf_ColumnValues2', '');
assertError('Name and data item for Column 2 must be specified at the same time.');
});
/**
* サイト情報取得の GET リクエストのテスト
* @param {Object} request
* @param request.url
* @param request.method
* @param request.headers
* @param siteUrl
*/
const assertGetSiteInfoRequest = ({ url, method, headers }, siteUrl) => {
const encodedUrl = encodeSharingUrl(siteUrl);
const expectedUrl = `${GRAPH_URI}shares/${encodedUrl}/site?select=id`;
expect(url).toEqual(expectedUrl);
expect(method).toEqual('GET');
expect(headers.Authorization).toEqual('Bearer access_token');
};
/**
* サイト情報取得の GET リクエストでエラー
*/
test('Fail in 1st GET request', () => {
const siteUrl = 'https://test-my.sharepoint.com/personal/user_test_onmicrosoft_com';
const listTitle = 'リスト 1';
const filter = "fields/Title eq 'リストアイテムのタイトル'";
prepareConfigs(siteUrl, listTitle, filter, '列 1', '列 2');
httpClient.setRequestHandler((request) => {
assertGetSiteInfoRequest(request, siteUrl);
return httpClient.createHttpResponse(400, 'application/json', '{}');
});
assertError('Failed to get site info. status: 400');
});
/**
* クエリパラメータのテスト用の文字列を生成する
* @param key
* @param value
* @returns {String}
*/
const generateQueryString = (key, value) => {
const encodedKey = encodeURIComponent(key);
const encodedValue = encodeURIComponent(value)
.replace(/%20/g, '+') // HttpRequestWrapper#formParam() はスペースを + に置き換える
.replace(/'/g, '%27') // encodeURIComponent() でエンコードされない文字をエンコード
.replace(/\(/g, '%28')
.replace(/\)/g, '%29');
return `${encodedKey}=${encodedValue}`;
};
/**
* 列情報取得の GET リクエストのテスト
* @param {Object} request
* @param request.url
* @param request.method
* @param request.headers
* @param siteId
* @param listTitle
*/
const assertGetColumnsRequest = ({ url, method, headers }, siteId, listTitle) => {
const expectedUrl = `${GRAPH_URI}sites/${encodeURIComponent(siteId)}/lists/${encodeURIComponent(listTitle)}/columns`
+ `?${generateQueryString('$select', 'name,text')}`;
expect(url).toEqual(expectedUrl);
expect(method).toEqual('GET');
expect(headers.Authorization).toEqual('Bearer access_token');
};
/**
* 列情報取得のの GET リクエストでエラー
*/
test('Fail in 2nd GET request', () => {
const siteUrl = 'https://test-my.sharepoint.com/personal/user_test_onmicrosoft_com';
const listTitle = 'リスト 1';
const filter = "fields/Title eq 'リストアイテムのタイトル'";
prepareConfigs(siteUrl, listTitle, filter, '列 1', '列 2');
let reqCount = 0;
const siteId = 'test-my.sharepoint.com,1234abcd-5e6f-7g8h-9i0j,1a2b3c4d-1a2b3c4d5e6f';
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertGetSiteInfoRequest(request, siteUrl);
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id":"${siteId}"}`);
}
assertGetColumnsRequest(request, siteId, listTitle);
return httpClient.createHttpResponse(400, 'application/json', '{}');
});
assertError('Failed to get columns. status: 400');
});
/**
* 列 1 に指定した名前の列が存在せずエラーになる場合
*/
test('Column 1 not found', () => {
const siteUrl = 'https://test-my.sharepoint.com/personal/user_test_onmicrosoft_com';
const listTitle = 'リスト 1';
const filter = "fields/Title eq 'リストアイテムのタイトル'";
prepareConfigs(siteUrl, listTitle, filter, '列 1', '列 2');
let reqCount = 0;
const siteId = 'test-my.sharepoint.com,1234abcd-5e6f-7g8h-9i0j,1a2b3c4d-1a2b3c4d5e6f';
const columns = [ // 列 1 は存在しない
{ name: '列 2', text: { allowMultipleLines: false } },
{ name: '列 3', text: { allowMultipleLines: false } },
];
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertGetSiteInfoRequest(request, siteUrl);
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id":"${siteId}"}`);
}
assertGetColumnsRequest(request, siteId, listTitle);
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify({ value: columns }));
});
assertError("Column '列 1' not found.");
});
/**
* 列 2 に指定した名前の列が存在せずエラーになる場合
*/
test('Column 2 not found', () => {
const siteUrl = 'https://test-my.sharepoint.com/personal/user_test_onmicrosoft_com';
const listTitle = 'リスト 1';
const filter = "fields/Title eq 'リストアイテムのタイトル'";
prepareConfigs(siteUrl, listTitle, filter, '列 1', '列 2');
let reqCount = 0;
const siteId = 'test-my.sharepoint.com,1234abcd-5e6f-7g8h-9i0j,1a2b3c4d-1a2b3c4d5e6f';
const columns = [ // 列 2 は存在しない
{ name: '列 1', text: { allowMultipleLines: false } },
{ name: '列 3', text: { allowMultipleLines: false } },
];
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertGetSiteInfoRequest(request, siteUrl);
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id":"${siteId}"}`);
}
assertGetColumnsRequest(request, siteId, listTitle);
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify({ value: columns }));
});
assertError("Column '列 2' not found.");
});
/**
* 列 1 に指定した名前の列が複数行のテキスト型でエラーになる場合
*/
test('Column 1 is multi-line text', () => {
const siteUrl = 'https://test-my.sharepoint.com/personal/user_test_onmicrosoft_com';
const listTitle = 'リスト 1';
const filter = "fields/Title eq 'リストアイテムのタイトル'";
prepareConfigs(siteUrl, listTitle, filter, '列 1', '列 2');
let reqCount = 0;
const siteId = 'test-my.sharepoint.com,1234abcd-5e6f-7g8h-9i0j,1a2b3c4d-1a2b3c4d5e6f';
const columns = [
{ name: '列 1', text: { allowMultipleLines: true } },
{ name: '列 2', text: { allowMultipleLines: false } },
];
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertGetSiteInfoRequest(request, siteUrl);
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id":"${siteId}"}`);
}
assertGetColumnsRequest(request, siteId, listTitle);
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify({ value: columns }));
});
assertError("'列 1' is a text column which can contain a multi-line text.");
});
/**
* 列 2 に指定した名前の列が複数行のテキスト型でエラーになる場合
*/
test('Column 2 is multi-line text', () => {
const siteUrl = 'https://test-my.sharepoint.com/personal/user_test_onmicrosoft_com';
const listTitle = 'リスト 1';
const filter = "fields/Title eq 'リストアイテムのタイトル'";
prepareConfigs(siteUrl, listTitle, filter, '列 1', '列 2');
let reqCount = 0;
const siteId = 'test-my.sharepoint.com,1234abcd-5e6f-7g8h-9i0j,1a2b3c4d-1a2b3c4d5e6f';
const columns = [
{ name: '列 1', text: { allowMultipleLines: false } },
{ name: '列 2', text: { allowMultipleLines: true } },
];
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertGetSiteInfoRequest(request, siteUrl);
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id":"${siteId}"}`);
}
assertGetColumnsRequest(request, siteId, listTitle);
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify({ value: columns }));
});
assertError("'列 2' is a text column which can contain a multi-line text.");
});
/**
* リストアイテム取得の GET リクエストのテスト
* @param {Object} request
* @param request.url
* @param request.method
* @param request.headers
* @param siteId
* @param listTitle
* @param filter
* @param columnNames
*/
const assertGetListItemsRequest = ({ url, method, headers }, siteId, listTitle, filter, columnNames) => {
let expectedUrl = `${GRAPH_URI}sites/${encodeURIComponent(siteId)}/lists/${encodeURIComponent(listTitle)}/items`
+ `?${generateQueryString('$select', 'id')}`
+ `&${generateQueryString('$top', MAX_PAGE_SIZE)}`
+ `&${generateQueryString('$filter', filter)}`;
if (columnNames.length > 0) {
const expand = `fields($select=${columnNames.join(',')})`;
expectedUrl += `&${generateQueryString('$expand', expand)}`;
}
expect(url).toEqual(expectedUrl);
expect(method).toEqual('GET');
expect(headers.Prefer).toEqual('HonorNonIndexedQueriesWarningMayFailRandomly');
expect(headers.Authorization).toEqual('Bearer access_token');
};
/**
* リストアイテム取得のの GET リクエストでエラー
*/
test('Fail in 3rd GET request', () => {
const siteUrl = 'https://test-my.sharepoint.com/personal/user_test_onmicrosoft_com';
const listTitle = 'リスト 1';
const filter = "fields/Title eq 'リストアイテムのタイトル'";
prepareConfigs(siteUrl, listTitle, filter, '列 1', '列 2');
let reqCount = 0;
const siteId = 'test-my.sharepoint.com,1234abcd-5e6f-7g8h-9i0j,1a2b3c4d-1a2b3c4d5e6f';
const columns = [
{ name: '列 1', text: { allowMultipleLines: false } },
{ name: '列 2', text: { allowMultipleLines: false } },
];
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertGetSiteInfoRequest(request, siteUrl);
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id":"${siteId}"}`);
}
if (reqCount === 1) {
assertGetColumnsRequest(request, siteId, listTitle);
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify({ value: columns }));
}
assertGetListItemsRequest(request, siteId, listTitle, filter, ['列 1', '列 2']);
return httpClient.createHttpResponse(400, 'application/json', '{}');
});
assertError('Failed to get list items. status: 400');
});
/**
* すべての API リクエストに成功する場合のリクエストハンドラを準備
* @param siteUrl
* @param siteId
* @param listTitle
* @param filter
* @param columnNames
* @param columns
* @param listItems
*/
const prepareRequestHandler = (siteUrl, siteId, listTitle, filter, columnNames, columns, listItems) => {
let reqCount = 0;
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertGetSiteInfoRequest(request, siteUrl);
reqCount++;
if (columnNames.length === 0) { // 列情報取得のリクエストが不要な場合、リクエストを 1 つ飛ばす
reqCount++;
}
return httpClient.createHttpResponse(200, 'application/json', `{"id":"${siteId}"}`);
}
if (reqCount === 1) {
assertGetColumnsRequest(request, siteId, listTitle);
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify({ value: columns }));
}
assertGetListItemsRequest(request, siteId, listTitle, filter, columnNames);
return httpClient
.createHttpResponse(200, 'application/json', JSON.stringify({ value: listItems }));
});
};
/**
* 検索結果が 0 件でエラーになる場合
*/
test('No list items found', () => {
const siteUrl = 'https://test-my.sharepoint.com/personal/user_test_onmicrosoft_com';
const listTitle = 'リスト 1';
const filter = "fields/Title eq 'リストアイテムのタイトル'";
prepareConfigs(siteUrl, listTitle, filter, '列 1', '列 2');
const siteId = 'test-my.sharepoint.com,1234abcd-5e6f-7g8h-9i0j,1a2b3c4d-1a2b3c4d5e6f';
const columnNames = ['列 1', '列 2'];
const columns = [
{ name: '列 1', text: { allowMultipleLines: false } },
{ name: '列 2' },
];
prepareRequestHandler(siteUrl, siteId, listTitle, filter, columnNames, columns, []);
assertError('No list items found.');
});
/**
* リストアイテム検索結果を準備
* @param num 検索結果の個数
* @param columnNames 検索結果に含まれる列の名前
* @param types 検索結果の列の型(String, Number, Boolean, Object, Array のいずれか)
* @returns {Array