Skip to content

Commit 7071913

Browse files
committed
Fixed images not loaded at continue workflow
1 parent aaed47f commit 7071913

File tree

4 files changed

+97
-31
lines changed

4 files changed

+97
-31
lines changed

src/lib/components/v2/workflow/RunWorkflowModal.svelte

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,9 @@
196196
}
197197
}
198198
199-
function resetLastTask() {
199+
async function firstTaskIndexChanged() {
200+
await loadDatasetImages();
201+
// reset last task
200202
if (
201203
lastTaskIndex !== undefined &&
202204
firstTaskIndex !== undefined &&
@@ -251,11 +253,14 @@
251253
}
252254
}
253255
256+
let datasetImagesLoading = false;
257+
254258
async function loadDatasetImages() {
255259
if (firstTaskIndex === undefined) {
256260
return;
257261
}
258262
263+
datasetImagesLoading = true;
259264
const task = workflow.task_list[firstTaskIndex];
260265
261266
const dataset = /** @type {import('fractal-components/types/api').DatasetV2} */ (
@@ -285,6 +290,7 @@
285290
if (response.ok) {
286291
imagePage = await response.json();
287292
}
293+
datasetImagesLoading = false;
288294
}
289295
290296
onMount(async () => {
@@ -391,7 +397,7 @@
391397
class="form-select"
392398
disabled={checkingConfiguration}
393399
bind:value={firstTaskIndex}
394-
on:change={resetLastTask}
400+
on:change={firstTaskIndexChanged}
395401
class:is-invalid={mode === 'continue' && firstTaskIndex === undefined}
396402
>
397403
<option value={undefined}>Select first task</option>
@@ -524,6 +530,9 @@
524530
</div>
525531
</div>
526532
{/if}
533+
{#if datasetImagesLoading}
534+
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" />
535+
{/if}
527536
</div>
528537
{/key}
529538
{#if checkingConfiguration}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { expect, test } from './workflow_fixture.js';
2+
import { waitModalClosed, waitPageLoading } from '../utils.js';
3+
import { createDataset } from './dataset_utils.js';
4+
import { createImage } from './image_utils.js';
5+
import { waitTaskSubmitted, waitTasksSuccess } from './workflow_task_utils.js';
6+
7+
test('Continue workflow displays image lists [#693]', async ({ page, workflow }) => {
8+
await page.waitForURL(workflow.url);
9+
await waitPageLoading(page);
10+
11+
let datasetName;
12+
await test.step('Create test dataset and open dataset page', async () => {
13+
const { name } = await createDataset(page, workflow.projectId);
14+
datasetName = name;
15+
await page.getByRole('link', { name: datasetName }).click();
16+
await waitPageLoading(page);
17+
});
18+
19+
await test.step('Create test image', async () => {
20+
await createImage(page, `/tmp/playwright/datasets/${datasetName}/img1`, { a1: 'v1' });
21+
});
22+
23+
await test.step('Run workflow', async () => {
24+
await page.goto(workflow.url);
25+
await waitPageLoading(page);
26+
await workflow.addTask('generic_task');
27+
await page.getByRole('button', { name: 'Run workflow' }).click();
28+
const modal = page.locator('.modal.show');
29+
await modal.waitFor();
30+
await expect(modal.getByRole('button', { name: 'Image list' })).toBeVisible();
31+
await page.getByRole('button', { name: 'Run', exact: true }).click();
32+
await page.getByRole('button', { name: 'Confirm' }).click();
33+
await waitModalClosed(page);
34+
});
35+
36+
await test.step('Wait tasks submitted', async () => {
37+
await waitTaskSubmitted(page, 1);
38+
});
39+
40+
await test.step('Wait task success', async () => {
41+
await waitTasksSuccess(page, 1);
42+
});
43+
44+
await test.step('Reload the page', async () => {
45+
await page.reload();
46+
});
47+
48+
await test.step('Open "Continue workflow" modal', async () => {
49+
await page.getByRole('button', { name: 'Continue workflow' }).click();
50+
const modal = page.locator('.modal.show');
51+
await modal.waitFor();
52+
await modal.getByRole('combobox', { name: 'First task' }).selectOption('generic_task');
53+
await expect(modal.getByRole('button', { name: 'Image list' })).toBeVisible();
54+
});
55+
});

tests/v2/image_utils.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { waitModalClosed } from '../utils';
2+
3+
/**
4+
* @param {import('@playwright/test').Page} page
5+
* @param {string} zarrUrl
6+
* @param {{[key: string]: string}} attributes
7+
* @param {{[key: string]: boolean}} types
8+
*/
9+
export async function createImage(page, zarrUrl, attributes = {}, types = {}) {
10+
const newImageBtn = page.getByRole('button', { name: 'Add an image list entry' });
11+
await newImageBtn.waitFor();
12+
await newImageBtn.click();
13+
const modal = page.locator('.modal.show');
14+
await modal.waitFor();
15+
await modal.getByRole('textbox', { name: 'Zarr URL' }).fill(zarrUrl);
16+
for (const [key, value] of Object.entries(attributes)) {
17+
await modal.getByRole('button', { name: 'Add attribute' }).click();
18+
await modal.getByPlaceholder('Key').last().fill(key);
19+
await modal.getByPlaceholder('Value').last().fill(value);
20+
}
21+
for (const [key, value] of Object.entries(types)) {
22+
await modal.getByRole('button', { name: 'Add type' }).click();
23+
await modal.getByPlaceholder('Key').last().fill(key);
24+
if (value) {
25+
await modal.getByRole('switch').last().click();
26+
}
27+
}
28+
await modal.getByRole('button', { name: 'Save' }).click();
29+
await waitModalClosed(page);
30+
}

tests/v2/run_workflow_images.spec.js

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { selectSlimSelect, waitModalClosed, waitPageLoading } from '../utils.js';
2+
import { createImage } from './image_utils.js';
23
import { expect, test } from './workflow_fixture.js';
34

45
test('View images in run workflow modal', async ({ page, workflow }) => {
@@ -113,32 +114,3 @@ test('View images in run workflow modal', async ({ page, workflow }) => {
113114
await waitModalClosed(page);
114115
});
115116
});
116-
117-
/**
118-
* @param {import('@playwright/test').Page} page
119-
* @param {string} zarrUrl
120-
* @param {{[key: string]: string}} attributes
121-
* @param {{[key: string]: boolean}} types
122-
*/
123-
async function createImage(page, zarrUrl, attributes = {}, types = {}) {
124-
const newImageBtn = page.getByRole('button', { name: 'Add an image list entry' });
125-
await newImageBtn.waitFor();
126-
await newImageBtn.click();
127-
const modal = page.locator('.modal.show');
128-
await modal.waitFor();
129-
await modal.getByRole('textbox', { name: 'Zarr URL' }).fill(zarrUrl);
130-
for (const [key, value] of Object.entries(attributes)) {
131-
await modal.getByRole('button', { name: 'Add attribute' }).click();
132-
await modal.getByPlaceholder('Key').last().fill(key);
133-
await modal.getByPlaceholder('Value').last().fill(value);
134-
}
135-
for (const [key, value] of Object.entries(types)) {
136-
await modal.getByRole('button', { name: 'Add type' }).click();
137-
await modal.getByPlaceholder('Key').last().fill(key);
138-
if (value) {
139-
await modal.getByRole('switch').last().click();
140-
}
141-
}
142-
await modal.getByRole('button', { name: 'Save' }).click();
143-
await waitModalClosed(page);
144-
}

0 commit comments

Comments
 (0)