@reshape-biotech/design-system 2.4.1 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/app.css +2 -2
- package/dist/components/graphs/chart/Chart.svelte +5 -1
- package/dist/components/graphs/matrix/Matrix.svelte +2 -2
- package/dist/components/icons/AnalysisIcon.svelte +1 -2
- package/dist/components/icons/custom/Halo.svelte +3 -2
- package/dist/components/icons/custom/Halo.svelte.d.ts +1 -1
- package/dist/components/icons/custom/LightBottomHighIcon.svelte +26 -0
- package/dist/components/icons/custom/LightBottomHighIcon.svelte.d.ts +8 -0
- package/dist/components/icons/custom/LightBottomLowIcon.svelte +23 -0
- package/dist/components/icons/custom/LightBottomLowIcon.svelte.d.ts +8 -0
- package/dist/components/icons/custom/LightBottomMediumIcon.svelte +26 -0
- package/dist/components/icons/custom/LightBottomMediumIcon.svelte.d.ts +8 -0
- package/dist/components/icons/custom/LightTopHighIcon.svelte +26 -0
- package/dist/components/icons/custom/LightTopHighIcon.svelte.d.ts +8 -0
- package/dist/components/icons/custom/LightTopLowIcon.svelte +26 -0
- package/dist/components/icons/custom/LightTopLowIcon.svelte.d.ts +8 -0
- package/dist/components/icons/custom/LightTopMediumIcon.svelte +26 -0
- package/dist/components/icons/custom/LightTopMediumIcon.svelte.d.ts +8 -0
- package/dist/components/icons/custom/Well.svelte +3 -2
- package/dist/components/icons/custom/Well.svelte.d.ts +1 -1
- package/dist/components/icons/custom/index.d.ts +9 -0
- package/dist/components/icons/custom/index.js +8 -0
- package/dist/components/icons/index.d.ts +8 -0
- package/dist/components/icons/index.js +2 -1
- package/dist/components/legend/Legend.stories.svelte +108 -0
- package/dist/components/{button/Button.test.svelte.d.ts → legend/Legend.stories.svelte.d.ts} +4 -4
- package/dist/components/legend/components/legend-item.svelte +28 -0
- package/dist/components/legend/components/legend-item.svelte.d.ts +9 -0
- package/dist/components/legend/components/legend-root.svelte +24 -0
- package/dist/components/legend/components/legend-root.svelte.d.ts +8 -0
- package/dist/components/legend/index.d.ts +11 -0
- package/dist/components/legend/index.js +2 -0
- package/dist/components/segmented-control-buttons/ControlButton.svelte +3 -1
- package/dist/components/select/components/MultiSelectTrigger.svelte +5 -4
- package/dist/components/select/components/SelectContent.svelte +1 -1
- package/dist/components/sjsf-wrappers/SjsfNumberInputWrapper.svelte.d.ts +1 -1
- package/dist/components/sjsf-wrappers/SjsfSelectWidgetWrapper.svelte.d.ts +1 -1
- package/dist/components/sjsf-wrappers/SjsfTextInputWrapper.svelte.d.ts +1 -1
- package/dist/components/tag/Tag.svelte +1 -1
- package/dist/components/tooltip/Tooltip.svelte +3 -0
- package/dist/components/tooltip/Tooltip.svelte.d.ts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/notifications.d.ts +2 -5
- package/dist/tailwind.preset.js +1 -1
- package/package.json +195 -189
- package/dist/components/activity/Activity.test.d.ts +0 -1
- package/dist/components/activity/Activity.test.js +0 -89
- package/dist/components/avatar/Avatar.test.d.ts +0 -1
- package/dist/components/avatar/Avatar.test.js +0 -55
- package/dist/components/button/Button.test.d.ts +0 -1
- package/dist/components/button/Button.test.js +0 -117
- package/dist/components/button/Button.test.svelte +0 -5
- package/dist/components/checkbox/Checkbox.test.d.ts +0 -1
- package/dist/components/checkbox/Checkbox.test.js +0 -51
- package/dist/components/graphs/matrix/Matrix.test.d.ts +0 -1
- package/dist/components/graphs/matrix/Matrix.test.js +0 -256
- package/dist/components/graphs/matrix/Matrix.test.svelte +0 -49
- package/dist/components/graphs/matrix/Matrix.test.svelte.d.ts +0 -4
- package/dist/components/input/Input.test.d.ts +0 -1
- package/dist/components/input/Input.test.js +0 -35
- package/dist/components/label/Label.test.d.ts +0 -1
- package/dist/components/label/Label.test.js +0 -29
- package/dist/components/manual-cfu-counter/test/ManualCFUCounter.test.d.ts +0 -1
- package/dist/components/manual-cfu-counter/test/ManualCFUCounter.test.js +0 -319
- package/dist/components/multi-cfu-counter/test/MultiCFUCounter.test.d.ts +0 -1
- package/dist/components/multi-cfu-counter/test/MultiCFUCounter.test.js +0 -320
- package/dist/components/stat-card/StatCard.test.d.ts +0 -1
- package/dist/components/stat-card/StatCard.test.js +0 -54
- package/dist/components/table/Table.test.d.ts +0 -1
- package/dist/components/table/Table.test.js +0 -97
- package/dist/components/table/Table.test.svelte +0 -37
- package/dist/components/table/Table.test.svelte.d.ts +0 -12
- package/dist/components/textarea/Textarea.test.d.ts +0 -1
- package/dist/components/textarea/Textarea.test.js +0 -90
- package/dist/components/toggle-icon-button/ToggleIconButton.test.d.ts +0 -1
- package/dist/components/toggle-icon-button/ToggleIconButton.test.js +0 -100
- package/dist/components/tooltip/Tooltip.test.d.ts +0 -1
- package/dist/components/tooltip/Tooltip.test.js +0 -81
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { render, fireEvent, screen } from '@testing-library/svelte';
|
|
2
|
-
import { tick } from 'svelte';
|
|
3
|
-
import StatCard from './StatCard.svelte';
|
|
4
|
-
import '@testing-library/jest-dom';
|
|
5
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
6
|
-
describe('StatCard', () => {
|
|
7
|
-
it('should focus the input field when the pencil edit icon is clicked', async () => {
|
|
8
|
-
render(StatCard, {
|
|
9
|
-
props: {
|
|
10
|
-
title: 'Test Stat',
|
|
11
|
-
value: 'Initial Value',
|
|
12
|
-
editable: true,
|
|
13
|
-
onsubmit: vi.fn(),
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
const pencilButton = screen.getByRole('button');
|
|
17
|
-
await fireEvent.click(pencilButton);
|
|
18
|
-
// Wait for Svelte's reactivity and the $effect with tick() to apply focus
|
|
19
|
-
await tick();
|
|
20
|
-
const inputField = screen.getByRole('textbox');
|
|
21
|
-
expect(inputField).toHaveFocus();
|
|
22
|
-
});
|
|
23
|
-
it('should focus the input field when the card body is clicked', async () => {
|
|
24
|
-
render(StatCard, {
|
|
25
|
-
props: {
|
|
26
|
-
title: 'Clickable Stat',
|
|
27
|
-
value: 'Initial Value',
|
|
28
|
-
editable: true,
|
|
29
|
-
onsubmit: vi.fn(),
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
const cardBody = screen.getByTestId('stat-card-body');
|
|
33
|
-
await fireEvent.click(cardBody);
|
|
34
|
-
await tick(); // Wait for Svelte's reactivity
|
|
35
|
-
const inputField = screen.getByRole('textbox');
|
|
36
|
-
expect(inputField).toHaveFocus();
|
|
37
|
-
});
|
|
38
|
-
it('should not focus the input field when the card body is clicked, out of editable state', async () => {
|
|
39
|
-
render(StatCard, {
|
|
40
|
-
props: {
|
|
41
|
-
title: 'Clickable Stat',
|
|
42
|
-
value: 'Initial Value',
|
|
43
|
-
editable: false,
|
|
44
|
-
onsubmit: vi.fn(),
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
const cardBody = screen.getByTestId('stat-card-body');
|
|
48
|
-
await fireEvent.click(cardBody);
|
|
49
|
-
await tick(); // Wait for Svelte's reactivity
|
|
50
|
-
// When not editable, the input field should not be rendered
|
|
51
|
-
const inputField = screen.queryByRole('textbox');
|
|
52
|
-
expect(inputField).toBeNull();
|
|
53
|
-
});
|
|
54
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { render, screen } from '@testing-library/svelte';
|
|
2
|
-
import Table from './Table.test.svelte';
|
|
3
|
-
const users = [
|
|
4
|
-
{
|
|
5
|
-
name: 'John Doe',
|
|
6
|
-
age: 25,
|
|
7
|
-
role: 'admin',
|
|
8
|
-
},
|
|
9
|
-
{
|
|
10
|
-
name: 'Jane Smith',
|
|
11
|
-
age: 32,
|
|
12
|
-
role: 'member',
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
name: 'Michael Johnson',
|
|
16
|
-
age: 41,
|
|
17
|
-
role: 'deactivated',
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
name: 'Emily Brown',
|
|
21
|
-
age: 28,
|
|
22
|
-
role: 'member',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
name: 'David Lee',
|
|
26
|
-
age: 37,
|
|
27
|
-
role: 'admin',
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
name: 'Sarah Wilson',
|
|
31
|
-
age: 29,
|
|
32
|
-
role: 'member',
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
name: 'Robert Taylor',
|
|
36
|
-
age: 45,
|
|
37
|
-
role: 'deactivated',
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
name: 'Lisa Anderson',
|
|
41
|
-
age: 33,
|
|
42
|
-
role: 'member',
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
name: 'James Martinez',
|
|
46
|
-
age: 39,
|
|
47
|
-
role: 'admin',
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
name: 'Jennifer Garcia',
|
|
51
|
-
age: 31,
|
|
52
|
-
role: 'deactivated',
|
|
53
|
-
},
|
|
54
|
-
];
|
|
55
|
-
describe('Table Component', () => {
|
|
56
|
-
it('renders the table with correct headers', () => {
|
|
57
|
-
render(Table, { props: { users } });
|
|
58
|
-
expect(screen.getByText('Name')).toBeInTheDocument();
|
|
59
|
-
expect(screen.getByText('Age')).toBeInTheDocument();
|
|
60
|
-
expect(screen.getByText('Role')).toBeInTheDocument();
|
|
61
|
-
});
|
|
62
|
-
it('renders table rows with user data', () => {
|
|
63
|
-
render(Table, { props: { users } });
|
|
64
|
-
users.forEach((user) => {
|
|
65
|
-
expect(screen.getByTestId(`user-${user.name}`)).toBeInTheDocument();
|
|
66
|
-
expect(screen.getByTestId(`user-${user.name}-age`)).toBeInTheDocument();
|
|
67
|
-
expect(screen.getByTestId(`user-${user.name}-role`)).toBeInTheDocument();
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
it('applies disabled class to deactivated users', () => {
|
|
71
|
-
render(Table, { props: { users } });
|
|
72
|
-
const deactivatedUser = screen.getByText('Michael Johnson');
|
|
73
|
-
expect(deactivatedUser.closest('tr')).toHaveClass('disabled');
|
|
74
|
-
});
|
|
75
|
-
it('renders phone icon button for admin users', () => {
|
|
76
|
-
render(Table, { props: { users, userRole: 'admin' } });
|
|
77
|
-
const phoneIcon = screen.getAllByTestId('phone-icon');
|
|
78
|
-
expect(phoneIcon).toHaveLength(users.length);
|
|
79
|
-
});
|
|
80
|
-
it('does not render phone icon button for non-admin users', () => {
|
|
81
|
-
render(Table, { props: { users, userRole: 'member' } });
|
|
82
|
-
const phoneIcon = screen.queryAllByTestId('phone-icon');
|
|
83
|
-
expect(phoneIcon).toHaveLength(0);
|
|
84
|
-
});
|
|
85
|
-
it('applies disabled styles to td elements when disabled', () => {
|
|
86
|
-
render(Table, { props: { users, userRole: 'member' } });
|
|
87
|
-
const deactivatedUser = screen.getByText('Michael Johnson');
|
|
88
|
-
const tr = deactivatedUser.closest('tr');
|
|
89
|
-
if (tr) {
|
|
90
|
-
expect(tr.classList.contains('disabled')).toBe(true);
|
|
91
|
-
expect(tr.classList.contains('[&.disabled]:text-tertiary')).toBe(true);
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
throw new Error('Tr element not found');
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
});
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import Table from './Table.svelte';
|
|
3
|
-
import IconButton from '../icon-button/IconButton.svelte';
|
|
4
|
-
import { Icon } from '../icons';
|
|
5
|
-
|
|
6
|
-
interface Props {
|
|
7
|
-
users?: { name: string; age: number; role: string }[];
|
|
8
|
-
userRole?: 'admin' | 'member' | 'deactivated';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let { users = [], userRole = 'admin' }: Props = $props();
|
|
12
|
-
</script>
|
|
13
|
-
|
|
14
|
-
<Table>
|
|
15
|
-
{#snippet children({ THead, TBody, Tr, Th, Td })}
|
|
16
|
-
<THead>
|
|
17
|
-
<Tr>
|
|
18
|
-
<Th>Name</Th>
|
|
19
|
-
<Th>Age</Th>
|
|
20
|
-
<Th class="w-[100px]">Role</Th>
|
|
21
|
-
<Th class="w-6"></Th>
|
|
22
|
-
</Tr>
|
|
23
|
-
</THead>
|
|
24
|
-
<TBody>
|
|
25
|
-
{#each users as user}
|
|
26
|
-
<Tr disabled={user.role === 'deactivated'}>
|
|
27
|
-
<Td dataTestId={`user-${user.name}`}>{user.name}</Td>
|
|
28
|
-
<Td dataTestId={`user-${user.name}-age`}>{user.age}</Td>
|
|
29
|
-
<Td dataTestId={`user-${user.name}-role`}>{user.role}</Td>
|
|
30
|
-
{#if 'admin' === userRole}
|
|
31
|
-
<Td dataTestId="phone-icon"><IconButton><Icon iconName="Phone" /></IconButton></Td>
|
|
32
|
-
{/if}
|
|
33
|
-
</Tr>
|
|
34
|
-
{/each}
|
|
35
|
-
</TBody>
|
|
36
|
-
{/snippet}
|
|
37
|
-
</Table>
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import Table from './Table.svelte';
|
|
2
|
-
interface Props {
|
|
3
|
-
users?: {
|
|
4
|
-
name: string;
|
|
5
|
-
age: number;
|
|
6
|
-
role: string;
|
|
7
|
-
}[];
|
|
8
|
-
userRole?: 'admin' | 'member' | 'deactivated';
|
|
9
|
-
}
|
|
10
|
-
declare const Table: import("svelte").Component<Props, {}, "">;
|
|
11
|
-
type Table = ReturnType<typeof Table>;
|
|
12
|
-
export default Table;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { render, screen, fireEvent } from '@testing-library/svelte';
|
|
2
|
-
import Textarea from './Textarea.svelte';
|
|
3
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
4
|
-
describe('Textarea component', () => {
|
|
5
|
-
it('renders with default props', () => {
|
|
6
|
-
render(Textarea, { props: { value: '' } });
|
|
7
|
-
const textarea = screen.getByRole('textbox');
|
|
8
|
-
expect(textarea).toBeInTheDocument();
|
|
9
|
-
expect(textarea).not.toHaveClass('!border-error'); // Default valid state
|
|
10
|
-
});
|
|
11
|
-
it('binds the value correctly', async () => {
|
|
12
|
-
const { component } = render(Textarea, { props: { value: 'Initial' } });
|
|
13
|
-
const textarea = screen.getByRole('textbox');
|
|
14
|
-
expect(textarea.value).toBe('Initial');
|
|
15
|
-
// Simulate user typing
|
|
16
|
-
await fireEvent.input(textarea, { target: { value: 'Changed' } });
|
|
17
|
-
expect(textarea.value).toBe('Changed'); // Check the DOM element's value directly
|
|
18
|
-
});
|
|
19
|
-
it('applies placeholder, name, required, readonly, maxlength attributes', () => {
|
|
20
|
-
render(Textarea, {
|
|
21
|
-
props: {
|
|
22
|
-
value: '',
|
|
23
|
-
placeholder: 'Enter text',
|
|
24
|
-
name: 'myTextarea',
|
|
25
|
-
required: true,
|
|
26
|
-
readonly: true,
|
|
27
|
-
maxlength: 50,
|
|
28
|
-
},
|
|
29
|
-
});
|
|
30
|
-
const textarea = screen.getByRole('textbox');
|
|
31
|
-
expect(textarea).toHaveAttribute('placeholder', 'Enter text');
|
|
32
|
-
expect(textarea).toHaveAttribute('name', 'myTextarea');
|
|
33
|
-
expect(textarea).toBeRequired();
|
|
34
|
-
expect(textarea).toHaveAttribute('readonly');
|
|
35
|
-
expect(textarea).toHaveAttribute('maxlength', '50');
|
|
36
|
-
});
|
|
37
|
-
it('calls onInput, onBlur, onKeydown event handlers', async () => {
|
|
38
|
-
const handleInput = vi.fn();
|
|
39
|
-
const handleBlur = vi.fn();
|
|
40
|
-
const handleKeydown = vi.fn();
|
|
41
|
-
render(Textarea, {
|
|
42
|
-
props: {
|
|
43
|
-
value: '',
|
|
44
|
-
oninput: handleInput,
|
|
45
|
-
onblur: handleBlur,
|
|
46
|
-
onkeydown: handleKeydown,
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
const textarea = screen.getByRole('textbox');
|
|
50
|
-
await fireEvent.input(textarea, { target: { value: 'test' } });
|
|
51
|
-
expect(handleInput).toHaveBeenCalledTimes(1);
|
|
52
|
-
await fireEvent.blur(textarea);
|
|
53
|
-
expect(handleBlur).toHaveBeenCalledTimes(1);
|
|
54
|
-
await fireEvent.keyDown(textarea, { key: 'Enter' });
|
|
55
|
-
expect(handleKeydown).toHaveBeenCalledTimes(1);
|
|
56
|
-
});
|
|
57
|
-
it('auto-resizes correctly on input', async () => {
|
|
58
|
-
// Mock scrollHeight to simulate content height
|
|
59
|
-
const mockScrollHeight = 200;
|
|
60
|
-
Object.defineProperty(HTMLElement.prototype, 'scrollHeight', {
|
|
61
|
-
configurable: true,
|
|
62
|
-
get() {
|
|
63
|
-
return mockScrollHeight;
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
render(Textarea, { props: { value: 'Short', size: 'dynamic' } });
|
|
67
|
-
const textarea = screen.getByRole('textbox');
|
|
68
|
-
// Simulate typing more content
|
|
69
|
-
await fireEvent.input(textarea, {
|
|
70
|
-
target: {
|
|
71
|
-
value: 'This is a much longer line of text that should definitely exceed the initial height and cause a resize.',
|
|
72
|
-
},
|
|
73
|
-
});
|
|
74
|
-
// Verify height was set to scrollHeight
|
|
75
|
-
expect(textarea.style.height).toBe(`${mockScrollHeight}px`);
|
|
76
|
-
});
|
|
77
|
-
it('calls focus function when exported focus() is called', () => {
|
|
78
|
-
const { component } = render(Textarea, { props: { value: '' } });
|
|
79
|
-
const textarea = screen.getByRole('textbox');
|
|
80
|
-
vi.spyOn(textarea, 'focus');
|
|
81
|
-
component.focus();
|
|
82
|
-
expect(textarea.focus).toHaveBeenCalled();
|
|
83
|
-
});
|
|
84
|
-
it('applies custom class', () => {
|
|
85
|
-
const customClass = 'my-custom-textarea';
|
|
86
|
-
render(Textarea, { props: { value: '', class: customClass } });
|
|
87
|
-
const textarea = screen.getByRole('textbox');
|
|
88
|
-
expect(textarea).toHaveClass(customClass);
|
|
89
|
-
});
|
|
90
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { render, fireEvent } from '@testing-library/svelte';
|
|
2
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
3
|
-
import ToggleIconButton from './ToggleIconButton.svelte';
|
|
4
|
-
describe('ToggleIconButton component', () => {
|
|
5
|
-
it('renders correctly', () => {
|
|
6
|
-
const { getByRole } = render(ToggleIconButton);
|
|
7
|
-
expect(getByRole('button')).toBeTruthy();
|
|
8
|
-
});
|
|
9
|
-
it('applies the correct variant class for secondary (default)', () => {
|
|
10
|
-
const { getByRole } = render(ToggleIconButton);
|
|
11
|
-
const button = getByRole('button');
|
|
12
|
-
expect(button.classList.toString()).toContain('bg-neutral text-icon-primary');
|
|
13
|
-
});
|
|
14
|
-
it('applies the correct variant class for primary-inverse', () => {
|
|
15
|
-
const { getByRole } = render(ToggleIconButton, {
|
|
16
|
-
props: {
|
|
17
|
-
variant: 'primary-inverse',
|
|
18
|
-
},
|
|
19
|
-
});
|
|
20
|
-
const button = getByRole('button');
|
|
21
|
-
expect(button.classList.toString()).toContain('bg-base-inverse text-icon-primary-inverse');
|
|
22
|
-
});
|
|
23
|
-
it('applies the active state class when isActive is true for secondary', () => {
|
|
24
|
-
const { getByRole, container } = render(ToggleIconButton, {
|
|
25
|
-
props: {
|
|
26
|
-
variant: 'secondary',
|
|
27
|
-
isActive: true,
|
|
28
|
-
},
|
|
29
|
-
});
|
|
30
|
-
const activeElement = container.querySelector('div');
|
|
31
|
-
expect(activeElement?.classList.toString()).toContain('bg-neutral-hover text-icon-primary');
|
|
32
|
-
});
|
|
33
|
-
it('applies the active state class when isActive is true for primary-inverse', () => {
|
|
34
|
-
const { getByRole, container } = render(ToggleIconButton, {
|
|
35
|
-
props: {
|
|
36
|
-
variant: 'primary-inverse',
|
|
37
|
-
isActive: true,
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
const activeElement = container.querySelector('div');
|
|
41
|
-
expect(activeElement?.classList.toString()).toContain('bg-accent-inverse text-icon-primary-inverse');
|
|
42
|
-
});
|
|
43
|
-
it('applies the size class', () => {
|
|
44
|
-
const { getByRole } = render(ToggleIconButton, {
|
|
45
|
-
props: {
|
|
46
|
-
size: 'lg',
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
const button = getByRole('button');
|
|
50
|
-
expect(button.classList.toString()).toContain('h-12 w-12');
|
|
51
|
-
});
|
|
52
|
-
it('applies the rounded-full class when rounded is true', () => {
|
|
53
|
-
const { getByRole } = render(ToggleIconButton, {
|
|
54
|
-
props: {
|
|
55
|
-
rounded: true,
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
const button = getByRole('button');
|
|
59
|
-
expect(button.classList.contains('rounded-full')).toBe(true);
|
|
60
|
-
});
|
|
61
|
-
it('applies the rounded-md class when rounded is false', () => {
|
|
62
|
-
const { getByRole } = render(ToggleIconButton, {
|
|
63
|
-
props: {
|
|
64
|
-
rounded: false,
|
|
65
|
-
},
|
|
66
|
-
});
|
|
67
|
-
const button = getByRole('button');
|
|
68
|
-
expect(button.classList.contains('rounded-md')).toBe(true);
|
|
69
|
-
});
|
|
70
|
-
it('calls onclick handler when clicked', async () => {
|
|
71
|
-
const handleClick = vi.fn();
|
|
72
|
-
const { getByRole } = render(ToggleIconButton, {
|
|
73
|
-
props: {
|
|
74
|
-
onclick: handleClick,
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
const button = getByRole('button');
|
|
78
|
-
await fireEvent.click(button);
|
|
79
|
-
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
80
|
-
});
|
|
81
|
-
it('is disabled when disabled prop is true', () => {
|
|
82
|
-
const { getByRole } = render(ToggleIconButton, {
|
|
83
|
-
props: {
|
|
84
|
-
disabled: true,
|
|
85
|
-
},
|
|
86
|
-
});
|
|
87
|
-
const button = getByRole('button');
|
|
88
|
-
expect(button.hasAttribute('disabled')).toBe(true);
|
|
89
|
-
expect(button.classList.contains('disabled:bg-neutral')).toBe(true);
|
|
90
|
-
});
|
|
91
|
-
it('shows spinner when loading is true', () => {
|
|
92
|
-
const { container } = render(ToggleIconButton, {
|
|
93
|
-
props: {
|
|
94
|
-
loading: true,
|
|
95
|
-
},
|
|
96
|
-
});
|
|
97
|
-
// Spinner should be present
|
|
98
|
-
expect(container.innerHTML).toContain('spinner');
|
|
99
|
-
});
|
|
100
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { render } from '@testing-library/svelte';
|
|
2
|
-
import { describe, it, expect } from 'vitest';
|
|
3
|
-
import TooltipTest from './TooltipTest.svelte';
|
|
4
|
-
// We test via a wrapper component because testing Svelte 5 snippets directly is complex
|
|
5
|
-
describe('Tooltip component', () => {
|
|
6
|
-
it('renders trigger content when forced open', () => {
|
|
7
|
-
const { getByText } = render(TooltipTest, {
|
|
8
|
-
props: {
|
|
9
|
-
forceOpen: true,
|
|
10
|
-
triggerText: 'Hover me',
|
|
11
|
-
contentText: 'Tooltip content',
|
|
12
|
-
},
|
|
13
|
-
});
|
|
14
|
-
expect(getByText('Hover me')).toBeInTheDocument();
|
|
15
|
-
expect(getByText('Tooltip content')).toBeInTheDocument();
|
|
16
|
-
});
|
|
17
|
-
it('applies custom class when forced open', () => {
|
|
18
|
-
render(TooltipTest, {
|
|
19
|
-
props: {
|
|
20
|
-
forceOpen: true,
|
|
21
|
-
class: 'custom-tooltip',
|
|
22
|
-
triggerText: 'Hover me',
|
|
23
|
-
contentText: 'Tooltip content',
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
// Tooltip content is portaled to document.body, so we search the entire document
|
|
27
|
-
const tooltipContent = document.querySelector('.custom-tooltip');
|
|
28
|
-
expect(tooltipContent).toBeInTheDocument();
|
|
29
|
-
});
|
|
30
|
-
it('applies design system tokens correctly when forced open', () => {
|
|
31
|
-
render(TooltipTest, {
|
|
32
|
-
props: {
|
|
33
|
-
forceOpen: true,
|
|
34
|
-
triggerText: 'Hover me',
|
|
35
|
-
contentText: 'Tooltip content',
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
// Tooltip content is portaled to document.body
|
|
39
|
-
const tooltipContent = document.querySelector('.bg-base-inverse');
|
|
40
|
-
expect(tooltipContent).toBeInTheDocument();
|
|
41
|
-
const textElement = document.querySelector('.text-primary-inverse');
|
|
42
|
-
expect(textElement).toBeInTheDocument();
|
|
43
|
-
});
|
|
44
|
-
it('renders with arrow by default when forced open', () => {
|
|
45
|
-
render(TooltipTest, {
|
|
46
|
-
props: {
|
|
47
|
-
forceOpen: true,
|
|
48
|
-
triggerText: 'Hover me',
|
|
49
|
-
contentText: 'Tooltip content',
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
// Arrow is part of the portaled content - bits-ui renders it as an SVG
|
|
53
|
-
const arrow = document.querySelector('svg[data-arrow]') || document.querySelector('[data-arrow]');
|
|
54
|
-
expect(arrow).toBeInTheDocument();
|
|
55
|
-
});
|
|
56
|
-
it('hides arrow when showArrow is false', () => {
|
|
57
|
-
render(TooltipTest, {
|
|
58
|
-
props: {
|
|
59
|
-
forceOpen: true,
|
|
60
|
-
showArrow: false,
|
|
61
|
-
triggerText: 'Hover me',
|
|
62
|
-
contentText: 'Tooltip content',
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
const arrow = document.querySelector('svg[data-arrow]') || document.querySelector('[data-arrow]');
|
|
66
|
-
expect(arrow).toBeNull();
|
|
67
|
-
});
|
|
68
|
-
it('applies correct placement when forced open', () => {
|
|
69
|
-
render(TooltipTest, {
|
|
70
|
-
props: {
|
|
71
|
-
forceOpen: true,
|
|
72
|
-
placement: 'bottom',
|
|
73
|
-
triggerText: 'Hover me',
|
|
74
|
-
contentText: 'Tooltip content',
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
// Check data attribute on portaled content
|
|
78
|
-
const tooltipContent = document.querySelector('[data-side="bottom"]');
|
|
79
|
-
expect(tooltipContent).toBeInTheDocument();
|
|
80
|
-
});
|
|
81
|
-
});
|