Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion server/app/db/version.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version": "2026-0227-091935" }
{"version": "2026-0302-111635" }
126 changes: 126 additions & 0 deletions test/cypress/e2e/jobExecute.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/**
* ジョブ実行テスト
*/
describe("jobExecute", ()=>{
const TYPE_INPUT = "input";
const TYPE_OUTPUT = "output";
const DEF_COMPONENT_TASK = "task";
const DEF_COMPONENT_FOREACH = "foreach";
const DEF_COMPONENT_WHILE = "while";
const DEF_COMPONENT_WORKFLOW = "workflow";
const TASK_NAME_0 = "task0";
const TASK_NAME_1 = "task1";

const FOREACH_NAME_0 = "foreach0";
const WORKFLOW_NAME_0 = "workflow0";
const WHILE_NAME_0 = "while0";
const LOCAL_HOST = "localhost";
const HOST_NAME = "wheel_release_test_server";
const FILE_NAME_TASK1 = "task1.sh";
const FILE_NAME_TASK2 = "task2.sh";
const FILE_NAME_WHILE = "while.sh";

const codeTask1 = `echo "test" > message.txt`;
const codeTask2 = `cat message.txt >/dev/null 2>&1`;
const codeWhile = [`set -eu`, `cnt=$(cat counter.txt)`, `if [ "$cnt" -lt 10 ]; then`, ` exit 0`, `else`, ` exit 1`].join("\n");

before(()=>{
return cy.removeAllProjects();
});

beforeEach(()=>{
cy.viewport("macbook-16");
return cy.createAndOpenProject();
});

after(()=>{
return cy.removeAllProjects();
});

/**
* localhostでのタスク実行
* 試験確認内容:ローカルホストに対するタスク実行ワークフローが
* 完了(status:finished)となること
*/
it("executeLocalhost", ()=>{
//workflow作成
cy.createComponent(DEF_COMPONENT_WORKFLOW, WORKFLOW_NAME_0, 501, 500);
//while 作成
cy.createComponent(DEF_COMPONENT_WHILE, WHILE_NAME_0, 501, 700);
cy.setupWhileWithScriptAndCondition(FILE_NAME_WHILE, codeWhile);
cy.closeProperty();
//コンポーネント同士を接続
cy.connectComponentMultiple(WORKFLOW_NAME_0, WHILE_NAME_0);
//workflow選択
cy.doubleClickComponentName(WORKFLOW_NAME_0);

//foreach作成
cy.createComponent(DEF_COMPONENT_FOREACH, FOREACH_NAME_0, 501, 500);
cy.setForeachLoop(2);
cy.closeProperty();
//foreach選択
cy.doubleClickComponentName(FOREACH_NAME_0);
//task 1つ目
cy.createComponent(DEF_COMPONENT_TASK, TASK_NAME_0, 501, 500);
cy.setupTaskWithScriptAndIO(FILE_NAME_TASK1, codeTask1, TYPE_OUTPUT, "message.txt", LOCAL_HOST);
cy.closeProperty();
//task 2つ目
cy.createComponent(DEF_COMPONENT_TASK, TASK_NAME_1, 501, 700);
cy.setupTaskWithScriptAndIO(FILE_NAME_TASK2, codeTask2, TYPE_INPUT, "message.txt", LOCAL_HOST);
cy.closeProperty();
//コンポーネント同士を接続
cy.connectComponentMultiple(TASK_NAME_0, TASK_NAME_1);

//タスク実行
cy.get("[data-cy=\"workflow-play-btn\"]", { timeout: 3000 }).click();

//完了まで待機
cy.checkProjectStatus("finished");
});

/**
* remoteHostでのタスク実行
* 試験確認内容:リモートホストに対するタスク実行ワークフローが
* 完了(status:finished)となること
*/
it("executeRemoteHost", ()=>{
//workflow作成
cy.createComponent(DEF_COMPONENT_WORKFLOW, WORKFLOW_NAME_0, 501, 500);
//while 作成
cy.createComponent(DEF_COMPONENT_WHILE, WHILE_NAME_0, 501, 700);
cy.setupWhileWithScriptAndCondition(FILE_NAME_WHILE, codeWhile);
cy.closeProperty();
//コンポーネント同士を接続
cy.connectComponentMultiple(WORKFLOW_NAME_0, WHILE_NAME_0);
//workflow選択
cy.doubleClickComponentName(WORKFLOW_NAME_0);
//foreach作成
cy.createComponent(DEF_COMPONENT_FOREACH, FOREACH_NAME_0, 501, 500);
cy.setForeachLoop(2);
cy.closeProperty();
//foreach選択
cy.doubleClickComponentName(FOREACH_NAME_0);
//task 1つ目
cy.createComponent(DEF_COMPONENT_TASK, TASK_NAME_0, 501, 500);
cy.setupTaskWithScriptAndIO(FILE_NAME_TASK1, codeTask1, TYPE_OUTPUT, "message.txt", HOST_NAME);
cy.switchUseJobScheduler("on");
cy.closeProperty();
//task 2つ目
cy.createComponent(DEF_COMPONENT_TASK, TASK_NAME_1, 501, 700);
cy.setupTaskWithScriptAndIO(FILE_NAME_TASK2, codeTask2, TYPE_INPUT, "message.txt", HOST_NAME);
cy.switchUseJobScheduler("on");
cy.closeProperty();
//コンポーネント同士を接続
cy.connectComponentMultiple(TASK_NAME_0, TASK_NAME_1);

//タスク実行
cy.get("[data-cy=\"workflow-play-btn\"]", { timeout: 3000 }).click();

//リモートアクセスパスワード
cy.get("[data-cy=\"buttons-ok-btn\"]", { timeout: 3000 });
cy.passwordType("passw0rd");

//完了まで待機
cy.checkProjectStatus("finished");
});
});
101 changes: 101 additions & 0 deletions test/cypress/support/commands-jobExecute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/**
* 正規表現で使えるようにメタ文字をエスケープする
* @param {string} s - 対象文字列
* @returns {string} エスケープ済み文字列
*/
function escapeRegExp(s) {
return String(s).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

/**
* whileにスクリプトファイルを作成 Conditionにセット
*/
Cypress.Commands.add("setupWhileWithScriptAndCondition", (scriptName, shellText)=>{
const scriptEle = "[data-cy=\"component_property-condition_use_javascript-autocomplete\"]";
//シェル作成
cy.scriptMake(scriptName, shellText);
//Conditionをクリック
cy.get("[data-cy=\"component_property-condition-setting_title\"]").click();
//Conditionにセット
cy.selectValueFromDropdownList(scriptEle, 3, scriptName);
//保存確認
cy.waitForSnackbar(new RegExp(`${escapeRegExp(scriptName)}\\s+saved\\s*$`, "i"));
});

/**
* taskにスクリプトファイルを作成 i/oファイルにセット
*/
Cypress.Commands.add("setupTaskWithScriptAndIO", (scriptName, shellText, inputType, ioFileName, target)=>{
const scriptEle = "[data-cy=\"component_property-script-autocomplete\"]";
const hostEle = "[data-cy=\"component_property-host-select\"]";

//シェル作成
cy.scriptMake(scriptName, shellText);

//script でシェル選択
cy.selectValueFromDropdownList(scriptEle, 3, scriptName);

//ローカルホスト選択
cy.selectValueFromDropdownList(hostEle, 3, target);

//インプットファイル指定
cy.enterInputOrOutputFile(inputType, ioFileName, true, true);

//保存確認
cy.waitForSnackbar(new RegExp(`${escapeRegExp(scriptName)}\\s+saved\\s*$`, "i"));
});

/**
* ファイル保存待機
*/
Cypress.Commands.add("waitForSnackbar", (messageRe, options = {})=>{
const timeout = options.timeout ?? 15000;
return cy
.contains("div.v-snackbar__content", messageRe, { timeout })
.should("be.visible");
});

/**
* foreach 繰り返し設定
*/
Cypress.Commands.add("setForeachLoop", (length)=>{
cy.get("[data-cy=\"component_property-loop_set_foreach-panel_title\"]").scrollIntoView()
.click();

for (let index = 0; index < length; index++) {
cy.get("[data-cy=\"component_property-index_foreach-list_form\"]").find("input")
.type(index);
cy.get("[data-cy=\"list_form-add-text_field\"]").find("[role=\"button\"]")
.eq(1)
.click();
}
});

/**
* テストで使用するremotehost情報の設定
*/
Cypress.Commands.add("setupRemotehost", (label, hostName)=>{
const PORT_NUMBER = 22;
const TEST_USER = "testuser";

cy.get("[data-cy=\"tool_bar-navi-icon\"]").click();
cy.get("[data-cy=\"navigation-manage_remote_host-btn\"]").click();
cy.get("[data-cy=\"remotehost-new_remote_host_setting-btn\"]").click();
cy.get("[data-cy=\"add_new_host-label-text_field\"]").type(label);
cy.get("[data-cy=\"add_new_host-hostname-text_field\"]").type(hostName);
cy.get("[data-cy=\"add_new_host-port_number_label-text_field\"]").type(`{selectall}{backspace}${PORT_NUMBER}`);
cy.get("[data-cy=\"add_new_host-user_id-text_field\"]").type(TEST_USER);
//Click on dialog title to trigger blur from all fields
cy.get("[data-cy=\"add_new_host-add_new_host-card_title\"]").click();
//Wait for OK button to be enabled
cy.get("[data-cy=\"add_new_host-ok-btn\"]", { timeout: 1000 }).should("not.be.disabled")
.click();
cy.contains("tr", label).find("[data-cy=\"action_row-edit-btn\"]")
.click();
cy.get("[data-cy=\"add_new_host-add_new_host-card_title\"]").should("be.visible");
//ダイアログ内のテキスト確認
cy.get("[data-cy=\"add_new_host-label-text_field\"]").find("input")
.should("have.value", label);
//ダイアログ内のOKボタン
cy.get("[data-cy=\"add_new_host-ok-btn\"]").click();
});
10 changes: 5 additions & 5 deletions test/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ Cypress.Commands.add("swicthUseJavascriptExpressionForConditionCheck", (flg)=>{

//open file editer
Cypress.Commands.add("clickFileEditer", ()=>{
cy.get("[href=\"/editor\"]").click()
cy.get("[data-cy=\"file_browser-edit_files-btn\"]").click()
.wait(animationWaitTime);
});

Expand All @@ -488,9 +488,9 @@ Cypress.Commands.add("scriptEdit", (scriptName, script)=>{
cy.clickFileEditer();
cy.get("#editor").find("textarea")
.type(script, { force: true });
cy.get("button").contains("button", "save all files")
.click();
cy.get("[href=\"/graph\"]", { timeout: 5500 }).click()
cy.get("[data-cy=\"workflow-text_editor_close-btn\"]").click();
cy.get("button").contains(/^keep changes$/i)
.click()
.wait(animationWaitTime);
});

Expand Down Expand Up @@ -562,7 +562,7 @@ Cypress.Commands.add("resetProject", ()=>{

//input remotehost password
Cypress.Commands.add("passwordType", (password)=>{
cy.contains("input password or passphrase").parent()
cy.contains("input password for").parent()
.parent()
.next()
.find("input")
Expand Down
1 change: 1 addition & 0 deletions test/cypress/support/e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import "./commands-home";
import "./commands-remoteHost";
import "./commands-workFlow";
import "./commands-shortcut";
import "./commands-jobExecute";
import "cypress-real-events";

//Alternatively you can use CommonJS syntax:
Expand Down
59 changes: 58 additions & 1 deletion test/wheel_config/remotehost.json
Original file line number Diff line number Diff line change
@@ -1 +1,58 @@
[]
[
{
"name": "componentTestLabel",
"host": "TestHostname",
"port": 8000,
"user": "testUser",
"numJob": 5,
"jobScheduler": "PBSPro",
"useBulkjob": true,
"useStepjob": true,
"queue": "testQueues",
"sharedHost": "",
"sharedPath": "",
"renewInterval": 0,
"statusCheckInterval": 60,
"maxStatusCheckError": 10,
"rcfile": "/etc/profile",
"useGfarm": true,
"id": "545dd3e0-b2;6d-11f0-bbe8-272d67e9e112"
},
{
"name": "testServer",
"host": "wheel_release_test_server",
"port": 8000,
"numJob": 5,
"queue": "workq",
"jobScheduler": "PBSPro",
"useBulkjob": false,
"useStepjob": false,
"sharedHost": "",
"sharedPath": "",
"renewInterval": 0,
"statusCheckInterval": 60,
"maxStatusCheckError": 10,
"id": "91041660-c8a4-11ee-8b76-87edc1fbf31a",
"user": "testuser",
"rcfile": "/etc/profile",
"prependCmd": ""
},
{
"name": "wheel_release_test_server",
"host": "wheel_release_test_server",
"port": 22,
"user": "testuser",
"id": "dd453fa0-0bc2-11f1-aec1-1f504ee4905a",
"numJob": 5,
"useBulkjob": false,
"useStepjob": false,
"sharedHost": "",
"sharedPath": "",
"renewInterval": 0,
"statusCheckInterval": 60,
"maxStatusCheckError": 10,
"rcfile": "/etc/profile",
"useGfarm": false,
"jobScheduler": "PBSPro"
}
]