@getmicdrop/svelte-components 5.3.12 → 5.3.13
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/dist/calendar/AboutShow/AboutShow.svelte +172 -172
- package/dist/calendar/Calendar/MiniMonthCalendar.svelte +782 -782
- package/dist/calendar/FAQs/FAQs.svelte +75 -75
- package/dist/calendar/MonthSwitcher/MonthSwitcher.svelte +126 -126
- package/dist/calendar/OrderSummary/OrderSummary.svelte +367 -367
- package/dist/calendar/PublicCard/PublicCard.svelte +145 -145
- package/dist/calendar/ShowCard/ShowCard.svelte +157 -157
- package/dist/calendar/ShowTimeCard/ShowTimeCard.svelte +61 -61
- package/dist/components/Layout/Grid.svelte +109 -109
- package/dist/components/Layout/Section.svelte +80 -80
- package/dist/components/Layout/Sidebar.svelte +108 -108
- package/dist/components/Layout/Stack.svelte +90 -90
- package/dist/constants/formOptions.js +26 -26
- package/dist/constants/validation.js +91 -91
- package/dist/constants/validation.spec.js +64 -64
- package/dist/datetime/__tests__/format.test.d.ts +2 -0
- package/dist/datetime/__tests__/format.test.d.ts.map +1 -0
- package/dist/datetime/__tests__/format.test.js +268 -0
- package/dist/datetime/__tests__/integration.test.d.ts +2 -0
- package/dist/datetime/__tests__/integration.test.d.ts.map +1 -0
- package/dist/datetime/__tests__/integration.test.js +243 -0
- package/dist/datetime/__tests__/parse.test.d.ts +2 -0
- package/dist/datetime/__tests__/parse.test.d.ts.map +1 -0
- package/dist/datetime/__tests__/parse.test.js +261 -0
- package/dist/datetime/__tests__/timezone.test.d.ts +2 -0
- package/dist/datetime/__tests__/timezone.test.d.ts.map +1 -0
- package/dist/datetime/__tests__/timezone.test.js +214 -0
- package/dist/datetime/constants.d.ts +133 -0
- package/dist/datetime/constants.d.ts.map +1 -0
- package/dist/datetime/constants.js +112 -0
- package/dist/datetime/format.d.ts +158 -0
- package/dist/datetime/format.d.ts.map +1 -0
- package/dist/datetime/format.js +315 -0
- package/dist/datetime/index.d.ts +42 -0
- package/dist/datetime/index.d.ts.map +1 -0
- package/dist/datetime/index.js +44 -0
- package/dist/datetime/parse.d.ts +149 -0
- package/dist/datetime/parse.d.ts.map +1 -0
- package/dist/datetime/parse.js +276 -0
- package/dist/datetime/timezone.d.ts +95 -0
- package/dist/datetime/timezone.d.ts.map +1 -0
- package/dist/datetime/timezone.js +241 -0
- package/dist/datetime/types.d.ts +105 -0
- package/dist/datetime/types.d.ts.map +1 -0
- package/dist/datetime/types.js +31 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +232 -218
- package/dist/patterns/data/DataGrid.svelte +45 -45
- package/dist/patterns/data/DataList.svelte +24 -24
- package/dist/patterns/data/DataTable.svelte +40 -40
- package/dist/patterns/forms/FormActions.spec.js +88 -88
- package/dist/patterns/forms/FormActions.stories.svelte +97 -97
- package/dist/patterns/forms/FormActions.svelte +46 -46
- package/dist/patterns/forms/FormGrid.svelte +33 -33
- package/dist/patterns/forms/FormSection.svelte +32 -32
- package/dist/patterns/forms/FormValidationSummary.spec.js +203 -203
- package/dist/patterns/forms/FormValidationSummary.stories.svelte +97 -97
- package/dist/patterns/forms/FormValidationSummary.svelte +67 -67
- package/dist/patterns/layout/Grid.svelte +35 -35
- package/dist/patterns/layout/Sidebar.svelte +39 -39
- package/dist/patterns/layout/Stack.svelte +45 -45
- package/dist/patterns/navigation/BottomNav.spec.js +130 -130
- package/dist/patterns/navigation/BottomNav.stories.svelte +117 -117
- package/dist/patterns/navigation/BottomNav.svelte +54 -54
- package/dist/patterns/navigation/Header.spec.js +203 -203
- package/dist/patterns/navigation/Header.stories.svelte +77 -77
- package/dist/patterns/navigation/Header.svelte +240 -240
- package/dist/patterns/page/PageHeader.svelte +36 -36
- package/dist/patterns/page/PageLayout.svelte +40 -40
- package/dist/patterns/page/PageLoader.spec.js +54 -54
- package/dist/patterns/page/PageLoader.stories.svelte +137 -137
- package/dist/patterns/page/PageLoader.svelte +41 -41
- package/dist/patterns/page/SectionHeader.svelte +41 -41
- package/dist/presets/badges.js +112 -112
- package/dist/presets/buttons.js +76 -76
- package/dist/presets/index.js +9 -9
- package/dist/primitives/Accordion/Accordion.stories.svelte +75 -75
- package/dist/primitives/Accordion/Accordion.svelte +61 -61
- package/dist/primitives/Accordion/AccordionItem.svelte +95 -95
- package/dist/primitives/Alert/Alert.spec.js +170 -170
- package/dist/primitives/Alert/Alert.stories.svelte +88 -88
- package/dist/primitives/Alert/Alert.svelte +65 -65
- package/dist/primitives/Avatar/Avatar.stories.svelte +94 -94
- package/dist/primitives/Avatar/Avatar.svelte +66 -66
- package/dist/primitives/Badges/Badge.spec.js +103 -103
- package/dist/primitives/Badges/Badge.stories.svelte +86 -86
- package/dist/primitives/Badges/Badge.svelte +142 -142
- package/dist/primitives/BottomSheet/BottomSheet.spec.js +127 -127
- package/dist/primitives/BottomSheet/BottomSheet.stories.svelte +83 -83
- package/dist/primitives/BottomSheet/BottomSheet.svelte +100 -100
- package/dist/primitives/Breadcrumb/Breadcrumb.spec.js +120 -120
- package/dist/primitives/Breadcrumb/Breadcrumb.stories.svelte +23 -23
- package/dist/primitives/Breadcrumb/Breadcrumb.svelte +89 -89
- package/dist/primitives/Button/Button.spec.js +211 -211
- package/dist/primitives/Button/Button.stories.svelte +76 -76
- package/dist/primitives/Button/Button.svelte +301 -301
- package/dist/primitives/Button/ButtonSaveDemo.spec.js +48 -48
- package/dist/primitives/Button/ButtonSaveDemo.svelte +25 -25
- package/dist/primitives/Button/ButtonVariantShowcase.svelte +129 -129
- package/dist/primitives/Card.spec.js +49 -49
- package/dist/primitives/Card.stories.svelte +22 -22
- package/dist/primitives/Card.svelte +28 -28
- package/dist/primitives/Checkbox/Checkbox.stories.svelte +84 -84
- package/dist/primitives/Checkbox/Checkbox.svelte +88 -88
- package/dist/primitives/DarkModeToggle.spec.js +357 -357
- package/dist/primitives/DarkModeToggle.stories.svelte +57 -57
- package/dist/primitives/DarkModeToggle.svelte +136 -136
- package/dist/primitives/Drawer/Drawer.stories.svelte +100 -100
- package/dist/primitives/Drawer/Drawer.svelte +214 -214
- package/dist/primitives/Dropdown/Dropdown.stories.svelte +137 -137
- package/dist/primitives/Dropdown/Dropdown.svelte +148 -148
- package/dist/primitives/Dropdown/DropdownItem.svelte +80 -80
- package/dist/primitives/Icons/ArrowLeft.svelte +20 -20
- package/dist/primitives/Icons/ArrowRight.svelte +20 -20
- package/dist/primitives/Icons/Availability.svelte +26 -26
- package/dist/primitives/Icons/Back.svelte +26 -26
- package/dist/primitives/Icons/CheckCircle.svelte +18 -18
- package/dist/primitives/Icons/CheckCircleOutline.svelte +27 -27
- package/dist/primitives/Icons/ChevronLeft.svelte +16 -16
- package/dist/primitives/Icons/ChevronRight.svelte +16 -16
- package/dist/primitives/Icons/Copy.svelte +27 -27
- package/dist/primitives/Icons/Cross.svelte +17 -17
- package/dist/primitives/Icons/DownArrow.svelte +20 -20
- package/dist/primitives/Icons/ErrorCircle.svelte +18 -18
- package/dist/primitives/Icons/FacebookIcon.svelte +13 -13
- package/dist/primitives/Icons/Home.svelte +27 -27
- package/dist/primitives/Icons/Icon.spec.js +175 -175
- package/dist/primitives/Icons/Icon.stories.svelte +100 -100
- package/dist/primitives/Icons/Icon.svelte +63 -63
- package/dist/primitives/Icons/IconGallery.stories.svelte +235 -235
- package/dist/primitives/Icons/ImageOutline.svelte +19 -19
- package/dist/primitives/Icons/Info.svelte +19 -19
- package/dist/primitives/Icons/InstagramIcon.svelte +19 -19
- package/dist/primitives/Icons/LogoInstagram.svelte +15 -15
- package/dist/primitives/Icons/Message.svelte +27 -27
- package/dist/primitives/Icons/MoonIcon.svelte +16 -16
- package/dist/primitives/Icons/More.svelte +33 -33
- package/dist/primitives/Icons/MoreHori.spec.js +67 -67
- package/dist/primitives/Icons/MoreHori.svelte +34 -34
- package/dist/primitives/Icons/Notification.svelte +26 -26
- package/dist/primitives/Icons/Payment.svelte +26 -26
- package/dist/primitives/Icons/Profile.svelte +33 -33
- package/dist/primitives/Icons/Reload.svelte +41 -41
- package/dist/primitives/Icons/Shows.svelte +33 -33
- package/dist/primitives/Icons/Signout.svelte +33 -33
- package/dist/primitives/Icons/SunIcon.svelte +19 -19
- package/dist/primitives/Icons/TiktokIcon.svelte +13 -13
- package/dist/primitives/Icons/TrashBinOutline.svelte +19 -19
- package/dist/primitives/Icons/TwitterIcon.svelte +13 -13
- package/dist/primitives/Icons/WarningIcon.spec.js +30 -30
- package/dist/primitives/Icons/WarningIcon.svelte +24 -24
- package/dist/primitives/Input/Input.spec.js +573 -573
- package/dist/primitives/Input/Input.stories.svelte +139 -139
- package/dist/primitives/Input/Input.svelte +444 -444
- package/dist/primitives/Input/Select.spec.js +218 -218
- package/dist/primitives/Input/Select.stories.svelte +112 -112
- package/dist/primitives/Input/Select.svelte +232 -232
- package/dist/primitives/Input/Textarea.stories.svelte +137 -137
- package/dist/primitives/Input/Textarea.svelte +79 -79
- package/dist/primitives/Label/Label.svelte +37 -37
- package/dist/primitives/Modal/Modal.spec.js +95 -95
- package/dist/primitives/Modal/Modal.stories.svelte +86 -86
- package/dist/primitives/Modal/Modal.svelte +158 -158
- package/dist/primitives/Pagination/Pagination.stories.svelte +76 -76
- package/dist/primitives/Pagination/Pagination.svelte +261 -261
- package/dist/primitives/Radio/Radio.stories.svelte +80 -80
- package/dist/primitives/Radio/Radio.svelte +67 -67
- package/dist/primitives/Skeleton/CardPlaceholder.svelte +87 -87
- package/dist/primitives/Skeleton/ImagePlaceholder.svelte +59 -59
- package/dist/primitives/Skeleton/ListPlaceholder.svelte +76 -76
- package/dist/primitives/Skeleton/Skeleton.stories.svelte +151 -151
- package/dist/primitives/Skeleton/Skeleton.svelte +52 -52
- package/dist/primitives/Spinner/Spinner.spec.js +75 -75
- package/dist/primitives/Spinner/Spinner.stories.svelte +29 -29
- package/dist/primitives/Spinner/Spinner.svelte +57 -57
- package/dist/primitives/Tabs/TabItem.svelte +51 -51
- package/dist/primitives/Tabs/Tabs.stories.svelte +112 -112
- package/dist/primitives/Tabs/Tabs.svelte +128 -128
- package/dist/primitives/Toggle.spec.js +127 -127
- package/dist/primitives/Toggle.stories.svelte +92 -92
- package/dist/primitives/Toggle.svelte +71 -71
- package/dist/primitives/Typography/Typography.svelte +53 -53
- package/dist/primitives/ValidationError.spec.js +103 -103
- package/dist/primitives/ValidationError.stories.svelte +111 -111
- package/dist/primitives/ValidationError.svelte +29 -29
- package/dist/recipes/CropImage/CropImage.spec.js +216 -216
- package/dist/recipes/CropImage/CropImage.stories.svelte +104 -104
- package/dist/recipes/CropImage/CropImage.svelte +238 -238
- package/dist/recipes/ImageUploader/ImageUploader.stories.svelte +125 -125
- package/dist/recipes/ImageUploader/ImageUploader.svelte +980 -980
- package/dist/recipes/Toaster/Toaster.stories.svelte +62 -62
- package/dist/recipes/feedback/EmptyState/EmptyState.svelte +47 -47
- package/dist/recipes/feedback/ErrorDisplay.spec.js +69 -69
- package/dist/recipes/feedback/ErrorDisplay.stories.svelte +112 -112
- package/dist/recipes/feedback/ErrorDisplay.svelte +38 -38
- package/dist/recipes/feedback/StatusIndicator/StatusIndicator.spec.js +129 -129
- package/dist/recipes/feedback/StatusIndicator/StatusIndicator.svelte +167 -167
- package/dist/recipes/fields/CheckboxField.svelte +85 -85
- package/dist/recipes/fields/FormField.svelte +58 -58
- package/dist/recipes/fields/RadioGroup.svelte +95 -95
- package/dist/recipes/fields/SelectField.svelte +82 -82
- package/dist/recipes/fields/TextareaField.svelte +101 -101
- package/dist/recipes/fields/ToggleField.svelte +60 -60
- package/dist/recipes/fields/index.js +7 -7
- package/dist/recipes/inputs/MultiSelect.spec.js +257 -257
- package/dist/recipes/inputs/MultiSelect.stories.svelte +133 -133
- package/dist/recipes/inputs/MultiSelect.svelte +244 -244
- package/dist/recipes/inputs/OTPInput.spec.js +238 -238
- package/dist/recipes/inputs/OTPInput.stories.svelte +162 -162
- package/dist/recipes/inputs/OTPInput.svelte +102 -102
- package/dist/recipes/inputs/PasswordInput.svelte +100 -100
- package/dist/recipes/inputs/PasswordStrengthIndicator/PasswordStrengthIndicator.spec.js +173 -173
- package/dist/recipes/inputs/PasswordStrengthIndicator/PasswordStrengthIndicator.svelte +108 -108
- package/dist/recipes/inputs/PlaceAutocomplete/PlaceAutocomplete.spec.js +300 -300
- package/dist/recipes/inputs/PlaceAutocomplete/PlaceAutocomplete.stories.svelte +165 -165
- package/dist/recipes/inputs/PlaceAutocomplete/PlaceAutocomplete.svelte +337 -337
- package/dist/recipes/inputs/Search.svelte +85 -85
- package/dist/recipes/inputs/SelectDropdown.svelte +161 -161
- package/dist/recipes/modals/AlertModal.svelte +130 -130
- package/dist/recipes/modals/ConfirmationModal.spec.js +191 -191
- package/dist/recipes/modals/ConfirmationModal.stories.svelte +119 -119
- package/dist/recipes/modals/ConfirmationModal.svelte +152 -152
- package/dist/recipes/modals/InputModal.svelte +182 -182
- package/dist/recipes/modals/ModalStateManager.spec.js +100 -100
- package/dist/recipes/modals/ModalStateManager.svelte +77 -77
- package/dist/recipes/modals/ModalTestWrapper.svelte +65 -65
- package/dist/recipes/modals/StatusModal.svelte +206 -206
- package/dist/services/EventService.js +75 -75
- package/dist/services/EventService.spec.js +217 -217
- package/dist/services/ShowService.spec.js +342 -342
- package/dist/stores/auth.js +93 -6
- package/dist/stores/auth.spec.js +310 -2
- package/dist/stores/toaster.js +13 -13
- package/dist/stories/ButtonAuditReview.stories.svelte +14 -14
- package/dist/stories/ButtonAuditReview.svelte +427 -427
- package/dist/stories/PatternsGallery.stories.svelte +19 -19
- package/dist/stories/PatternsGallery.svelte +388 -388
- package/dist/stories/PrimitivesGallery.stories.svelte +19 -19
- package/dist/stories/PrimitivesGallery.svelte +752 -752
- package/dist/stories/RecipesGallery.stories.svelte +19 -19
- package/dist/stories/RecipesGallery.svelte +441 -441
- package/dist/stories/button-audit-manifest.json +11186 -11186
- package/dist/tailwind/preset.cjs +82 -82
- package/dist/telemetry.js +357 -357
- package/dist/tokens/tokens.css +87 -87
- package/dist/utils/apiConfig.js +49 -49
- package/dist/utils/utils.js +9 -1
- package/package.json +233 -191
|
@@ -1,203 +1,203 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { render, screen, fireEvent } from '@testing-library/svelte';
|
|
3
|
-
import Header from './Header.svelte';
|
|
4
|
-
|
|
5
|
-
// Mock SvelteKit modules
|
|
6
|
-
vi.mock('$app/stores', () => ({
|
|
7
|
-
page: {
|
|
8
|
-
subscribe: (fn) => {
|
|
9
|
-
fn({ url: { pathname: '/shows' } });
|
|
10
|
-
return () => {};
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
}));
|
|
14
|
-
|
|
15
|
-
vi.mock('$app/paths', () => ({
|
|
16
|
-
base: '/performers'
|
|
17
|
-
}));
|
|
18
|
-
|
|
19
|
-
vi.mock('$app/navigation', () => ({
|
|
20
|
-
goto: vi.fn()
|
|
21
|
-
}));
|
|
22
|
-
|
|
23
|
-
describe('Header', () => {
|
|
24
|
-
const defaultProps = {
|
|
25
|
-
name: 'Test Performer',
|
|
26
|
-
email: 'test@example.com',
|
|
27
|
-
avatar: 'https://example.com/avatar.jpg',
|
|
28
|
-
navLinks: [
|
|
29
|
-
{ label: 'Shows', href: '/shows' },
|
|
30
|
-
{ label: 'Availability', href: '/availability' },
|
|
31
|
-
{ label: 'Profile', href: '/profile' }
|
|
32
|
-
],
|
|
33
|
-
dropdownLinks: [
|
|
34
|
-
{ label: 'Account Settings', href: '/account-settings' },
|
|
35
|
-
{ label: 'Payment Settings', href: '/payment-settings' }
|
|
36
|
-
],
|
|
37
|
-
signoutHandler: vi.fn(),
|
|
38
|
-
showBackButton: false
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
beforeEach(() => {
|
|
42
|
-
vi.clearAllMocks();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
describe('basic rendering', () => {
|
|
46
|
-
it('renders the logo', () => {
|
|
47
|
-
const { container } = render(Header, defaultProps);
|
|
48
|
-
const logo = container.querySelector('img[alt="Micdrop"]');
|
|
49
|
-
expect(logo).toBeTruthy();
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('renders navigation links', () => {
|
|
53
|
-
render(Header, defaultProps);
|
|
54
|
-
expect(screen.getByText('Shows')).toBeTruthy();
|
|
55
|
-
expect(screen.getByText('Availability')).toBeTruthy();
|
|
56
|
-
expect(screen.getByText('Profile')).toBeTruthy();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('renders dark mode toggle', () => {
|
|
60
|
-
const { container } = render(Header, defaultProps);
|
|
61
|
-
// DarkModeToggle should be present
|
|
62
|
-
expect(container.querySelector('button[aria-label]')).toBeTruthy();
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
describe('back button mode', () => {
|
|
67
|
-
it('shows back button when showBackButton is true', () => {
|
|
68
|
-
const { container } = render(Header, { ...defaultProps, showBackButton: true });
|
|
69
|
-
const backButton = container.querySelector('.header-back-button');
|
|
70
|
-
expect(backButton).toBeTruthy();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('does not show back button by default', () => {
|
|
74
|
-
const { container } = render(Header, defaultProps);
|
|
75
|
-
const backButton = container.querySelector('.header-back-button');
|
|
76
|
-
expect(backButton).toBeFalsy();
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
describe('avatar buttons', () => {
|
|
81
|
-
it('renders mobile avatar button', () => {
|
|
82
|
-
const { container } = render(Header, defaultProps);
|
|
83
|
-
const mobileButton = container.querySelector('.avatar-button--mobile');
|
|
84
|
-
expect(mobileButton).toBeTruthy();
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('renders desktop avatar button', () => {
|
|
88
|
-
const { container } = render(Header, defaultProps);
|
|
89
|
-
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
90
|
-
expect(desktopButton).toBeTruthy();
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
describe('desktop dropdown', () => {
|
|
95
|
-
it('shows dropdown when desktop avatar is clicked', async () => {
|
|
96
|
-
const { container } = render(Header, defaultProps);
|
|
97
|
-
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
98
|
-
|
|
99
|
-
await fireEvent.click(desktopButton);
|
|
100
|
-
|
|
101
|
-
const dropdown = container.querySelector('.desktop-dropdown');
|
|
102
|
-
expect(dropdown).toBeTruthy();
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('displays user name and email in dropdown', async () => {
|
|
106
|
-
const { container } = render(Header, defaultProps);
|
|
107
|
-
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
108
|
-
|
|
109
|
-
await fireEvent.click(desktopButton);
|
|
110
|
-
|
|
111
|
-
expect(screen.getByText('Test Performer')).toBeTruthy();
|
|
112
|
-
expect(screen.getByText('test@example.com')).toBeTruthy();
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it('displays dropdown links', async () => {
|
|
116
|
-
const { container } = render(Header, defaultProps);
|
|
117
|
-
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
118
|
-
|
|
119
|
-
await fireEvent.click(desktopButton);
|
|
120
|
-
|
|
121
|
-
expect(screen.getByText('Account Settings')).toBeTruthy();
|
|
122
|
-
expect(screen.getByText('Payment Settings')).toBeTruthy();
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('displays sign out button', async () => {
|
|
126
|
-
const { container } = render(Header, defaultProps);
|
|
127
|
-
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
128
|
-
|
|
129
|
-
await fireEvent.click(desktopButton);
|
|
130
|
-
|
|
131
|
-
expect(screen.getByText('Sign out')).toBeTruthy();
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it('closes dropdown when backdrop is clicked', async () => {
|
|
135
|
-
const { container } = render(Header, defaultProps);
|
|
136
|
-
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
137
|
-
|
|
138
|
-
await fireEvent.click(desktopButton);
|
|
139
|
-
|
|
140
|
-
const backdrop = container.querySelector('.dropdown-backdrop');
|
|
141
|
-
await fireEvent.click(backdrop);
|
|
142
|
-
|
|
143
|
-
const dropdown = container.querySelector('.desktop-dropdown');
|
|
144
|
-
expect(dropdown).toBeFalsy();
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('calls signoutHandler when sign out is clicked', async () => {
|
|
148
|
-
const signoutHandler = vi.fn();
|
|
149
|
-
const { container } = render(Header, { ...defaultProps, signoutHandler });
|
|
150
|
-
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
151
|
-
|
|
152
|
-
await fireEvent.click(desktopButton);
|
|
153
|
-
|
|
154
|
-
const signOutButton = screen.getByText('Sign out');
|
|
155
|
-
await fireEvent.click(signOutButton);
|
|
156
|
-
|
|
157
|
-
expect(signoutHandler).toHaveBeenCalled();
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
it('toggles dropdown on repeated clicks', async () => {
|
|
161
|
-
const { container } = render(Header, defaultProps);
|
|
162
|
-
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
163
|
-
|
|
164
|
-
await fireEvent.click(desktopButton);
|
|
165
|
-
expect(container.querySelector('.desktop-dropdown')).toBeTruthy();
|
|
166
|
-
|
|
167
|
-
await fireEvent.click(desktopButton);
|
|
168
|
-
expect(container.querySelector('.desktop-dropdown')).toBeFalsy();
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
describe('mobile sheet', () => {
|
|
173
|
-
it('triggers mobile sheet state when mobile avatar is clicked', async () => {
|
|
174
|
-
const { container } = render(Header, defaultProps);
|
|
175
|
-
const mobileButton = container.querySelector('.avatar-button--mobile');
|
|
176
|
-
|
|
177
|
-
// Click should trigger the sheet opening (internal state)
|
|
178
|
-
await fireEvent.click(mobileButton);
|
|
179
|
-
|
|
180
|
-
// The mobile button should exist and be clickable
|
|
181
|
-
expect(mobileButton).toBeTruthy();
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
describe('navigation active state', () => {
|
|
186
|
-
it('marks current path as active', () => {
|
|
187
|
-
const { container } = render(Header, defaultProps);
|
|
188
|
-
const showsLink = container.querySelector('a[href="/shows"]');
|
|
189
|
-
expect(showsLink.classList.contains('active')).toBe(true);
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
describe('default values', () => {
|
|
194
|
-
it('shows "Performer" when name is empty', async () => {
|
|
195
|
-
const { container } = render(Header, { ...defaultProps, name: '' });
|
|
196
|
-
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
197
|
-
|
|
198
|
-
await fireEvent.click(desktopButton);
|
|
199
|
-
|
|
200
|
-
expect(screen.getByText('Performer')).toBeTruthy();
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
});
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/svelte';
|
|
3
|
+
import Header from './Header.svelte';
|
|
4
|
+
|
|
5
|
+
// Mock SvelteKit modules
|
|
6
|
+
vi.mock('$app/stores', () => ({
|
|
7
|
+
page: {
|
|
8
|
+
subscribe: (fn) => {
|
|
9
|
+
fn({ url: { pathname: '/shows' } });
|
|
10
|
+
return () => {};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
vi.mock('$app/paths', () => ({
|
|
16
|
+
base: '/performers'
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
vi.mock('$app/navigation', () => ({
|
|
20
|
+
goto: vi.fn()
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
describe('Header', () => {
|
|
24
|
+
const defaultProps = {
|
|
25
|
+
name: 'Test Performer',
|
|
26
|
+
email: 'test@example.com',
|
|
27
|
+
avatar: 'https://example.com/avatar.jpg',
|
|
28
|
+
navLinks: [
|
|
29
|
+
{ label: 'Shows', href: '/shows' },
|
|
30
|
+
{ label: 'Availability', href: '/availability' },
|
|
31
|
+
{ label: 'Profile', href: '/profile' }
|
|
32
|
+
],
|
|
33
|
+
dropdownLinks: [
|
|
34
|
+
{ label: 'Account Settings', href: '/account-settings' },
|
|
35
|
+
{ label: 'Payment Settings', href: '/payment-settings' }
|
|
36
|
+
],
|
|
37
|
+
signoutHandler: vi.fn(),
|
|
38
|
+
showBackButton: false
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
vi.clearAllMocks();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('basic rendering', () => {
|
|
46
|
+
it('renders the logo', () => {
|
|
47
|
+
const { container } = render(Header, defaultProps);
|
|
48
|
+
const logo = container.querySelector('img[alt="Micdrop"]');
|
|
49
|
+
expect(logo).toBeTruthy();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('renders navigation links', () => {
|
|
53
|
+
render(Header, defaultProps);
|
|
54
|
+
expect(screen.getByText('Shows')).toBeTruthy();
|
|
55
|
+
expect(screen.getByText('Availability')).toBeTruthy();
|
|
56
|
+
expect(screen.getByText('Profile')).toBeTruthy();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('renders dark mode toggle', () => {
|
|
60
|
+
const { container } = render(Header, defaultProps);
|
|
61
|
+
// DarkModeToggle should be present
|
|
62
|
+
expect(container.querySelector('button[aria-label]')).toBeTruthy();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('back button mode', () => {
|
|
67
|
+
it('shows back button when showBackButton is true', () => {
|
|
68
|
+
const { container } = render(Header, { ...defaultProps, showBackButton: true });
|
|
69
|
+
const backButton = container.querySelector('.header-back-button');
|
|
70
|
+
expect(backButton).toBeTruthy();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('does not show back button by default', () => {
|
|
74
|
+
const { container } = render(Header, defaultProps);
|
|
75
|
+
const backButton = container.querySelector('.header-back-button');
|
|
76
|
+
expect(backButton).toBeFalsy();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe('avatar buttons', () => {
|
|
81
|
+
it('renders mobile avatar button', () => {
|
|
82
|
+
const { container } = render(Header, defaultProps);
|
|
83
|
+
const mobileButton = container.querySelector('.avatar-button--mobile');
|
|
84
|
+
expect(mobileButton).toBeTruthy();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('renders desktop avatar button', () => {
|
|
88
|
+
const { container } = render(Header, defaultProps);
|
|
89
|
+
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
90
|
+
expect(desktopButton).toBeTruthy();
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('desktop dropdown', () => {
|
|
95
|
+
it('shows dropdown when desktop avatar is clicked', async () => {
|
|
96
|
+
const { container } = render(Header, defaultProps);
|
|
97
|
+
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
98
|
+
|
|
99
|
+
await fireEvent.click(desktopButton);
|
|
100
|
+
|
|
101
|
+
const dropdown = container.querySelector('.desktop-dropdown');
|
|
102
|
+
expect(dropdown).toBeTruthy();
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('displays user name and email in dropdown', async () => {
|
|
106
|
+
const { container } = render(Header, defaultProps);
|
|
107
|
+
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
108
|
+
|
|
109
|
+
await fireEvent.click(desktopButton);
|
|
110
|
+
|
|
111
|
+
expect(screen.getByText('Test Performer')).toBeTruthy();
|
|
112
|
+
expect(screen.getByText('test@example.com')).toBeTruthy();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('displays dropdown links', async () => {
|
|
116
|
+
const { container } = render(Header, defaultProps);
|
|
117
|
+
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
118
|
+
|
|
119
|
+
await fireEvent.click(desktopButton);
|
|
120
|
+
|
|
121
|
+
expect(screen.getByText('Account Settings')).toBeTruthy();
|
|
122
|
+
expect(screen.getByText('Payment Settings')).toBeTruthy();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('displays sign out button', async () => {
|
|
126
|
+
const { container } = render(Header, defaultProps);
|
|
127
|
+
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
128
|
+
|
|
129
|
+
await fireEvent.click(desktopButton);
|
|
130
|
+
|
|
131
|
+
expect(screen.getByText('Sign out')).toBeTruthy();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('closes dropdown when backdrop is clicked', async () => {
|
|
135
|
+
const { container } = render(Header, defaultProps);
|
|
136
|
+
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
137
|
+
|
|
138
|
+
await fireEvent.click(desktopButton);
|
|
139
|
+
|
|
140
|
+
const backdrop = container.querySelector('.dropdown-backdrop');
|
|
141
|
+
await fireEvent.click(backdrop);
|
|
142
|
+
|
|
143
|
+
const dropdown = container.querySelector('.desktop-dropdown');
|
|
144
|
+
expect(dropdown).toBeFalsy();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('calls signoutHandler when sign out is clicked', async () => {
|
|
148
|
+
const signoutHandler = vi.fn();
|
|
149
|
+
const { container } = render(Header, { ...defaultProps, signoutHandler });
|
|
150
|
+
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
151
|
+
|
|
152
|
+
await fireEvent.click(desktopButton);
|
|
153
|
+
|
|
154
|
+
const signOutButton = screen.getByText('Sign out');
|
|
155
|
+
await fireEvent.click(signOutButton);
|
|
156
|
+
|
|
157
|
+
expect(signoutHandler).toHaveBeenCalled();
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('toggles dropdown on repeated clicks', async () => {
|
|
161
|
+
const { container } = render(Header, defaultProps);
|
|
162
|
+
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
163
|
+
|
|
164
|
+
await fireEvent.click(desktopButton);
|
|
165
|
+
expect(container.querySelector('.desktop-dropdown')).toBeTruthy();
|
|
166
|
+
|
|
167
|
+
await fireEvent.click(desktopButton);
|
|
168
|
+
expect(container.querySelector('.desktop-dropdown')).toBeFalsy();
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
describe('mobile sheet', () => {
|
|
173
|
+
it('triggers mobile sheet state when mobile avatar is clicked', async () => {
|
|
174
|
+
const { container } = render(Header, defaultProps);
|
|
175
|
+
const mobileButton = container.querySelector('.avatar-button--mobile');
|
|
176
|
+
|
|
177
|
+
// Click should trigger the sheet opening (internal state)
|
|
178
|
+
await fireEvent.click(mobileButton);
|
|
179
|
+
|
|
180
|
+
// The mobile button should exist and be clickable
|
|
181
|
+
expect(mobileButton).toBeTruthy();
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
describe('navigation active state', () => {
|
|
186
|
+
it('marks current path as active', () => {
|
|
187
|
+
const { container } = render(Header, defaultProps);
|
|
188
|
+
const showsLink = container.querySelector('a[href="/shows"]');
|
|
189
|
+
expect(showsLink.classList.contains('active')).toBe(true);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
describe('default values', () => {
|
|
194
|
+
it('shows "Performer" when name is empty', async () => {
|
|
195
|
+
const { container } = render(Header, { ...defaultProps, name: '' });
|
|
196
|
+
const desktopButton = container.querySelector('.avatar-button--desktop');
|
|
197
|
+
|
|
198
|
+
await fireEvent.click(desktopButton);
|
|
199
|
+
|
|
200
|
+
expect(screen.getByText('Performer')).toBeTruthy();
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
});
|
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
<script module>
|
|
2
|
-
import { defineMeta } from "@storybook/addon-svelte-csf";
|
|
3
|
-
|
|
4
|
-
import Header from "./Header.svelte";
|
|
5
|
-
|
|
6
|
-
const { Story } = defineMeta({
|
|
7
|
-
title: "Components/Layout/Header",
|
|
8
|
-
component: Header,
|
|
9
|
-
argTypes: {
|
|
10
|
-
name: { control: "text" },
|
|
11
|
-
email: { control: "text" },
|
|
12
|
-
avatar: { control: "text" },
|
|
13
|
-
signoutHandler: { action: "signout" },
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
function handleSignout() {
|
|
18
|
-
alert("User signed out");
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
</script>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
<Story
|
|
25
|
-
name="Default Header"
|
|
26
|
-
args={{
|
|
27
|
-
name: "John Performer",
|
|
28
|
-
email: "john@example.com",
|
|
29
|
-
avatar: "https://i.pravatar.cc/150?img=12",
|
|
30
|
-
signoutHandler: handleSignout
|
|
31
|
-
}}
|
|
32
|
-
/>
|
|
33
|
-
|
|
34
|
-
<Story name="With Long Name">
|
|
35
|
-
<Header
|
|
36
|
-
name="Alexander Christopher Wellington"
|
|
37
|
-
email="alexander.wellington@performersportal.com"
|
|
38
|
-
avatar="https://i.pravatar.cc/150?img=33"
|
|
39
|
-
signoutHandler={handleSignout}
|
|
40
|
-
/>
|
|
41
|
-
</Story>
|
|
42
|
-
|
|
43
|
-
<Story name="With Short Name">
|
|
44
|
-
<Header
|
|
45
|
-
name="Jo"
|
|
46
|
-
email="jo@test.com"
|
|
47
|
-
avatar="https://i.pravatar.cc/150?img=5"
|
|
48
|
-
signoutHandler={handleSignout}
|
|
49
|
-
/>
|
|
50
|
-
</Story>
|
|
51
|
-
|
|
52
|
-
<Story name="Female Performer">
|
|
53
|
-
<Header
|
|
54
|
-
name="Sarah Johnson"
|
|
55
|
-
email="sarah.johnson@comedy.com"
|
|
56
|
-
avatar="https://i.pravatar.cc/150?img=47"
|
|
57
|
-
signoutHandler={handleSignout}
|
|
58
|
-
/>
|
|
59
|
-
</Story>
|
|
60
|
-
|
|
61
|
-
<Story name="Without Email">
|
|
62
|
-
<Header
|
|
63
|
-
name="Anonymous Performer"
|
|
64
|
-
email=""
|
|
65
|
-
avatar="https://i.pravatar.cc/150?img=68"
|
|
66
|
-
signoutHandler={handleSignout}
|
|
67
|
-
/>
|
|
68
|
-
</Story>
|
|
69
|
-
|
|
70
|
-
<Story name="With Default Avatar">
|
|
71
|
-
<Header
|
|
72
|
-
name="Default User"
|
|
73
|
-
email="default@performers.com"
|
|
74
|
-
avatar=""
|
|
75
|
-
signoutHandler={handleSignout}
|
|
76
|
-
/>
|
|
77
|
-
</Story>
|
|
1
|
+
<script module>
|
|
2
|
+
import { defineMeta } from "@storybook/addon-svelte-csf";
|
|
3
|
+
|
|
4
|
+
import Header from "./Header.svelte";
|
|
5
|
+
|
|
6
|
+
const { Story } = defineMeta({
|
|
7
|
+
title: "Components/Layout/Header",
|
|
8
|
+
component: Header,
|
|
9
|
+
argTypes: {
|
|
10
|
+
name: { control: "text" },
|
|
11
|
+
email: { control: "text" },
|
|
12
|
+
avatar: { control: "text" },
|
|
13
|
+
signoutHandler: { action: "signout" },
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
function handleSignout() {
|
|
18
|
+
alert("User signed out");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
<Story
|
|
25
|
+
name="Default Header"
|
|
26
|
+
args={{
|
|
27
|
+
name: "John Performer",
|
|
28
|
+
email: "john@example.com",
|
|
29
|
+
avatar: "https://i.pravatar.cc/150?img=12",
|
|
30
|
+
signoutHandler: handleSignout
|
|
31
|
+
}}
|
|
32
|
+
/>
|
|
33
|
+
|
|
34
|
+
<Story name="With Long Name">
|
|
35
|
+
<Header
|
|
36
|
+
name="Alexander Christopher Wellington"
|
|
37
|
+
email="alexander.wellington@performersportal.com"
|
|
38
|
+
avatar="https://i.pravatar.cc/150?img=33"
|
|
39
|
+
signoutHandler={handleSignout}
|
|
40
|
+
/>
|
|
41
|
+
</Story>
|
|
42
|
+
|
|
43
|
+
<Story name="With Short Name">
|
|
44
|
+
<Header
|
|
45
|
+
name="Jo"
|
|
46
|
+
email="jo@test.com"
|
|
47
|
+
avatar="https://i.pravatar.cc/150?img=5"
|
|
48
|
+
signoutHandler={handleSignout}
|
|
49
|
+
/>
|
|
50
|
+
</Story>
|
|
51
|
+
|
|
52
|
+
<Story name="Female Performer">
|
|
53
|
+
<Header
|
|
54
|
+
name="Sarah Johnson"
|
|
55
|
+
email="sarah.johnson@comedy.com"
|
|
56
|
+
avatar="https://i.pravatar.cc/150?img=47"
|
|
57
|
+
signoutHandler={handleSignout}
|
|
58
|
+
/>
|
|
59
|
+
</Story>
|
|
60
|
+
|
|
61
|
+
<Story name="Without Email">
|
|
62
|
+
<Header
|
|
63
|
+
name="Anonymous Performer"
|
|
64
|
+
email=""
|
|
65
|
+
avatar="https://i.pravatar.cc/150?img=68"
|
|
66
|
+
signoutHandler={handleSignout}
|
|
67
|
+
/>
|
|
68
|
+
</Story>
|
|
69
|
+
|
|
70
|
+
<Story name="With Default Avatar">
|
|
71
|
+
<Header
|
|
72
|
+
name="Default User"
|
|
73
|
+
email="default@performers.com"
|
|
74
|
+
avatar=""
|
|
75
|
+
signoutHandler={handleSignout}
|
|
76
|
+
/>
|
|
77
|
+
</Story>
|