2026-07-31
(C) Questetra, Inc. (MIT License)
3
2
This item searches for an item (such as a file or a folder) with a specific name directly under the specified folder on Box.
The search result status is one of the following: FOUND_FILE / FOUND_FOLDER / FOUND_OTHER / NOT_FOUND
この工程は、Box の指定フォルダ直下に特定の名前の項目(ファイルやフォルダ)があるかどうか調べます。検索結果のステータスは、FOUND_FILE
/ FOUND_FOLDER / FOUND_OTHER / NOT_FOUND のいずれかです。
https://support.questetra.com/en/bpmn-icons/service-task-box-file-search/
https://support.questetra.com/ja/bpmn-icons/service-task-box-file-search/
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAD/UlEQVRYR82XbWibVRTHf/fJ2jXJ
2qSd65x11aC0YgJWZUwEWZ0D/SJaHYKKmgykbL70Bf2k4IYwZOKWOhFRMM9QZxHUjSEo+7AOlA1E
7WSRThzdqq1tWWxjm7Zrk1y5N+SlydM2XdvN50sebs5z7u+e8z/n3iu4xo9Y1Pz+3x6F5BagAYQb
oX4BSTfIUaAbIboIeY8W63dhAH+vGyZaQLYihLsox1LBiCA4OjA9CmzOZ34Af9gP8kDRE+dPo0GM
AObtR+YimBvAfzaIEC1FrXghIymDmL42KzNrgMBZE8RzC/ld1P8SE9MbyP+mEGA5V16Ykg5MX2vu
8GwAlXNBaFErW6yxFE25msgCaLXHeq9YcMWCaGE6PenqyAEI70bwRrF+lmQn2YPp3a18ZAECYVWv
rrTj0I4bqHLaeOTgn0uay/JjFQXTV5kFUB1OyK9zjYeC9ThKBeW7epYfQHfPlBZSEbBQ/nBHCmDN
zpUCkLoiUgCBcBegenzmUQDO1QaHT0dpqC3T4yd7YrzyxZB+33V/Jds3VbBmtUH/SJzmQwN07ryR
7r4p2jtTNh88uwHPdaU8uP+iVRRPEvI2pgEuADflA6wrtxV8+GPvJBcuzfDY3RXYjBzgfxNU2A0M
AW2fD1Jht/FmUzWx6STuFyyiqDYw03tnGkDmz6QioADUZO98F8HtMHh521o9lpQwNSMxvx/l9PkJ
XtpWxSaPnZFYArfDRmQ8oeFcDhvvHv+Hts5Bax2FvGJeAFUFW97q5Yc/JrWDVx9ay74n1uv3Iz+P
0fRetkIiB+uxlxj80jfFvbfatc2Jnhhb91mGPwWUA1CQgoH9dawrX0VN+zmGxxLa/qnNLj5rrtHv
ShtPf9ifWdnfB+p02X7z6zhNd5Xr8U9PRXnmo6zN7DDIM4R8DXOK8NRrHu65xY7K+QNvX2SDaxXH
Wmqpu75U+1FhVsL78qcxDjfX8ORml05BeZmN6YTUDUalQenh/RMjC4jQogwb6x189eJGKp02YpeT
2AxBWYmgLzLDwGhcw8UTaJG57AaT0xIlJGXTcTyi09HcWMml8QTVLecKAWRuGVo0IvXF1tuc7N1e
rUspnpSE+y+z4+N+/hqJ88nzNdxX58BRajAYjbPn6DB7H1/P70PTPNzRpyf8tr2WjVUleF8/bwGQ
24jU33mt2Fq2yzYaJeTVx7v/0WaktmMxoaohsyEt23pnO4oiHTcXbsfK6JoeSNKUK3oky54D0tNd
vUMp8hAhnz8/rVfpWF648vkjkEmHPqiYSxBmFCn8V3YxyUDoq1krAnWcLrZCokjU1Sy4tKtZfsJS
l9NGhGgA6QZxR8pEngExipTdYHTNt+LiNbBCTSDf7X8FbX8wYecpbwAAAABJRU5ErkJggg==
{
const oauth2 = httpClient.createAuthSettingOAuth2(
'Box',
'https://account.box.com/api/oauth2/authorize',
'https://api.box.com/oauth2/token',
'root_readonly',
'consumer_key',
'consumer_secret',
'access_token'
);
configs.putObject('conf_OAuth2', oauth2);
configs.put('conf_Name', name);
configs.putObject('conf_SearchFolder', searchFolderOnly);
// 検索対象の親フォルダの ID を保存する文字型データ項目(単数行)を準備
const parentFolderIdDef = engine.createDataDefinition('親フォルダの ID', 1, 'q_parent_folder_id', 'STRING_TEXTFIELD');
engine.setData(parentFolderIdDef, parentFolderId);
configs.putObject('conf_ParentFolderId', parentFolderIdDef);
// 検索結果のステータスを保存する文字型データ項目(単数行)を準備
const statusDef = engine.createDataDefinition('ステータス', 2, 'q_status', 'STRING_TEXTFIELD');
engine.setData(statusDef, '事前文字列');
configs.putObject('conf_Status', statusDef);
// 見つかった項目の ID を保存する文字型データ項目(単数行)を準備
const foundIdDef = engine.createDataDefinition('見つかった項目の ID', 3, 'q_found_id', 'STRING_TEXTFIELD');
engine.setData(foundIdDef, '事前文字列');
configs.putObject('conf_FoundId', foundIdDef);
// 見つかった項目の URL を保存する文字型データ項目(単数行)を準備
const foundUrlDef = engine.createDataDefinition('見つかった項目の URL', 4, 'q_found_url', 'STRING_TEXTFIELD');
engine.setData(foundUrlDef, '事前文字列');
configs.putObject('conf_FoundUrl', foundUrlDef);
return {
statusDef,
foundIdDef,
foundUrlDef
};
};
/**
* 異常系のテスト
* @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.');
}
};
/**
* 子アイテムを検索する GET リクエストのテスト
* @param {Object} request
* @param request.url
* @param request.method
* @param folderId
* @param marker
*/
const assertSearchRequest = ({ url, method }, folderId, marker = '') => {
expect(url).toEqual(`https://api.box.com/2.0/folders/${folderId}/items?fields=id%2Ctype%2Cname&limit=1000&usemarker=true&marker=${marker}`);
expect(method).toEqual('GET');
};
/**
* Name to search for が空でエラーになる場合
*/
test('Name to search for is blank', () => {
prepareConfigs('12345', '');
assertError('Name to search for is blank.');
});
/**
* C5, C6, C7 のいずれも設定されておらずエラーになる場合
*/
test('None of the data items to save the result is set', () => {
prepareConfigs('12345', 'test2');
configs.put('conf_Status', '');
configs.put('conf_FoundId', '');
configs.put('conf_FoundUrl', '');
assertError('None of the data items to save the result is set.');
});
/**
* 子アイテム検索リクエストが失敗する場合
*/
test('GET Failed', () => {
const { statusDef, foundIdDef, foundUrlDef } = prepareConfigs('12345', 'test3');
httpClient.setRequestHandler((request) => {
assertSearchRequest(request, '12345');
return httpClient.createHttpResponse(400, 'application/json', '{}');
});
assertError('Failed to search. status: 400');
// 文字型データ項目の値が変更されていないことを確認
expect(engine.findData(statusDef)).toEqual('事前文字列');
expect(engine.findData(foundIdDef)).toEqual('事前文字列');
expect(engine.findData(foundUrlDef)).toEqual('事前文字列');
});
/**
* ファイルが見つかる場合 - 親フォルダ ID 未指定(ルートフォルダ直下を検索)
*/
test('Success - Found File - Parent Folder ID is blank (search under root)', () => {
const { statusDef, foundIdDef, foundUrlDef } = prepareConfigs('', 'file1.txt');
httpClient.setRequestHandler((request) => {
assertSearchRequest(request, '0');
const responseObj = {
'entries': [
{ 'id': '11111', 'type': 'file', 'name': 'other.txt' },
{ 'id': '22222', 'type': 'file', 'name': 'file1.txt' }
]
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
main();
expect(engine.findData(statusDef)).toEqual('FOUND_FILE');
expect(engine.findData(foundIdDef)).toEqual('22222');
expect(engine.findData(foundUrlDef)).toEqual('https://app.box.com/file/22222');
});
/**
* フォルダが見つかる場合 - 親フォルダ ID を固定値で指定
*/
test('Success - Found Folder - Specify Parent Folder ID with a fixed value', () => {
const { statusDef, foundIdDef, foundUrlDef } = prepareConfigs(null, 'folder1');
configs.put('conf_ParentFolderId', '54321');
httpClient.setRequestHandler((request) => {
assertSearchRequest(request, '54321');
const responseObj = {
'entries': [
{ 'id': '33333', 'type': 'folder', 'name': 'folder1' }
]
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
main();
expect(engine.findData(statusDef)).toEqual('FOUND_FOLDER');
expect(engine.findData(foundIdDef)).toEqual('33333');
expect(engine.findData(foundUrlDef)).toEqual('https://app.box.com/folder/33333');
});
/**
* ファイルでもフォルダでもない項目が見つかる場合(FOUND_OTHER)
* 表示 URL の形式が定まらないため、見つかった項目の URL は null になる
*/
test('Success - Found Other', () => {
const { statusDef, foundIdDef, foundUrlDef } = prepareConfigs('12345', 'bookmark1');
httpClient.setRequestHandler((request) => {
assertSearchRequest(request, '12345');
const responseObj = {
'entries': [
{ 'id': '44444', 'type': 'web_link', 'name': 'bookmark1' }
]
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
main();
expect(engine.findData(statusDef)).toEqual('FOUND_OTHER');
expect(engine.findData(foundIdDef)).toEqual('44444');
expect(engine.findData(foundUrlDef)).toEqual(null);
});
/**
* 検索対象の名前が最終ページまで見つからない場合(NOT_FOUND)
*/
test('Success - Not Found', () => {
const { statusDef, foundIdDef, foundUrlDef } = prepareConfigs('12345', 'notExist');
httpClient.setRequestHandler((request) => {
assertSearchRequest(request, '12345');
const responseObj = {
'entries': [
{ 'id': '55555', 'type': 'file', 'name': 'other1.txt' }
]
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
main();
expect(engine.findData(statusDef)).toEqual('NOT_FOUND');
expect(engine.findData(foundIdDef)).toEqual(null);
expect(engine.findData(foundUrlDef)).toEqual(null);
});
/**
* ページングを行い、2 回目のリクエストで見つかる場合
*/
test('Success - Found on the 2nd page', () => {
const { statusDef, foundIdDef, foundUrlDef } = prepareConfigs('12345', 'target');
let reqCount = 0;
httpClient.setRequestHandler((request) => {
if (reqCount++ === 0) {
assertSearchRequest(request, '12345', '');
const responseObj = {
'entries': [
{ 'id': '66666', 'type': 'file', 'name': 'other2.txt' }
],
'next_marker': 'marker123'
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
}
assertSearchRequest(request, '12345', 'marker123');
const responseObj = {
'entries': [
{ 'id': '77777', 'type': 'folder', 'name': 'target' }
]
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
main();
expect(reqCount).toEqual(2);
expect(engine.findData(statusDef)).toEqual('FOUND_FOLDER');
expect(engine.findData(foundIdDef)).toEqual('77777');
expect(engine.findData(foundUrlDef)).toEqual('https://app.box.com/folder/77777');
});
/**
* リクエスト数の上限を超えてしまう場合
*/
test('Too many files and folders are in the specified folder', () => {
const { statusDef, foundIdDef, foundUrlDef } = prepareConfigs('12345', 'neverFound');
let reqCount = 0;
httpClient.setRequestHandler(() => {
const responseObj = {
'entries': [
{ 'id': `${reqCount}`, 'type': 'file', 'name': `other${reqCount}` }
],
'next_marker': `marker${reqCount}`
};
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
assertError('Too many files and folders are in the specified folder. The search could not be completed.');
// 文字型データ項目の値が変更されていないことを確認
expect(engine.findData(statusDef)).toEqual('事前文字列');
expect(engine.findData(foundIdDef)).toEqual('事前文字列');
expect(engine.findData(foundUrlDef)).toEqual('事前文字列');
});
/**
* C4(フォルダのみを検索対象にする)が有効な場合、名前が一致するファイルを無視してフォルダを見つける
*/
test('Success - Found Folder - C4 (Search only folders) is enabled', () => {
const { statusDef, foundIdDef, foundUrlDef } = prepareConfigs('12345', 'target2', true);
httpClient.setRequestHandler((request) => {
assertSearchRequest(request, '12345');
const responseObj = {
'entries': [
{ 'id': '11112', 'type': 'file', 'name': 'target2' },
{ 'id': '22223', 'type': 'folder', 'name': 'target2' }
]
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
main();
expect(engine.findData(statusDef)).toEqual('FOUND_FOLDER');
expect(engine.findData(foundIdDef)).toEqual('22223');
expect(engine.findData(foundUrlDef)).toEqual('https://app.box.com/folder/22223');
});
/**
* C4(フォルダのみを検索対象にする)が有効な場合、名前が一致するフォルダが無ければ異常終了する
* (名前が一致するファイルがあっても検索対象外のため無視される)
*/
test('C4 (Search only folders) is enabled and no matching folder is found - aborts', () => {
prepareConfigs('12345', 'notFolder', true);
httpClient.setRequestHandler((request) => {
assertSearchRequest(request, '12345');
const responseObj = {
'entries': [
{ 'id': '33334', 'type': 'file', 'name': 'notFolder' }
]
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
assertError('Folder "notFolder" was not found.');
});
/**
* C5(ステータス)のみが設定されている場合、C6(ID)・C7(URL)は保存されない
*/
test('Success - Only conf_Status data item is set', () => {
const { statusDef, foundIdDef, foundUrlDef } = prepareConfigs('12345', 'file2.txt');
configs.put('conf_FoundId', '');
configs.put('conf_FoundUrl', '');
httpClient.setRequestHandler((request) => {
assertSearchRequest(request, '12345');
const responseObj = {
'entries': [
{ 'id': '88888', 'type': 'file', 'name': 'file2.txt' }
]
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
main();
expect(engine.findData(statusDef)).toEqual('FOUND_FILE');
expect(engine.findData(foundIdDef)).toEqual('事前文字列');
expect(engine.findData(foundUrlDef)).toEqual('事前文字列');
});
/**
* C6(ID)のみが設定されている場合、C5(ステータス)・C7(URL)は保存されない
*/
test('Success - Only conf_FoundId data item is set', () => {
const { statusDef, foundIdDef, foundUrlDef } = prepareConfigs('12345', 'file3.txt');
configs.put('conf_Status', '');
configs.put('conf_FoundUrl', '');
httpClient.setRequestHandler((request) => {
assertSearchRequest(request, '12345');
const responseObj = {
'entries': [
{ 'id': '99999', 'type': 'file', 'name': 'file3.txt' }
]
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
main();
expect(engine.findData(statusDef)).toEqual('事前文字列');
expect(engine.findData(foundIdDef)).toEqual('99999');
expect(engine.findData(foundUrlDef)).toEqual('事前文字列');
});
/**
* C7(URL)のみが設定されている場合、C5(ステータス)・C6(ID)は保存されない
*/
test('Success - Only conf_FoundUrl data item is set', () => {
const { statusDef, foundIdDef, foundUrlDef } = prepareConfigs('12345', 'file4.txt');
configs.put('conf_Status', '');
configs.put('conf_FoundId', '');
httpClient.setRequestHandler((request) => {
assertSearchRequest(request, '12345');
const responseObj = {
'entries': [
{ 'id': '10101', 'type': 'file', 'name': 'file4.txt' }
]
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
main();
expect(engine.findData(statusDef)).toEqual('事前文字列');
expect(engine.findData(foundIdDef)).toEqual('事前文字列');
expect(engine.findData(foundUrlDef)).toEqual('https://app.box.com/file/10101');
});
/**
* 検索する名前と実際の項目名で大文字・小文字が異なっていても見つかる場合
*/
test('Success - Found File - Case-insensitive match', () => {
const { statusDef, foundIdDef, foundUrlDef } = prepareConfigs('12345', 'FILE5.TXT');
httpClient.setRequestHandler((request) => {
assertSearchRequest(request, '12345');
const responseObj = {
'entries': [
{ 'id': '20202', 'type': 'file', 'name': 'file5.txt' }
]
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
main();
expect(engine.findData(statusDef)).toEqual('FOUND_FILE');
expect(engine.findData(foundIdDef)).toEqual('20202');
expect(engine.findData(foundUrlDef)).toEqual('https://app.box.com/file/20202');
});
]]>