2022-08-04 (C) Questetra, Inc. (MIT License) 2 This item searches records in a Kintone App using a query. この工程は、kintone アプリから検索クエリに合致するレコードを取得します。 https://support.questetra.com/bpmn-icons/kintone-choice-download/ https://support.questetra.com/ja/bpmn-icons/kintone-choice-download/ iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAEAElEQVRYR8VXXWhTVxz/nZubNLlJ bVbd6nSDglFwKkOrY+zDdAzBB1mHDoZSX/wAqw9WnPRBNzuHMJljsuksbPPBiQ4RpThlMLGNL+Jg iiAbaARfrNqa2ObjNuQm9y/n3N7b3JvcNI6OnKfk/L9+9/f/OOcw1HmxWuMPtc1R/I3KWonwAYCl AFoBvDRh/wzAAwC3dIaBXFo9P+fvIbUW31MCyLS3zi7qcg8YthHgr9FpDoQ+j1Q4FBp88LiaTVUA o+3ztxHRYQYEawns1CEgyxj7LDx4r8/N3hXAWDTyIwFd/yWw04YBx5ti8e2VfFUEMBqddxpg66cj +KQPOhOO3d9QAZx9azq/vBYmbAzwnIPo+PR+ucMbY12lNWEB4NWukRx3KzhpVguIdFBipCo+z4LF KN6946rDC9PLChGzOywAYysj3xFDd5ml1wel52t4P1wjRNqf/VC/2QtoeZuq/NZKKPu+BZsRBiVH oH7ZjcLtvyoCYYQjTdfiu7hQAOBDJhhSEs4+967qQGD3V2D+gM0R5cYxfngvtCsXwcLNCB7sg2cR n032Vbh5HernO0DZtE3AgFw2o87kw0oASLZHOiXCr6VanshChH7qB5hLpxIhs7UD/p1fQF6y3JXy wo0Ysj1byuQ6w8bmwfgp4X00GvkFwKZSrdDR3yBF3gB0HUyxzyFSs4AkgZJPIb36GiidAgs1ij1r FYugTEqkJLWmrYwFACfCsfhmE8DNiflu2YeOnbVopfQYmF8RMsqpYI1Nxu/ECNjMlw0bTQONZ4WM Uy70ZVmIUuveqVS8t8Kx+DITQLLkYBFGnAHP4jYLEGUzyJ8/iYbOListvNhY8wQAAPrwI2gDl9Hw 6WYb5elP3oP+9IkzDc/CsXizCYCcUicAXvVULAJkqLKAIpzy9uRpEl8dmgE9MQJp1iu1AEA4Fjcq bDQaKQMQ/OGMvbh42/HgvgaD/tQYtIFLkN+OQuIseH3GvoMVvufCgA1AWQrkFe9D6f0eLBiayLHB gNmSvBVzR3rh69gAz8I3J1PlAKDF/oDauxMgvWoKyorQ4FlCoHs/fB+tnxw8stegO9gIPcnpboHZ FRycWZj6k4dQ921H8d4/zsDmf1sRlrVhqZU0ey58H3dCer0Vctu7FgtWDQjuCXpiGPn+06L98hdO uQU29yfbsNIgqmTNB45y6GdrLtgA8E68+jvUA2LCTrlsg8htFFf0InkQ2HMQvtVroQ8PQWqZK7qB j9ziv7enDCwy6xzFfNP1MHJxyScgnxPM60X+8rmaAptKZYcRF0x1HL9QhCrKrscxt6nrhcQEXdcr mQmirpfS/4OJF76WW0zU82Figqjr06y0m+r2OJ2u/nfz8xwerN4wOc7tdwAAAABJRU5ErkJggg== 10 and 数値2 > 20", "displayFields": [ "表示するフィールド1", "表示するフィールド2" ], "sort": "ソートフィールド1 desc, ソートフィールド2 asc", "size": "5" } }, "ルックアップ": { "type": "SINGLE_LINE_TEXT", "code": "ルックアップ", "label": "ルックアップ", "noLabel": true, "required": false, "lookup": { "relatedApp": { "app": "100", "code": "コピー元アプリのアプリコード" }, "relatedKeyField": "コピー元のフィールド", "fieldMappings": [ { "field": "コピー先のフィールド", "relatedField": "コピー元のフィールド" } ], "lookupPickerFields": [ "ルックアップ選択時に表示されるフィールド1" ], "filterCond": "数値 > 10 and 数値2 > 20", "sort": "ソートフィールド1 desc, ソートフィールド2 asc" } }, "グループ": { "type": "GROUP", "code": "グループ", "label": "グループ", "noLabel": true, "openGroup": true }, "テーブル": { "type": "SUBTABLE", "code": "テーブル", "label": "テーブル", "noLabel": false, "fields": { "文字列__1行_テーブル": { "type": "SINGLE_LINE_TEXT", "code": "文字列__1行_テーブル", "label": "文字列 (1行)テーブル", "noLabel": false, "required": true, "unique": false, "maxLength": "64", "minLength": "0", "defaultValue": "", "expression": "", "hideExpression": false } } }, "ステータス": { "type": "STATUS", "code": "ステータス", "label": "ステータス", "enabled": "true" }, "作業者": { "type": "STATUS_ASSIGNEE", "code": "作業者", "label": "作業者", "enabled": "true" }, "カテゴリー": { "type": "CATEGORY", "code": "カテゴリー", "label": "カテゴリー", "enabled": "true" }, "作成日時": { "type": "CREATED_TIME", "code": "作成日時", "label": "作成日時" }, "更新日時": { "type": "UPDATED_TIME", "code": "更新日時", "label": "更新日時" }, "レコード番号": { "type": "RECORD_NUMBER", "code": "レコード番号", "label": "レコード番号" } }, "revision": "2" }; /** * 設定の準備 * @param domain * @param guestSpaceId * @param appId * @param query * @param fieldCode1 * @param fieldCode2 * @return dataDefList */ const prepareConfigs = (domain, guestSpaceId, appId, query, fieldCode1, fieldCode2) => { configs.put('conf_auth', 'kintone'); configs.put('conf_domain', domain); configs.put('conf_guestSpaceId', guestSpaceId); configs.put('conf_appId', appId); configs.put('conf_query', query); configs.put('conf_idField', fieldCode1); configs.put('conf_labelField', fieldCode2); // 文字型データ項目(複数行)を準備 const recordIdDataDef = engine.createDataDefinition('レコード ID', 1, 'q_recordIds', 'STRING_TEXTAREA'); const value1DataDef = engine.createDataDefinition('値_1', 2, 'q_fieldValues1', 'STRING_TEXTAREA'); const value2DataDef = engine.createDataDefinition('値_2', 3, 'q_fieldValues2', 'STRING_TEXTAREA'); engine.setData(recordIdDataDef, '事前\n文字列'); engine.setData(value1DataDef, '事前\n文字列'); engine.setData(value2DataDef, '事前\n文字列'); configs.putObject('conf_recordIds', recordIdDataDef); configs.putObject('conf_ids', value1DataDef); configs.putObject('conf_labels', value2DataDef); return [recordIdDataDef, value1DataDef, value2DataDef]; }; /** * フィールド一覧取得の GET リクエストのテスト * @param {Object} request * @param request.url * @param request.method * @param domain * @param guestSpaceId * @param appId */ const assertCheckFieldsRequest = ({url, method}, domain, guestSpaceId, appId) => { expect(method).toEqual('GET'); if (guestSpaceId === '') { // ゲストスペース外のアプリの場合 expect(url).toEqual(`https://${domain}/k/v1/app/form/fields.json?app=${appId}`); } else { // ゲストスペース内のアプリの場合 expect(url).toEqual(`https://${domain}/k/guest/${guestSpaceId}/v1/app/form/fields.json?app=${appId}`); } }; /** * レコード取得の GET リクエストのテスト * @param {Object} request * @param request.url * @param request.method * @param domain * @param guestSpaceId * @param appId * @param query * @param fields * @param lastRecordId */ const assertGetRecordsRequest = ({url, method}, domain, guestSpaceId, appId, query, fields, lastRecordId) => { expect(method).toEqual('GET'); let expectedUrl; if (guestSpaceId === '') { // ゲストスペース外のアプリの場合 expectedUrl = `https://${domain}/k/v1/records.json?app=${appId}`; } else { // ゲストスペース内のアプリの場合 expectedUrl = `https://${domain}/k/guest/${guestSpaceId}/v1/records.json?app=${appId}`; } if (query === '') { // 検索クエリが空の場合 query = `$id > ${lastRecordId} order by $id asc limit ${LIMIT}`; } else { // 検索クエリが空でない場合 query = `( ${query} ) and $id > ${lastRecordId} order by $id asc limit ${LIMIT}`; } expectedUrl += '&query=' + encodeURIComponent(query); fields.forEach((fieldCode, i) => { expectedUrl += '&' + encodeURIComponent(`fields[${i}]`) + '=' + encodeURIComponent(fieldCode); }); expect(url).toEqual(expectedUrl.replace(/%20/g, '+').replace(/\(/g, '%28').replace(/\)/g, '%29')); }; /** * レコード取得のレスポンスを準備 * @param from レコード取得開始位置 * @param recordNum レコード数 * @param fields * @param types * @return responseObj */ const prepareGetRecordsResponse = (from, recordNum, fields, types) => { const responseObj = { "records": [] }; for (let i = from; i < from + recordNum; i++) { const record = {}; fields.forEach((fieldCode, j) => { let value; if (fieldCode === '$id') { value = `${i}`; } else { value = `${i} 番目のレコードの ${fieldCode} の値`; } record[fieldCode] = { "type": types[j], "value": value }; }); responseObj.records.push(record); } return responseObj; }; /** * ドメインが不正な文字列でエラーになる場合 */ test('Invalid Kintone domain', () => { prepareConfigs('invalidDomain', '1', '2', '$id < 10', '文字列__1行_', '数値'); expect(execute).toThrow('Invalid Kintone domain.'); }); /** * ゲストスペース ID が不正な文字列でエラーになる場合 */ test('Invalid Guest Space ID', () => { prepareConfigs('xxxxx.kintone.com', 'invalidId', '2', '$id < 10', '文字列__1行_', '数値'); expect(execute).toThrow('Invalid Guest Space ID.'); }); /** * アプリ ID が不正な文字列でエラーになる場合 */ test('Invalid App ID', () => { prepareConfigs('xxxxx.kintone.com', '1', 'invalidId', '$id < 10', '文字列__1行_', '数値'); expect(execute).toThrow('Invalid App ID.'); }); /** * 保存先データ項目が一つも設定されておらずエラーになる場合 */ test('No data item to save the result is set', () => { configs.put('conf_auth', 'kintone'); configs.put('conf_domain', 'xxxxx.kintone.com'); configs.put('conf_appId', '123'); configs.put('conf_query', '$id < 10'); configs.put('conf_idField', '文字列__1行_'); configs.put('conf_labelField', '数値'); expect(execute).toThrow('No data item to save the result is set.'); }); /** * フィールドコード_1 が空なのに値_1 の保存先データ項目が設定されていてエラーになる場合 */ test('FieldCode1 is empty but the data item to save the values is set', () => { prepareConfigs('xxxxx.kintone.com', '', '123', '$id < 10', '', '数値'); expect(execute).toThrow('Field Code 1 is empty but the data item to save the values is set.'); }); /** * フィールドコード_2 が空なのに値_2 の保存先データ項目が設定されていてエラーになる場合 */ test('FieldCode2 is empty but the data item to save the values is set', () => { prepareConfigs('xxxxx.kintone.com', '', '123', '$id < 10', '文字列__1行_', ''); expect(execute).toThrow('Field Code 2 is empty but the data item to save the values is set.'); }); /** * フィールドコード_1 が設定されているのに保存先データ項目が設定されておらずエラーになる場合 */ test('Data item to save the values of FieldCode1 is not set', () => { configs.put('conf_auth', 'kintone'); configs.put('conf_domain', 'xxxxx.kintone.com'); configs.put('conf_appId', '123'); configs.put('conf_query', '$id < 10'); configs.put('conf_idField', '文字列__1行_'); configs.put('conf_labelField', '数値'); // 文字型データ項目(複数行)を準備(値_1 を保存するデータ項目は設定しない) const recordIdDataDef = engine.createDataDefinition('レコード ID', 1, 'q_recordIds', 'STRING_TEXTAREA'); const value2DataDef = engine.createDataDefinition('値_2', 3, 'q_fieldValues2', 'STRING_TEXTAREA'); configs.putObject('conf_recordIds', recordIdDataDef); configs.putObject('conf_labels', value2DataDef); expect(execute).toThrow('Data item to save the values of Field Code 1 is not set.'); }); /** * フィールドコード_2 が設定されているのに保存先データ項目が設定されておらずエラーになる場合 */ test('Data item to save the values of FieldCode2 is not set', () => { configs.put('conf_auth', 'kintone'); configs.put('conf_domain', 'xxxxx.kintone.com'); configs.put('conf_appId', '123'); configs.put('conf_query', '$id < 10'); configs.put('conf_idField', '文字列__1行_'); configs.put('conf_labelField', '数値'); // 文字型データ項目(複数行)を準備(値_2 を保存するデータ項目は設定しない) const recordIdDataDef = engine.createDataDefinition('レコード ID', 1, 'q_recordIds', 'STRING_TEXTAREA'); const value1DataDef = engine.createDataDefinition('値_1', 2, 'q_fieldValues1', 'STRING_TEXTAREA'); configs.putObject('conf_recordIds', recordIdDataDef); configs.putObject('conf_ids', value1DataDef); expect(execute).toThrow('Data item to save the values of Field Code 2 is not set.'); }); /** * フィールド一覧取得の GET リクエストで失敗 */ test('Failed to get form fields', () => { prepareConfigs('xxxxx.kintone.com', '', '123', '$id < 10', '文字列__1行_', '数値'); httpClient.setRequestHandler((request) => { assertCheckFieldsRequest(request, 'xxxxx.kintone.com', '', '123'); return httpClient.createHttpResponse(400, 'application/json', '{}'); }); expect(execute).toThrow('Failed to get form fields. status: 400'); }); /** * フィールドコード_1 に存在しないフィールドコードを指定 */ test('FieldCode1 does not exist', () => { prepareConfigs('xxxxx.kintone.com', '', '123', '$id < 10', '存在しないフィールド1', '数値'); httpClient.setRequestHandler((request) => { assertCheckFieldsRequest(request, 'xxxxx.kintone.com', '', '123'); return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(CHECK_FIELDS_RESPONSE)); }); expect(execute).toThrow('Field Code: 存在しないフィールド1 does not exist in the app.'); }); /** * フィールドコード_2 に存在しないフィールドコードを指定 */ test('FieldCode2 does not exist', () => { prepareConfigs('xxxxx.kintone.com', '', '123', '$id < 10', '文字列__1行_', '存在しないフィールド2'); httpClient.setRequestHandler((request) => { assertCheckFieldsRequest(request, 'xxxxx.kintone.com', '', '123'); return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(CHECK_FIELDS_RESPONSE)); }); expect(execute).toThrow('Field Code: 存在しないフィールド2 does not exist in the app.'); }); /** * フィールドコード_1 にサポート外の型のフィールドコードを指定 */ test('Field Type of FieldCode1 is not supported', () => { prepareConfigs('xxxxx.kintone.com', '', '123', '$id < 10', 'ユーザー選択', '数値'); httpClient.setRequestHandler((request) => { assertCheckFieldsRequest(request, 'xxxxx.kintone.com', '', '123'); return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(CHECK_FIELDS_RESPONSE)); }); expect(execute).toThrow('Unable to save the values of ユーザー選択. Field Type USER_SELECT is not supported.'); }); /** * フィールドコード_2 にサポート外の型のフィールドコードを指定 */ test('Field Type of FieldCode2 is not supported', () => { prepareConfigs('xxxxx.kintone.com', '', '123', '$id < 10', '文字列__1行_', 'チェックボックス'); httpClient.setRequestHandler((request) => { assertCheckFieldsRequest(request, 'xxxxx.kintone.com', '', '123'); return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(CHECK_FIELDS_RESPONSE)); }); expect(execute).toThrow('Unable to save the values of チェックボックス. Field Type CHECK_BOX is not supported.'); }); /** * レコード一覧取得の GET リクエストで失敗 */ test('Failed to get records', () => { prepareConfigs('xxxxx.kintone.com', '', '123', '$id < 10', '文字列__1行_', '数値'); const fields = ['$id', '文字列__1行_', '数値']; let requestCount = 0; httpClient.setRequestHandler((request) => { if (requestCount === 0) { // フィールド一覧のリクエスト assertCheckFieldsRequest(request, 'xxxxx.kintone.com', '', '123'); requestCount++; return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(CHECK_FIELDS_RESPONSE)); } else { // レコード取得のリクエスト assertGetRecordsRequest(request, 'xxxxx.kintone.com', '', '123', '$id < 10', fields, 0); return httpClient.createHttpResponse(400, 'application/json', '{}'); } }); expect(execute).toThrow('Failed to get records. status: 400'); }); /** * 検索結果が0件 */ test('No records found', () => { prepareConfigs('xxxxx.kintone.com', '', '123', '文字列__1行_ = アイウエオ', '文字列__1行_', '数値'); const fields = ['$id', '文字列__1行_', '数値']; let requestCount = 0; httpClient.setRequestHandler((request) => { if (requestCount === 0) { // フィールド一覧のリクエスト assertCheckFieldsRequest(request, 'xxxxx.kintone.com', '', '123'); requestCount++; return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(CHECK_FIELDS_RESPONSE)); } else { // レコード取得のリクエスト assertGetRecordsRequest(request, 'xxxxx.kintone.com', '', '123', '文字列__1行_ = アイウエオ', fields, 0); return httpClient.createHttpResponse(200, 'application/json', '{ "records": [] }'); } }); expect(execute).toThrow('No records found.'); }); /** * レコード検索成功 * ゲストスペース外のアプリ * クエリ指定 * レコード500件未満(レコード取得のリクエスト1回) */ test('200 Success - without guestSpaceId, with query, less than 500 records', () => { const dataDefList = prepareConfigs('xxxxx.kintone.com', '', '123', '$id < 500 \n and 数値 > 0', '文字列__1行_', '数値'); const fields = ['$id', '文字列__1行_', '数値']; const types = ['__ID__', 'SINGLE_LINE_TEXT', 'NUMBER']; let requestCount = 0; httpClient.setRequestHandler((request) => { if (requestCount === 0) { // フィールド一覧のリクエスト assertCheckFieldsRequest(request, 'xxxxx.kintone.com', '', '123'); requestCount++; return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(CHECK_FIELDS_RESPONSE)); } else { // レコード取得のリクエスト assertGetRecordsRequest(request, 'xxxxx.kintone.com', '', '123', '$id < 500 \n and 数値 > 0', fields, 0); return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(prepareGetRecordsResponse(1, LIMIT - 1, fields, types))); } }); //