-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRegisterUpdateDialog.test.tsx
More file actions
108 lines (100 loc) · 5.21 KB
/
RegisterUpdateDialog.test.tsx
File metadata and controls
108 lines (100 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { describe, it, expect, vi } from 'vitest';
import { RegisterUpdateDialog } from './RegisterUpdateDialog';
describe('RegisterUpdateDialog', () => {
it('renders the four fields when open', () => {
render(<RegisterUpdateDialog open onClose={() => {}} onSubmit={async () => {}} />);
expect(screen.getByLabelText(/^id$/i)).toBeInTheDocument();
expect(screen.getByLabelText(/^name$/i)).toBeInTheDocument();
expect(screen.getByLabelText(/^automated$/i)).toBeInTheDocument();
expect(screen.getByLabelText(/additional metadata/i)).toBeInTheDocument();
});
it('rejects empty id', async () => {
const onSubmit = vi.fn();
render(<RegisterUpdateDialog open onClose={() => {}} onSubmit={onSubmit} />);
fireEvent.click(screen.getByRole('button', { name: /^register$/i }));
expect(await screen.findByText(/id is required/i)).toBeInTheDocument();
expect(onSubmit).not.toHaveBeenCalled();
});
it('rejects malformed JSON metadata', async () => {
const onSubmit = vi.fn();
render(<RegisterUpdateDialog open onClose={() => {}} onSubmit={onSubmit} />);
fireEvent.change(screen.getByLabelText(/^id$/i), { target: { value: 'x' } });
fireEvent.change(screen.getByLabelText(/additional metadata/i), { target: { value: '{not json' } });
fireEvent.click(screen.getByRole('button', { name: /^register$/i }));
expect(await screen.findByText(/invalid json/i)).toBeInTheDocument();
expect(onSubmit).not.toHaveBeenCalled();
});
it('strips reserved keys from metadata so UI-validated fields win', async () => {
const onSubmit = vi.fn().mockResolvedValue(undefined);
render(<RegisterUpdateDialog open onClose={() => {}} onSubmit={onSubmit} />);
fireEvent.change(screen.getByLabelText(/^id$/i), { target: { value: 'ui-id' } });
fireEvent.change(screen.getByLabelText(/additional metadata/i), {
target: { value: '{"id":"evil","update_name":"evil","automated":true,"extra":1}' },
});
fireEvent.click(screen.getByRole('button', { name: /^register$/i }));
await waitFor(() =>
expect(onSubmit).toHaveBeenCalledWith({
id: 'ui-id',
update_name: 'ui-id',
automated: false,
extra: 1,
})
);
});
it.each([
['string', '"just a string"'],
['array', '[1, 2, 3]'],
['null', 'null'],
['number', '42'],
])('rejects non-object JSON metadata (%s)', async (_label, raw) => {
const onSubmit = vi.fn();
render(<RegisterUpdateDialog open onClose={() => {}} onSubmit={onSubmit} />);
fireEvent.change(screen.getByLabelText(/^id$/i), { target: { value: 'x' } });
fireEvent.change(screen.getByLabelText(/additional metadata/i), { target: { value: raw } });
fireEvent.click(screen.getByRole('button', { name: /^register$/i }));
expect(await screen.findByText(/invalid json/i)).toBeInTheDocument();
expect(onSubmit).not.toHaveBeenCalled();
});
it('surfaces onSubmit rejection as inline error and keeps dialog open', async () => {
const onSubmit = vi.fn().mockRejectedValue(new Error('backend exploded'));
const onClose = vi.fn();
render(<RegisterUpdateDialog open onClose={onClose} onSubmit={onSubmit} />);
fireEvent.change(screen.getByLabelText(/^id$/i), { target: { value: 'x' } });
fireEvent.click(screen.getByRole('button', { name: /^register$/i }));
expect(await screen.findByRole('alert')).toHaveTextContent(/backend exploded/i);
expect(onClose).not.toHaveBeenCalled();
});
it('submits merged body on valid input', async () => {
const onSubmit = vi.fn().mockResolvedValue(undefined);
render(<RegisterUpdateDialog open onClose={() => {}} onSubmit={onSubmit} />);
fireEvent.change(screen.getByLabelText(/^id$/i), { target: { value: 'pkg-1' } });
fireEvent.change(screen.getByLabelText(/^name$/i), { target: { value: 'Pkg One' } });
fireEvent.click(screen.getByLabelText(/^automated$/i));
fireEvent.change(screen.getByLabelText(/additional metadata/i), {
target: { value: '{"origins":["a"]}' },
});
fireEvent.click(screen.getByRole('button', { name: /^register$/i }));
await waitFor(() =>
expect(onSubmit).toHaveBeenCalledWith({
id: 'pkg-1',
update_name: 'Pkg One',
automated: true,
origins: ['a'],
})
);
});
it('always includes automated=false when unchecked', async () => {
const onSubmit = vi.fn().mockResolvedValue(undefined);
render(<RegisterUpdateDialog open onClose={() => {}} onSubmit={onSubmit} />);
fireEvent.change(screen.getByLabelText(/^id$/i), { target: { value: 'plain' } });
fireEvent.click(screen.getByRole('button', { name: /^register$/i }));
await waitFor(() =>
expect(onSubmit).toHaveBeenCalledWith({
id: 'plain',
update_name: 'plain',
automated: false,
})
);
});
});