From decd06666c547601c832e7533b75a05d19135ab7 Mon Sep 17 00:00:00 2001 From: Florent Benoit Date: Mon, 25 Nov 2024 14:59:23 +0100 Subject: [PATCH] feat: allow to cancel a task that is cancellable fixes https://github.com/podman-desktop/podman-desktop/issues/9092 Signed-off-by: Florent Benoit --- .../LegacyTaskManagerItem.spec.ts | 57 ++++++++++++++++++- .../task-manager/LegacyTaskManagerItem.svelte | 20 ++++++- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/packages/renderer/src/lib/task-manager/LegacyTaskManagerItem.spec.ts b/packages/renderer/src/lib/task-manager/LegacyTaskManagerItem.spec.ts index ae7101405..251640b74 100644 --- a/packages/renderer/src/lib/task-manager/LegacyTaskManagerItem.spec.ts +++ b/packages/renderer/src/lib/task-manager/LegacyTaskManagerItem.spec.ts @@ -19,7 +19,7 @@ import '@testing-library/jest-dom/vitest'; import { fireEvent, render, screen } from '@testing-library/svelte'; -import { expect, test, vi } from 'vitest'; +import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; import type { TaskInfo } from '/@api/taskInfo'; @@ -45,6 +45,16 @@ const IN_PROGRESS_TASK_2: TaskInfo = { cancellable: false, }; +const CANCELLABLE_TASK: TaskInfo = { + id: '1', + name: 'Cancellable Task 1', + state: 'running', + status: 'in-progress', + started, + cancellable: true, + cancellationTokenSourceId: 1, +}; + const CANCELED_TASK: TaskInfo = { id: '1', name: 'Canceled Task 1', @@ -55,6 +65,21 @@ const CANCELED_TASK: TaskInfo = { cancellationTokenSourceId: 1, }; +beforeAll(() => { + Object.defineProperty(global, 'window', { + value: { + cancelToken: vi.fn(), + setTimeout: vi.fn(), + clearTimeout: vi.fn(), + }, + writable: true, + }); +}); + +beforeEach(() => { + vi.resetAllMocks(); +}); + test('Expect that the action button is visible', async () => { render(LegacyTaskManagerItem, { task: IN_PROGRESS_TASK, @@ -96,3 +121,33 @@ test('Expect that the canceled state is displayed', async () => { expect(canceledTaskIcon).toBeInTheDocument(); expect(canceledTaskIcon.parentElement?.classList.contains('text-[var(--pd-status-exited)]')).toBeTruthy(); }); + +describe('Cancel button', () => { + const cancelPrefixButton = 'Cancel task'; + + test('Expect that cancel button is visible for cancellable task', async () => { + const task = CANCELLABLE_TASK; + render(LegacyTaskManagerItem, { + task, + }); + // expect the button to cancel a task is there + const canceledTaskButton = screen.getByRole('button', { name: `${cancelPrefixButton} ${task.name}` }); + expect(canceledTaskButton).toBeInTheDocument(); + + // click on it + await fireEvent.click(canceledTaskButton); + + // expect the cancelToken method has been called + expect(vi.mocked(window.cancelToken)).toHaveBeenCalledWith(CANCELLABLE_TASK.cancellationTokenSourceId); + }); + + test('Expect that cancel button is not visible if not a cancellable task', async () => { + const task = IN_PROGRESS_TASK; + render(LegacyTaskManagerItem, { + task: IN_PROGRESS_TASK, + }); + // expect the button to cancel a task is not there + const canceledTaskButton = screen.queryByRole('button', { name: `${cancelPrefixButton} ${task.name}` }); + expect(canceledTaskButton).not.toBeInTheDocument(); + }); +}); diff --git a/packages/renderer/src/lib/task-manager/LegacyTaskManagerItem.svelte b/packages/renderer/src/lib/task-manager/LegacyTaskManagerItem.svelte index 589e4e498..8b6c5e579 100644 --- a/packages/renderer/src/lib/task-manager/LegacyTaskManagerItem.svelte +++ b/packages/renderer/src/lib/task-manager/LegacyTaskManagerItem.svelte @@ -4,10 +4,11 @@ import { faClose, faInfoCircle, faSquareCheck, + faTimesCircle, faTriangleExclamation, type IconDefinition, } from '@fortawesome/free-solid-svg-icons'; -import { TableDurationColumn } from '@podman-desktop/ui-svelte'; +import { TableDurationColumn, Tooltip } from '@podman-desktop/ui-svelte'; import { onMount } from 'svelte'; import Fa from 'svelte-fa'; @@ -43,6 +44,12 @@ onMount(() => { } }); +async function cancelTask(): Promise { + if (task.cancellationTokenSourceId) { + await window.cancelToken(task.cancellationTokenSourceId); + } +} + async function closeCompleted(task: TaskInfo | NotificationTaskInfo) { // needs to delete the task from the svelte store return removeTask(task.id); @@ -56,10 +63,19 @@ async function doExecuteAction(task: TaskInfo) {
-
+
+ {#if task.state !== 'completed' && task.cancellable} +
+ + + +
+ {/if}