Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add confirmation dialog when deleting objects #5445

Merged
merged 4 commits into from Jan 25, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 8 additions & 1 deletion packages/renderer/src/lib/compose/ComposeActions.spec.ts
Expand Up @@ -18,7 +18,7 @@

import '@testing-library/jest-dom/vitest';
import { test, expect, vi, beforeEach, afterEach } from 'vitest';
import { fireEvent, render, screen } from '@testing-library/svelte';
import { fireEvent, render, screen, waitFor } from '@testing-library/svelte';
import ComposeActions from './ComposeActions.svelte';
import type { ComposeInfoUI } from './ComposeInfoUI';
import type { ContainerInfoUI } from '../container/ContainerInfoUI';
Expand All @@ -41,8 +41,10 @@ const compose: ComposeInfoUI = {

const getContributedMenusMock = vi.fn();
const updateMock = vi.fn();
const showMessageBoxMock = vi.fn();

beforeEach(() => {
(window as any).showMessageBox = showMessageBoxMock;
(window as any).startContainersByLabel = vi.fn();
(window as any).stopContainersByLabel = vi.fn();
(window as any).restartContainersByLabel = vi.fn();
Expand Down Expand Up @@ -103,13 +105,18 @@ test('Expect no error and status restarting compose', async () => {
});

test('Expect no error and status deleting compose', async () => {
// Mock the showMessageBox to return 0 (yes)
showMessageBoxMock.mockResolvedValue({ response: 0 });
deboer-tim marked this conversation as resolved.
Show resolved Hide resolved
const { component } = render(ComposeActions, { compose });
component.$on('update', updateMock);

// click on delete button
const deleteButton = screen.getByRole('button', { name: 'Delete Compose' });
await fireEvent.click(deleteButton);

// Wait for confirmation modal to disappear after clicking on delete
await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument());

expect(compose.status).toEqual('DELETING');
expect(compose.actionError).toEqual('');
expect(compose.containers[0].state).toEqual('DELETING');
Expand Down
1 change: 1 addition & 0 deletions packages/renderer/src/lib/compose/ComposeActions.svelte
Expand Up @@ -133,6 +133,7 @@ if (dropdownMenu) {

<ListItemButtonIcon
title="Delete Compose"
confirm="{true}"
onClick="{() => deleteCompose()}"
icon="{faTrash}"
detailed="{detailed}"
Expand Down
Expand Up @@ -18,16 +18,18 @@

import '@testing-library/jest-dom/vitest';
import { test, expect, vi, beforeEach, afterEach } from 'vitest';
import { fireEvent, render, screen } from '@testing-library/svelte';
import { fireEvent, render, screen, waitFor } from '@testing-library/svelte';
import ContainerActions from './ContainerActions.svelte';
import type { ContainerInfoUI } from './ContainerInfoUI';

const container: ContainerInfoUI = {} as ContainerInfoUI;

const getContributedMenusMock = vi.fn();
const updateMock = vi.fn();
const showMessageBoxMock = vi.fn();

beforeEach(() => {
(window as any).showMessageBox = showMessageBoxMock;
(window as any).startContainer = vi.fn();
(window as any).stopContainer = vi.fn();
(window as any).restartContainer = vi.fn();
Expand Down Expand Up @@ -82,13 +84,18 @@ test('Expect no error and status restarting container', async () => {
});

test('Expect no error and status deleting container', async () => {
// Mock the showMessageBox to return 0 (yes)
showMessageBoxMock.mockResolvedValue({ response: 0 });
const { component } = render(ContainerActions, { container });
component.$on('update', updateMock);

// click on delete button
const deleteButton = screen.getByRole('button', { name: 'Delete Container' });
await fireEvent.click(deleteButton);

// Wait for confirmation modal to disappear after clicking on delete
await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument());

expect(container.state).toEqual('DELETING');
expect(container.actionError).toEqual('');
expect(updateMock).toHaveBeenCalled();
Expand Down
Expand Up @@ -145,6 +145,7 @@ if (dropdownMenu) {

<ListItemButtonIcon
title="Delete Container"
confirm="{true}"
onClick="{() => deleteContainer()}"
icon="{faTrash}"
detailed="{detailed}"
Expand Down
13 changes: 9 additions & 4 deletions packages/renderer/src/lib/container/ContainerDetails.spec.ts
Expand Up @@ -17,8 +17,8 @@
***********************************************************************/

import '@testing-library/jest-dom/vitest';
import { test, expect, vi, beforeAll, beforeEach } from 'vitest';
import { fireEvent, render, screen } from '@testing-library/svelte';
import { test, expect, vi, beforeAll } from 'vitest';
import { fireEvent, render, screen, waitFor } from '@testing-library/svelte';

import ContainerDetails from './ContainerDetails.svelte';
import { get } from 'svelte/store';
Expand All @@ -31,6 +31,7 @@ import { lastPage } from '/@/stores/breadcrumb';
const listContainersMock = vi.fn();

const getContainerInspectMock = vi.fn();
const showMessageBoxMock = vi.fn();

const myContainer: ContainerInfo = {
Id: 'myContainer',
Expand Down Expand Up @@ -59,6 +60,7 @@ vi.mock('xterm', () => {
});

beforeAll(() => {
(window as any).showMessageBox = showMessageBoxMock;
(window as any).listContainers = listContainersMock;
(window as any).deleteContainer = deleteContainerMock;
(window as any).getContainerInspect = getContainerInspectMock;
Expand All @@ -75,8 +77,6 @@ beforeAll(() => {
getContributedMenusMock.mockImplementation(() => Promise.resolve([]));
});

beforeEach(() => {});

test('Expect logs when tty is not enabled', async () => {
router.goto('/');

Expand Down Expand Up @@ -137,6 +137,8 @@ test('Expect show tty if container has tty enabled', async () => {
});

test('Expect redirect to previous page if container is deleted', async () => {
// Mock the showMessageBox to return 0 (yes)
showMessageBoxMock.mockResolvedValue({ response: 0 });
router.goto('/');

getContainerInspectMock.mockResolvedValue({
Expand Down Expand Up @@ -174,6 +176,9 @@ test('Expect redirect to previous page if container is deleted', async () => {
const deleteButton = screen.getByRole('button', { name: 'Delete Container' });
await fireEvent.click(deleteButton);

// Wait for confirmation modal to disappear after clicking on delete
await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument());

// check that delete method has been called
expect(deleteContainerMock).toHaveBeenCalled();

Expand Down
Expand Up @@ -20,7 +20,7 @@

import '@testing-library/jest-dom/vitest';
import { beforeAll, test, expect, vi } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/svelte';
import { render, screen, fireEvent, waitFor } from '@testing-library/svelte';
import ContainerList from './ContainerList.svelte';
import { containersInfos } from '../../stores/containers';
import { get } from 'svelte/store';
Expand All @@ -29,6 +29,7 @@ import { providerInfos } from '../../stores/providers';
const listContainersMock = vi.fn();
const getProviderInfosMock = vi.fn();
const getContributedMenusMock = vi.fn();
const showMessageBoxMock = vi.fn();

const listPodsMock = vi.fn();

Expand All @@ -38,6 +39,7 @@ const deleteContainersByLabelMock = vi.fn();

// fake the window.events object
beforeAll(() => {
(window as any).showMessageBox = showMessageBoxMock;
const onDidUpdateProviderStatusMock = vi.fn();
(window as any).onDidUpdateProviderStatus = onDidUpdateProviderStatusMock;
onDidUpdateProviderStatusMock.mockImplementation(() => Promise.resolve());
Expand Down Expand Up @@ -77,6 +79,8 @@ test('Expect no container engines being displayed', async () => {
});

test('Delete a group of compose containers succesfully', async () => {
// Mock the showMessageBox to return 0 (yes)
showMessageBoxMock.mockResolvedValue({ response: 0 });
getProviderInfosMock.mockResolvedValue([
{
name: 'podman',
Expand Down Expand Up @@ -136,6 +140,9 @@ test('Delete a group of compose containers succesfully', async () => {
// Click on it
await fireEvent.click(deleteButton);

// Wait for confirmation modal to disappear after clicking on delete
await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument());

// wait deleteContainerMock is called
while (deleteContainersByLabelMock.mock.calls.length === 0) {
await new Promise(resolve => setTimeout(resolve, 100));
Expand Down
12 changes: 10 additions & 2 deletions packages/renderer/src/lib/deployments/DeploymentActions.spec.ts
Expand Up @@ -18,7 +18,7 @@

import '@testing-library/jest-dom/vitest';
import { test, expect, vi, beforeEach, afterEach } from 'vitest';
import { fireEvent, render, screen } from '@testing-library/svelte';
import { fireEvent, render, screen, waitFor } from '@testing-library/svelte';
import DeploymentActions from './DeploymentActions.svelte';
import type { DeploymentUI } from './DeploymentUI';

Expand All @@ -45,12 +45,20 @@ afterEach(() => {
});

test('Expect no error and status deleting deployment', async () => {
const showMessageBoxMock = vi.fn();
(window as any).showMessageBox = showMessageBoxMock;
showMessageBoxMock.mockResolvedValue({ response: 0 });

const { component } = render(DeploymentActions, { deployment });
component.$on('update', updateMock);

// click on delete button
// click on delete buttons
const deleteButton = screen.getByRole('button', { name: 'Delete Deployment' });
await fireEvent.click(deleteButton);
expect(showMessageBoxMock).toHaveBeenCalledOnce();

// Wait for confirmation modal to disappear after clicking on delete
await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument());

expect(deployment.status).toEqual('DELETING');
expect(updateMock).toHaveBeenCalled();
Expand Down
Expand Up @@ -19,6 +19,7 @@ async function deleteDeployment(): Promise<void> {

<ListItemButtonIcon
title="Delete Deployment"
confirm="{true}"
onClick="{() => deleteDeployment()}"
detailed="{detailed}"
icon="{faTrash}" />
Expand Up @@ -18,7 +18,7 @@

import '@testing-library/jest-dom/vitest';
import { test, expect, vi, beforeAll } from 'vitest';
import { fireEvent, render, screen } from '@testing-library/svelte';
import { fireEvent, render, screen, waitFor } from '@testing-library/svelte';

import DeploymentDetails from './DeploymentDetails.svelte';

Expand Down Expand Up @@ -49,6 +49,10 @@ beforeAll(() => {
});

test('Expect redirect to previous page if deployment is deleted', async () => {
const showMessageBoxMock = vi.fn();
(window as any).showMessageBox = showMessageBoxMock;
showMessageBoxMock.mockResolvedValue({ response: 0 });

const routerGotoSpy = vi.spyOn(router, 'goto');
deployments.set([deployment]);

Expand All @@ -71,6 +75,10 @@ test('Expect redirect to previous page if deployment is deleted', async () => {
// click on delete button
const deleteButton = screen.getByRole('button', { name: 'Delete Deployment' });
await fireEvent.click(deleteButton);
expect(showMessageBoxMock).toHaveBeenCalledOnce();

// Wait for confirmation modal to disappear after clicking on delete
await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument());

// check that delete method has been called
expect(kubernetesDeleteDeploymentMock).toHaveBeenCalled();
Expand Down
7 changes: 5 additions & 2 deletions packages/renderer/src/lib/dialogs/MessageBox.svelte
Expand Up @@ -139,6 +139,9 @@ function getButtonType(b: boolean): ButtonType {
<div class="fixed top-0 left-0 right-0 bottom-0 bg-black bg-opacity-60 bg-blend-multiply h-full grid z-50">
<div
class="flex flex-col place-self-center w-[550px] rounded-xl bg-charcoal-800 shadow-xl shadow-black"
role="dialog"
aria-labelledby="{title}"
aria-label="{title}"
bind:this="{messageBox}">
<div class="flex items-center justify-between pl-4 pr-3 py-3 space-x-2 text-gray-400">
{#if type === 'error'}
Expand All @@ -163,10 +166,10 @@ function getButtonType(b: boolean): ButtonType {
</div>

<div class="max-h-80 overflow-auto">
<div class="px-10 py-4 text-sm text-gray-500 leading-5">{message}</div>
<div class="px-10 py-4 text-sm text-gray-500 leading-5" aria-label="Dialog Message">{message}</div>

{#if detail}
<div class="px-10 pb-4 text-sm text-gray-500 leading-5">{detail}</div>
<div class="px-10 pb-4 text-sm text-gray-500 leading-5" aria-label="Dialog Details">{detail}</div>
{/if}
</div>

Expand Down
2 changes: 2 additions & 0 deletions packages/renderer/src/lib/image/ImageActions.spec.ts
Expand Up @@ -47,6 +47,8 @@ const fakedImage: ImageInfoUI = {
} as unknown as ImageInfoUI;

test('Expect showMessageBox to be called when error occurs', async () => {
// Mock the showMessageBox to return 0 (yes)
showMessageBoxMock.mockResolvedValue({ response: 0 });
getContributedMenusMock.mockImplementation(() => Promise.resolve([]));

render(ImageActions, {
Expand Down
1 change: 1 addition & 0 deletions packages/renderer/src/lib/image/ImageActions.svelte
Expand Up @@ -92,6 +92,7 @@ function onError(error: string): void {

<ListItemButtonIcon
title="Delete Image"
confirm="{true}"
onClick="{() => deleteImage()}"
detailed="{detailed}"
icon="{faTrash}"
Expand Down
13 changes: 12 additions & 1 deletion packages/renderer/src/lib/image/ImageDetails.spec.ts
Expand Up @@ -18,7 +18,7 @@

import '@testing-library/jest-dom/vitest';
import { describe, test, expect, vi, afterEach, beforeEach } from 'vitest';
import { fireEvent, render, screen } from '@testing-library/svelte';
import { fireEvent, render, screen, waitFor } from '@testing-library/svelte';

import ImageDetails from './ImageDetails.svelte';
import { get } from 'svelte/store';
Expand All @@ -42,6 +42,7 @@ import { viewsContributions } from '/@/stores/views';

const listImagesMock = vi.fn();
const getContributedMenusMock = vi.fn();
const showMessageBoxMock = vi.fn();

const myImage: ImageInfo = {
Id: 'myImage',
Expand All @@ -66,6 +67,7 @@ const deleteImageMock = vi.fn();
const hasAuthMock = vi.fn();

beforeEach(() => {
(window as any).showMessageBox = showMessageBoxMock;
imagesInfos.set([]);
viewsContributions.set([]);
(window as any).listImages = listImagesMock;
Expand All @@ -82,6 +84,9 @@ afterEach(() => {
});

test('Expect redirect to previous page if image is deleted', async () => {
// Mock the showMessageBox to return 0 (yes)
showMessageBoxMock.mockResolvedValue({ response: 0 });

const routerGotoSpy = vi.spyOn(router, 'goto');
listImagesMock.mockResolvedValue([myImage]);
window.dispatchEvent(new CustomEvent('extensions-already-started'));
Expand Down Expand Up @@ -112,6 +117,9 @@ test('Expect redirect to previous page if image is deleted', async () => {
const deleteButton = screen.getByRole('button', { name: 'Delete Image' });
await fireEvent.click(deleteButton);

// Wait for modal to disappear after clicking on delete
await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument());

// check that delete method has been called
expect(deleteImageMock).toHaveBeenCalled();

Expand Down Expand Up @@ -147,6 +155,9 @@ test('expect delete image called with image id when image name is <none>', async
const deleteButton = screen.getByRole('button', { name: 'Delete Image' });
await fireEvent.click(deleteButton);

// Wait for confirmation modal to disappear after clicking on delete
await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument());

// check that delete method has been called
expect(deleteImageMock).toHaveBeenCalledWith(myNoneNameImage.engineId, myNoneNameImage.Id);
});
Expand Down