3
2
2024-02-27
(C) Questetra, Inc. (MIT License)
This item uploads media files to WordPress.com.
この工程は、WordPress.com 上にメディアファイルをアップロードします。
https://support.questetra.com/bpmn-icons/service-task-wordpress-media-upload/
https://support.questetra.com/ja/bpmn-icons/service-task-wordpress-media-upload/
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
{
const oauth2 = httpClient.createAuthSettingOAuth2(
'WordPress.com',
'https://public-api.wordpress.com/oauth2/authorize',
'https://public-api.wordpress.com/oauth2/token',
'posts',
'client_id',
'client_secret',
'access_token'
);
configs.putObject('conf_Auth', oauth2);
configs.put('conf_Domain', domain);
setDataItem('Files', 1, 'FILE', files);
const idDef = setDataItem('Ids', 2, 'STRING_TEXTAREA', '事前文字列');
const urlDef = setDataItem('Urls', 3, 'STRING_TEXTAREA', '事前文字列');
return { idDef, urlDef };
};
/**
* データ項目を作成し、config にセットする
* @param name config 名の conf_ 以降
* @param index
* @param type
* @param value
* @param dataDef
*/
const setDataItem = (name, index, type, value) => {
const dataDef = engine.createDataDefinition(name, index, `q_${name}`, type);
engine.setData(dataDef, value);
configs.putObject(`conf_${name}`, dataDef);
return dataDef;
};
/**
* 異常系のテスト
* @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('Succeed - no files to upload', () => {
const {idDef, urlDef} = prepareConfigs('test1.example.com', null);
expect(main()).toEqual(undefined);
expect(engine.findData(idDef)).toEqual('');
expect(engine.findData(urlDef)).toEqual('');
});
/**
* 指定サイズのファイルを作成
* @param name
* @param contentType
* @param size
* @return qfile
*/
const createQfile = (name, contentType, size) => {
let text = '';
if (size >= 4000) {
text = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'.repeat(100); // 40 * 100 = 4000
}
while (text.length < size) {
if (text.length !== 0 && text.length * 2 <= size) {
text += text;
} else if (text.length + 1000 <= size) {
text += 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'.repeat(25); // 40 * 25 = 1000
} else {
text += 'a';
}
}
return engine.createQfile(name, contentType, text);
};
/**
* 複数のファイルが指定されているが、メディア ID を保存するデータ項目が単一行の場合
*/
test('Multiple files are set while the data item to save Media IDs is Single-line', () => {
const files = [
createQfile('file1.txt', 'text/plain', 100),
createQfile('file2.txt', 'text/plain', 200),
createQfile('file3.txt', 'text/plain', 300)
];
prepareConfigs('test1.example.com', files);
setDataItem('Ids', 4, 'STRING_TEXTFIELD', '事前文字列');
assertError('Multiple files are set while the data item to save Media IDs is Single-line.');
});
/**
* 複数のファイルが指定されているが、メディア URL を保存するデータ項目が単一行の場合
*/
test('Multiple files are set while the data item to save Media URLs is Single-line', () => {
const files = [
createQfile('file1.txt', 'text/plain', 100),
createQfile('file2.txt', 'text/plain', 200),
createQfile('file3.txt', 'text/plain', 300)
];
prepareConfigs('test1.example.com', files);
setDataItem('Urls', 4, 'STRING_TEXTFIELD', '事前文字列');
assertError('Multiple files are set while the data item to save Media URLs is Single-line.');
});
/**
* メディアアップロードの POST リクエストのテスト
* @param {Object} request
* @param request.url
* @param request.method
* @param request.headers
* @param request.contentType
* @param domain
*/
const assertRequest = ({ url, method, headers, contentType}, domain) => {
const expectedUrl = `https://public-api.wordpress.com/rest/${API_VERSION}/sites/${encodeURIComponent(domain)}/media/new`
+ `?fields=${encodeURIComponent('ID,URL')}`;
expect(url).toEqual(expectedUrl);
expect(method).toEqual('POST');
expect(headers['Authorization']).toEqual('Bearer access_token');
expect(contentType).startsWith('multipart/form-data');
// body 部のテストは省略
};
/**
* メディアアップロードの POST リクエストでエラー
*/
test('Fail in POST request', () => {
const files = [
createQfile('file1.txt', 'text/plain', 100),
createQfile('file2.txt', 'text/plain', 200),
createQfile('file3.txt', 'text/plain', 300)
];
prepareConfigs('test1.example.com', files);
httpClient.setRequestHandler((request) => {
assertRequest(request, 'test1.example.com');
return httpClient.createHttpResponse(400, 'application/json', '{}');
});
assertError('Failed to upload media. status: 400');
});
/**
* POST リクエストの 200 レスポンスを準備
* @param ids アップロードに成功したメディアの ID の配列
* @param urls アップロードに成功したメディアの URL の配列
* @param errors エラーオブジェクトの配列
* @return HttpResponse
*/
const prepare200Response = (ids, urls, errors = undefined) => {
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify({
errors: errors,
media: ids.map((id, i) => ({ ID: id, URL: urls[i] }))
}));
};
/**
* メディアアップロードの POST リクエストには成功するが、
* レスポンスにエラーを含む場合
*/
test('Some files failed to be uploaded', () => {
const files = [
createQfile('file1.png', 'image/png', 100),
createQfile('file2.txt', 'text/plain', 200), // サポート外のファイル形式
createQfile('file3.jpg', 'image/jpg', 300)
];
prepareConfigs('test1.example.com', files);
const ids = [1, 2];
const urls = [
'https://test1.example.com/2024/02/file1.png',
'https://test1.example.com/2024/02/file3.jpg'
];
const errors = [
{
file: 'file2.txt',
error: 'upload_error',
message: 'Sorry, you are not allowed to upload this file type.',
}
];
httpClient.setRequestHandler((request) => {
assertRequest(request, 'test1.example.com');
return prepare200Response(ids, urls, errors);
});
assertError('Some files failed to be uploaded.');
});
/**
* 成功 - すべての項目を指定
*/
test('Succeed - with all configurations', () => {
const files = [
createQfile('file1.png', 'image/png', 100),
createQfile('file2.gif', 'image/gif', 200),
createQfile('file3.jpg', 'image/jpg', 300)
];
const {idDef, urlDef} = prepareConfigs('test1.example.com', files);
const ids = [1, 2, 3];
const urls = [
'https://test1.example.com/2024/02/file1.png',
'https://test1.example.com/2024/02/file2.gif',
'https://test1.example.com/2024/02/file3.jpg'
];
httpClient.setRequestHandler((request) => {
assertRequest(request, 'test1.example.com');
return prepare200Response(ids, urls);
});
expect(main()).toEqual(undefined);
expect(engine.findData(idDef)).toEqual(ids.join('\n'));
expect(engine.findData(urlDef)).toEqual(urls.join('\n'));
});
/**
* 成功 - アップロードファイルが 1 つで、保存先データ項目が単一行
*/
test('Succeed - only one file, save to STRING_TEXTFIELD', () => {
const files = [
createQfile('test.png', 'image/png', 100)
];
prepareConfigs('test2.example.com', files);
const idDef = setDataItem('Ids', 4, 'STRING_TEXTFIELD', '事前文字列');
const urlDef = setDataItem('Urls', 5, 'STRING_TEXTFIELD', '事前文字列');
const ids = [100];
const urls = [
'https://test2.example.com/2024/03/test.png'
];
httpClient.setRequestHandler((request) => {
assertRequest(request, 'test2.example.com');
return prepare200Response(ids, urls);
});
expect(main()).toEqual(undefined);
expect(engine.findData(idDef)).toEqual('100');
expect(engine.findData(urlDef)).toEqual('https://test2.example.com/2024/03/test.png');
});
/**
* 成功 - 保存先データ項目の指定なし
*/
test('Succeed - no data items to save the result', () => {
const files = [
createQfile('file1.png', 'image/png', 100),
createQfile('file2.gif', 'image/gif', 200),
createQfile('file3.jpg', 'image/jpg', 300)
];
const {idDef, urlDef} = prepareConfigs('test1.example.com', files);
configs.put('conf_Ids', '');
configs.put('conf_Urls', '');
const ids = [1, 2, 3];
const urls = [
'https://test1.example.com/2024/02/file1.png',
'https://test1.example.com/2024/02/file2.gif',
'https://test1.example.com/2024/02/file3.jpg'
];
httpClient.setRequestHandler((request) => {
assertRequest(request, 'test1.example.com');
return prepare200Response(ids, urls);
});
expect(main()).toEqual(undefined);
expect(engine.findData(idDef)).toEqual('事前文字列');
expect(engine.findData(urlDef)).toEqual('事前文字列');
});
]]>