mirror of
https://github.com/podman-desktop/podman-desktop
synced 2026-04-21 17:47:22 +00:00
feat(renderer): add support for danger styling in MessageBox
Signed-off-by: Dias Tursynbayev <original.justmello1337@gmail.com>
This commit is contained in:
parent
a165724486
commit
f125bc1ef5
3 changed files with 172 additions and 3 deletions
|
|
@ -55,7 +55,7 @@ export interface MessageBoxOptions {
|
|||
*/
|
||||
buttons?: ButtonsType[];
|
||||
/**
|
||||
* The (optional) type, one of 'none' | 'info' | 'error' | 'question' | 'warning'.
|
||||
* The (optional) type, one of 'none' | 'info' | 'error' | 'question' | 'warning' | 'danger'.
|
||||
*/
|
||||
type?: string;
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -194,4 +194,169 @@ describe('MessageBox', () => {
|
|||
expect(title2).toBeInTheDocument();
|
||||
await fireEvent.click(ok2);
|
||||
});
|
||||
|
||||
test('Expect danger type to keep default button first in layout', async () => {
|
||||
const idRequest = 700;
|
||||
const messageBoxOptions: MessageBoxOptions = {
|
||||
id: idRequest,
|
||||
title: 'Danger',
|
||||
message: 'Danger Message',
|
||||
type: 'danger',
|
||||
buttons: ['Delete', 'Cancel'],
|
||||
};
|
||||
|
||||
receiveFunctionMock.mockImplementation((message: string, callback: (options: MessageBoxOptions) => void) => {
|
||||
if (message === 'showMessageBox:open') {
|
||||
callback(messageBoxOptions);
|
||||
}
|
||||
});
|
||||
|
||||
render(MessageBox, {});
|
||||
|
||||
const allButtons = screen.getAllByRole('button');
|
||||
expect(allButtons[1]).toHaveTextContent('Cancel');
|
||||
expect(allButtons[2]).toHaveTextContent('Delete');
|
||||
await fireEvent.click(screen.getByRole('button', { name: 'Cancel' }));
|
||||
expect(window.sendShowMessageBoxOnSelect).toBeCalledWith(idRequest, 1, undefined);
|
||||
});
|
||||
|
||||
test('Expect explicit default and cancel ids to be honored', async () => {
|
||||
const idRequest = 701;
|
||||
const messageBoxOptions: MessageBoxOptions = {
|
||||
id: idRequest,
|
||||
title: 'Explicit ids',
|
||||
message: 'Message',
|
||||
type: 'warning',
|
||||
buttons: ['Ignore', 'Abort'],
|
||||
cancelId: 1,
|
||||
defaultId: 1,
|
||||
};
|
||||
|
||||
receiveFunctionMock.mockImplementation((message: string, callback: (options: MessageBoxOptions) => void) => {
|
||||
if (message === 'showMessageBox:open') {
|
||||
callback(messageBoxOptions);
|
||||
}
|
||||
});
|
||||
|
||||
render(MessageBox, {});
|
||||
|
||||
const allButtons = screen.getAllByRole('button');
|
||||
expect(allButtons[1]).toHaveTextContent('Cancel');
|
||||
expect(allButtons[2]).toHaveTextContent('Ignore');
|
||||
await userEvent.keyboard('{Escape}');
|
||||
expect(window.sendShowMessageBoxOnSelect).toBeCalledWith(idRequest, 1);
|
||||
});
|
||||
|
||||
test('Expect cancel at index 0 to move default to index 1', async () => {
|
||||
const idRequest = 702;
|
||||
const messageBoxOptions: MessageBoxOptions = {
|
||||
id: idRequest,
|
||||
title: 'Cancel first',
|
||||
message: 'Message',
|
||||
buttons: ['Cancel', 'Proceed'],
|
||||
};
|
||||
|
||||
receiveFunctionMock.mockImplementation((message: string, callback: (options: MessageBoxOptions) => void) => {
|
||||
if (message === 'showMessageBox:open') {
|
||||
callback(messageBoxOptions);
|
||||
}
|
||||
});
|
||||
|
||||
render(MessageBox, {});
|
||||
|
||||
const allButtons = screen.getAllByRole('button');
|
||||
expect(allButtons[1]).toHaveTextContent('Cancel');
|
||||
expect(allButtons[2]).toHaveTextContent('Proceed');
|
||||
await fireEvent.click(screen.getByRole('button', { name: 'Proceed' }));
|
||||
expect(window.sendShowMessageBoxOnSelect).toBeCalledWith(idRequest, 1, undefined);
|
||||
});
|
||||
|
||||
test('Expect danger default button to use danger styling', async () => {
|
||||
const messageBoxOptions: MessageBoxOptions = {
|
||||
id: 703,
|
||||
title: 'Danger default',
|
||||
message: 'Message',
|
||||
type: 'danger',
|
||||
buttons: ['Cancel', 'Delete'],
|
||||
defaultId: 1,
|
||||
};
|
||||
|
||||
receiveFunctionMock.mockImplementation((message: string, callback: (options: MessageBoxOptions) => void) => {
|
||||
if (message === 'showMessageBox:open') {
|
||||
callback(messageBoxOptions);
|
||||
}
|
||||
});
|
||||
|
||||
render(MessageBox, {});
|
||||
|
||||
const deleteButton = screen.getByRole('button', { name: 'Delete' });
|
||||
expect(deleteButton.className).toContain('pd-button-danger-bg');
|
||||
});
|
||||
|
||||
test.each([
|
||||
{ id: 704, title: 'Warn', message: 'Message', type: 'warning' as const },
|
||||
{ id: 705, title: 'Info', message: 'Message', type: 'info' as const },
|
||||
{ id: 706, title: 'Question', message: 'Message', type: 'question' as const },
|
||||
])('Expect $type icon to render', async messageBoxOptions => {
|
||||
let eventCallback: ((options: MessageBoxOptions) => void) | undefined;
|
||||
receiveFunctionMock.mockImplementation((message: string, callback: (options: MessageBoxOptions) => void) => {
|
||||
if (message === 'showMessageBox:open') {
|
||||
eventCallback = callback;
|
||||
}
|
||||
});
|
||||
render(MessageBox, {});
|
||||
|
||||
await vi.waitFor(() => eventCallback !== undefined);
|
||||
|
||||
eventCallback?.(messageBoxOptions);
|
||||
expect(await screen.findByText(messageBoxOptions.title)).toBeInTheDocument();
|
||||
|
||||
if (messageBoxOptions.type === 'info') {
|
||||
expect(document.querySelectorAll('.place-content-center').length).toBeGreaterThanOrEqual(2);
|
||||
}
|
||||
});
|
||||
|
||||
test('Expect dropdown button to call selection with dropdown index', async () => {
|
||||
const idRequest = 707;
|
||||
const messageBoxOptions: MessageBoxOptions = {
|
||||
id: idRequest,
|
||||
title: 'Actions',
|
||||
message: 'Message',
|
||||
buttons: [{ type: 'dropdownButton', heading: 'More', buttons: ['A', 'B'] }],
|
||||
};
|
||||
|
||||
receiveFunctionMock.mockImplementation((message: string, callback: (options: MessageBoxOptions) => void) => {
|
||||
if (message === 'showMessageBox:open') {
|
||||
callback(messageBoxOptions);
|
||||
}
|
||||
});
|
||||
|
||||
render(MessageBox, {});
|
||||
|
||||
await fireEvent.click(screen.getByRole('button', { name: 'More' }));
|
||||
await fireEvent.click(await screen.findByText('B'));
|
||||
expect(window.sendShowMessageBoxOnSelect).toBeCalledWith(idRequest, 0, 1);
|
||||
});
|
||||
|
||||
test('Expect icon button to call selection', async () => {
|
||||
const idRequest = 708;
|
||||
const messageBoxOptions: MessageBoxOptions = {
|
||||
id: idRequest,
|
||||
title: 'Actions',
|
||||
message: 'Message',
|
||||
buttons: [{ type: 'iconButton', label: 'Run', icon: 'fas fa-play' }],
|
||||
};
|
||||
|
||||
receiveFunctionMock.mockImplementation((message: string, callback: (options: MessageBoxOptions) => void) => {
|
||||
if (message === 'showMessageBox:open') {
|
||||
callback(messageBoxOptions);
|
||||
}
|
||||
});
|
||||
|
||||
render(MessageBox, {});
|
||||
|
||||
await vi.waitFor(() => expect(screen.getByRole('button', { name: 'Run' })).toBeInTheDocument());
|
||||
await fireEvent.click(screen.getByRole('button', { name: 'Run' }));
|
||||
expect(window.sendShowMessageBoxOnSelect).toBeCalledWith(idRequest, 0, undefined);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ let footerMarkdownDescription: string | undefined = $state();
|
|||
|
||||
let display = $state(false);
|
||||
|
||||
const DANGER_TYPE = 'danger';
|
||||
|
||||
const showMessageBoxCallback = (messageBoxParameter: unknown): void => {
|
||||
const options: MessageBoxOptions | undefined = messageBoxParameter as MessageBoxOptions;
|
||||
currentId = options?.id || 0;
|
||||
|
|
@ -107,7 +109,9 @@ async function onClose(): Promise<void> {
|
|||
|
||||
function getButtonType(b: boolean): ButtonType {
|
||||
// eslint-disable-next-line sonarjs/no-selector-parameter
|
||||
if (b) {
|
||||
if (b && type === DANGER_TYPE) {
|
||||
return 'danger';
|
||||
} else if (b) {
|
||||
return 'primary';
|
||||
} else {
|
||||
return 'secondary';
|
||||
|
|
@ -119,7 +123,7 @@ function getButtonType(b: boolean): ButtonType {
|
|||
<Dialog title={title} onclose={onClose}>
|
||||
{#snippet icon()}
|
||||
|
||||
{#if type === 'error'}
|
||||
{#if type === 'error' || type === DANGER_TYPE}
|
||||
<Icon class="h-4 w-4 text-[var(--pd-state-error)]" icon={faCircleExclamation} />
|
||||
{:else if type === 'warning'}
|
||||
<Icon class="h-4 w-4 text-[var(--pd-state-warning)]" icon={faTriangleExclamation} />
|
||||
|
|
|
|||
Loading…
Reference in a new issue