@getmicdrop/svelte-components 2.0.4 → 2.0.6

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.
Files changed (107) hide show
  1. package/dist/components/Alert/Alert.spec.js +170 -170
  2. package/dist/components/Badges/Badge.spec.js +103 -103
  3. package/dist/components/BottomSheet/BottomSheet.spec.js +127 -127
  4. package/dist/components/Breadcrumb/Breadcrumb.spec.js +120 -120
  5. package/dist/components/Button/Button.spec.js +211 -211
  6. package/dist/components/Button/ButtonSaveDemo.spec.js +48 -48
  7. package/dist/components/Calendar/Calendar.spec.js +131 -131
  8. package/dist/components/Calendar/QuarterView.spec.js +394 -394
  9. package/dist/components/Card.spec.js +47 -47
  10. package/dist/components/CropImage/CropImage.spec.js +216 -216
  11. package/dist/components/DarkModeToggle.spec.js +357 -357
  12. package/dist/components/ErrorDisplay.spec.js +69 -69
  13. package/dist/components/FormActions.spec.js +88 -88
  14. package/dist/components/FormValidationSummary.spec.js +203 -203
  15. package/dist/components/Icons/Icon.spec.js +175 -175
  16. package/dist/components/Icons/MoreHori.spec.js +67 -67
  17. package/dist/components/Icons/WarningIcon.spec.js +30 -30
  18. package/dist/components/Input/Input.spec.js +573 -573
  19. package/dist/components/Input/MultiSelect.spec.js +257 -257
  20. package/dist/components/Input/OTPInput.spec.js +238 -238
  21. package/dist/components/Input/Select.spec.js +218 -218
  22. package/dist/components/Layout/BottomNav.spec.js +130 -130
  23. package/dist/components/Layout/Header.spec.js +203 -203
  24. package/dist/components/Modal/ConfirmationModal.spec.js +191 -191
  25. package/dist/components/Modal/Modal.spec.js +95 -95
  26. package/dist/components/Modal/ModalStateManager.spec.js +100 -100
  27. package/dist/components/PageLoader.spec.js +54 -54
  28. package/dist/components/PasswordStrengthIndicator/PasswordStrengthIndicator.spec.js +173 -173
  29. package/dist/components/PlaceAutocomplete/PlaceAutocomplete.spec.js +300 -300
  30. package/dist/components/Spinner/Spinner.spec.js +75 -75
  31. package/dist/components/StatusIndicator/StatusIndicator.spec.js +129 -129
  32. package/dist/components/Toaster/Toaster.stories.svelte +1 -1
  33. package/dist/components/Toggle.spec.js +158 -158
  34. package/dist/components/ValidationError.spec.js +79 -79
  35. package/dist/components/pages/performers/AvailabilityCalendarModal.spec.js +606 -606
  36. package/dist/components/pages/performers/AvailabilityCalendarModal.svelte +4 -4
  37. package/dist/components/pages/performers/ModalShowInfo.spec.js +124 -124
  38. package/dist/components/pages/performers/ModalShowInfo.svelte +1 -1
  39. package/dist/components/pages/performers/PageBackButton.spec.js +89 -89
  40. package/dist/components/pages/performers/SectionHeader.spec.js +75 -75
  41. package/dist/components/pages/performers/ShowDetails.spec.js +166 -166
  42. package/dist/components/pages/performers/ShowItemCard.spec.js +793 -793
  43. package/dist/components/pages/performers/ShowItemCard.svelte +4 -4
  44. package/dist/components/pages/performers/SwitchOption.spec.js +127 -127
  45. package/dist/components/pages/performers/VenueInfo.spec.js +167 -167
  46. package/dist/components/pages/performers/VenueInfo.svelte +1 -1
  47. package/dist/components/pages/performers/VenueItemCard.spec.js +763 -763
  48. package/dist/components/pages/performers/VenueItemCard.svelte +4 -4
  49. package/dist/components/pages/profile/profile-form.spec.js +9 -9
  50. package/dist/components/pages/settings/tabs/CustomImageDropzone.svelte +3 -3
  51. package/dist/components/pages/shows/ShowList.spec.js +33 -33
  52. package/dist/components/pages/shows/TabContent.spec.js +90 -90
  53. package/dist/components/pages/shows/TabNavigation.spec.js +143 -143
  54. package/dist/config.js +5 -5
  55. package/dist/config.spec.js +29 -29
  56. package/dist/constants/formOptions.js +25 -25
  57. package/dist/constants/formOptions.spec.js +88 -88
  58. package/dist/index.js +111 -111
  59. package/dist/stores/auth.d.ts +9 -0
  60. package/dist/stores/auth.d.ts.map +1 -0
  61. package/dist/stores/auth.js +36 -0
  62. package/dist/stores/auth.spec.d.ts +2 -0
  63. package/dist/stores/auth.spec.d.ts.map +1 -0
  64. package/dist/stores/auth.spec.js +139 -0
  65. package/dist/stores/formDataStore.d.ts +17 -0
  66. package/dist/stores/formDataStore.d.ts.map +1 -0
  67. package/dist/stores/formDataStore.js +25 -0
  68. package/dist/stores/formDataStore.spec.d.ts +2 -0
  69. package/dist/stores/formDataStore.spec.d.ts.map +1 -0
  70. package/dist/stores/formDataStore.spec.js +257 -0
  71. package/dist/stores/formSave.d.ts +24 -0
  72. package/dist/stores/formSave.d.ts.map +1 -0
  73. package/dist/stores/formSave.js +132 -0
  74. package/dist/stores/formSave.spec.d.ts +2 -0
  75. package/dist/stores/formSave.spec.d.ts.map +1 -0
  76. package/dist/stores/formSave.spec.js +296 -0
  77. package/dist/stores/index.d.ts +1 -0
  78. package/dist/stores/index.d.ts.map +1 -0
  79. package/dist/stores/index.js +0 -0
  80. package/dist/stores/navigation.d.ts +5 -0
  81. package/dist/stores/navigation.d.ts.map +1 -0
  82. package/dist/stores/navigation.js +12 -0
  83. package/dist/stores/navigation.spec.d.ts +2 -0
  84. package/dist/stores/navigation.spec.d.ts.map +1 -0
  85. package/dist/stores/navigation.spec.js +136 -0
  86. package/dist/stores/toaster.d.ts +4 -0
  87. package/dist/stores/toaster.d.ts.map +1 -0
  88. package/dist/stores/toaster.js +13 -0
  89. package/dist/stores/toaster.spec.d.ts +2 -0
  90. package/dist/stores/toaster.spec.d.ts.map +1 -0
  91. package/dist/stores/toaster.spec.js +59 -0
  92. package/dist/telemetry.js +357 -357
  93. package/dist/telemetry.server.js +211 -211
  94. package/dist/telemetry.server.spec.js +434 -434
  95. package/dist/telemetry.spec.js +660 -660
  96. package/dist/utils/apiConfig.js +49 -49
  97. package/dist/utils/apiConfig.spec.js +118 -118
  98. package/dist/utils/greetings.js +187 -187
  99. package/dist/utils/greetings.spec.js +337 -337
  100. package/dist/utils/imageValidation.js +121 -121
  101. package/dist/utils/imageValidation.spec.js +220 -220
  102. package/dist/utils/portal.js +25 -25
  103. package/dist/utils/portal.spec.js +143 -143
  104. package/dist/utils/utils/utils.js +323 -323
  105. package/dist/utils/utils/utils.spec.js +698 -698
  106. package/dist/utils/utils.spec.js +643 -643
  107. package/package.json +1 -1
@@ -1,100 +1,100 @@
1
- import { render, screen } from "@testing-library/svelte";
2
- import userEvent from "@testing-library/user-event";
3
- import { expect, describe, test, vi } from "vitest";
4
- import ModalStateManager from "./ModalStateManager.svelte";
5
-
6
- describe("ModalStateManager Component Tests", () => {
7
- test("Shows processing state when isProcessing is true", () => {
8
- render(ModalStateManager, {
9
- props: { isProcessing: true, isSuccess: false },
10
- });
11
- expect(screen.getByText("Processing your request")).toBeInTheDocument();
12
- });
13
-
14
- test("Shows custom processing message", () => {
15
- render(ModalStateManager, {
16
- props: {
17
- isProcessing: true,
18
- isSuccess: false,
19
- processingMessage: "Please wait...",
20
- },
21
- });
22
- expect(screen.getByText("Please wait...")).toBeInTheDocument();
23
- });
24
-
25
- test("Shows success state when isSuccess is true", () => {
26
- render(ModalStateManager, {
27
- props: { isProcessing: false, isSuccess: true, successTitle: "Done!" },
28
- });
29
- expect(screen.getByText("Done!")).toBeInTheDocument();
30
- });
31
-
32
- test("Shows success message when provided", () => {
33
- render(ModalStateManager, {
34
- props: {
35
- isProcessing: false,
36
- isSuccess: true,
37
- successTitle: "Success",
38
- successMessage: "Your action was completed.",
39
- },
40
- });
41
- expect(screen.getByText("Your action was completed.")).toBeInTheDocument();
42
- });
43
-
44
- test("Shows continue button in success state", () => {
45
- render(ModalStateManager, {
46
- props: { isProcessing: false, isSuccess: true },
47
- });
48
- expect(screen.getByText("Continue")).toBeInTheDocument();
49
- });
50
-
51
- test("Uses custom success button text", () => {
52
- render(ModalStateManager, {
53
- props: {
54
- isProcessing: false,
55
- isSuccess: true,
56
- successButtonText: "Close",
57
- },
58
- });
59
- expect(screen.getByText("Close")).toBeInTheDocument();
60
- });
61
-
62
- test("Calls onSuccessClose when success button clicked", async () => {
63
- const user = userEvent.setup();
64
- const onSuccessClose = vi.fn();
65
-
66
- render(ModalStateManager, {
67
- props: { isProcessing: false, isSuccess: true, onSuccessClose },
68
- });
69
-
70
- await user.click(screen.getByText("Continue"));
71
- expect(onSuccessClose).toHaveBeenCalledTimes(1);
72
- });
73
-
74
- test("Processing state shows spinner animation", () => {
75
- const { container } = render(ModalStateManager, {
76
- props: { isProcessing: true, isSuccess: false },
77
- });
78
- const spinner = container.querySelector(".animate-spin");
79
- expect(spinner).toBeInTheDocument();
80
- });
81
-
82
- test("Processing state has orange background", () => {
83
- const { container } = render(ModalStateManager, {
84
- props: { isProcessing: true, isSuccess: false },
85
- });
86
- const spinnerBg = container.querySelector(".bg-orange-300");
87
- expect(spinnerBg).toBeInTheDocument();
88
- });
89
-
90
- test("Success state priority over processing", () => {
91
- // When both are true, success should show
92
- render(ModalStateManager, {
93
- props: { isProcessing: true, isSuccess: true, successTitle: "Complete" },
94
- });
95
- expect(screen.getByText("Complete")).toBeInTheDocument();
96
- expect(
97
- screen.queryByText("Processing your request")
98
- ).not.toBeInTheDocument();
99
- });
100
- });
1
+ import { render, screen } from "@testing-library/svelte";
2
+ import userEvent from "@testing-library/user-event";
3
+ import { expect, describe, test, vi } from "vitest";
4
+ import ModalStateManager from "./ModalStateManager.svelte";
5
+
6
+ describe("ModalStateManager Component Tests", () => {
7
+ test("Shows processing state when isProcessing is true", () => {
8
+ render(ModalStateManager, {
9
+ props: { isProcessing: true, isSuccess: false },
10
+ });
11
+ expect(screen.getByText("Processing your request")).toBeInTheDocument();
12
+ });
13
+
14
+ test("Shows custom processing message", () => {
15
+ render(ModalStateManager, {
16
+ props: {
17
+ isProcessing: true,
18
+ isSuccess: false,
19
+ processingMessage: "Please wait...",
20
+ },
21
+ });
22
+ expect(screen.getByText("Please wait...")).toBeInTheDocument();
23
+ });
24
+
25
+ test("Shows success state when isSuccess is true", () => {
26
+ render(ModalStateManager, {
27
+ props: { isProcessing: false, isSuccess: true, successTitle: "Done!" },
28
+ });
29
+ expect(screen.getByText("Done!")).toBeInTheDocument();
30
+ });
31
+
32
+ test("Shows success message when provided", () => {
33
+ render(ModalStateManager, {
34
+ props: {
35
+ isProcessing: false,
36
+ isSuccess: true,
37
+ successTitle: "Success",
38
+ successMessage: "Your action was completed.",
39
+ },
40
+ });
41
+ expect(screen.getByText("Your action was completed.")).toBeInTheDocument();
42
+ });
43
+
44
+ test("Shows continue button in success state", () => {
45
+ render(ModalStateManager, {
46
+ props: { isProcessing: false, isSuccess: true },
47
+ });
48
+ expect(screen.getByText("Continue")).toBeInTheDocument();
49
+ });
50
+
51
+ test("Uses custom success button text", () => {
52
+ render(ModalStateManager, {
53
+ props: {
54
+ isProcessing: false,
55
+ isSuccess: true,
56
+ successButtonText: "Close",
57
+ },
58
+ });
59
+ expect(screen.getByText("Close")).toBeInTheDocument();
60
+ });
61
+
62
+ test("Calls onSuccessClose when success button clicked", async () => {
63
+ const user = userEvent.setup();
64
+ const onSuccessClose = vi.fn();
65
+
66
+ render(ModalStateManager, {
67
+ props: { isProcessing: false, isSuccess: true, onSuccessClose },
68
+ });
69
+
70
+ await user.click(screen.getByText("Continue"));
71
+ expect(onSuccessClose).toHaveBeenCalledTimes(1);
72
+ });
73
+
74
+ test("Processing state shows spinner animation", () => {
75
+ const { container } = render(ModalStateManager, {
76
+ props: { isProcessing: true, isSuccess: false },
77
+ });
78
+ const spinner = container.querySelector(".animate-spin");
79
+ expect(spinner).toBeInTheDocument();
80
+ });
81
+
82
+ test("Processing state has orange background", () => {
83
+ const { container } = render(ModalStateManager, {
84
+ props: { isProcessing: true, isSuccess: false },
85
+ });
86
+ const spinnerBg = container.querySelector(".bg-orange-300");
87
+ expect(spinnerBg).toBeInTheDocument();
88
+ });
89
+
90
+ test("Success state priority over processing", () => {
91
+ // When both are true, success should show
92
+ render(ModalStateManager, {
93
+ props: { isProcessing: true, isSuccess: true, successTitle: "Complete" },
94
+ });
95
+ expect(screen.getByText("Complete")).toBeInTheDocument();
96
+ expect(
97
+ screen.queryByText("Processing your request")
98
+ ).not.toBeInTheDocument();
99
+ });
100
+ });
@@ -1,54 +1,54 @@
1
- import { render, screen } from "@testing-library/svelte";
2
- import { expect, describe, test } from "vitest";
3
- import PageLoader from "./PageLoader.svelte";
4
-
5
- describe("PageLoader Component Tests", () => {
6
- test("Shows spinner when loading", () => {
7
- render(PageLoader, { props: { isLoading: true } });
8
- expect(screen.getByRole("status")).toBeInTheDocument();
9
- });
10
-
11
- test("Shows error alert when error is set", () => {
12
- render(PageLoader, {
13
- props: { isLoading: false, error: "Something went wrong" },
14
- });
15
- expect(screen.getByRole("alert")).toBeInTheDocument();
16
- expect(screen.getByText("Something went wrong")).toBeInTheDocument();
17
- });
18
-
19
- test("Shows custom error title", () => {
20
- render(PageLoader, {
21
- props: {
22
- isLoading: false,
23
- error: "Failed",
24
- errorTitle: "Loading Error",
25
- },
26
- });
27
- expect(screen.getByText("Loading Error")).toBeInTheDocument();
28
- });
29
-
30
- test("Does not show spinner when not loading", () => {
31
- render(PageLoader, { props: { isLoading: false } });
32
- expect(screen.queryByRole("status")).not.toBeInTheDocument();
33
- });
34
-
35
- test("Does not show error when no error", () => {
36
- render(PageLoader, { props: { isLoading: false, error: null } });
37
- expect(screen.queryByRole("alert")).not.toBeInTheDocument();
38
- });
39
-
40
- test("Has custom min height class", () => {
41
- const { container } = render(PageLoader, {
42
- props: { isLoading: true, minHeight: "h-96" },
43
- });
44
- const loadingDiv = container.querySelector(".h-96");
45
- expect(loadingDiv).toBeInTheDocument();
46
- });
47
-
48
- test("Shows loading message when provided", () => {
49
- render(PageLoader, {
50
- props: { isLoading: true, loadingMessage: "Please wait..." },
51
- });
52
- expect(screen.getByText("Please wait...")).toBeInTheDocument();
53
- });
54
- });
1
+ import { render, screen } from "@testing-library/svelte";
2
+ import { expect, describe, test } from "vitest";
3
+ import PageLoader from "./PageLoader.svelte";
4
+
5
+ describe("PageLoader Component Tests", () => {
6
+ test("Shows spinner when loading", () => {
7
+ render(PageLoader, { props: { isLoading: true } });
8
+ expect(screen.getByRole("status")).toBeInTheDocument();
9
+ });
10
+
11
+ test("Shows error alert when error is set", () => {
12
+ render(PageLoader, {
13
+ props: { isLoading: false, error: "Something went wrong" },
14
+ });
15
+ expect(screen.getByRole("alert")).toBeInTheDocument();
16
+ expect(screen.getByText("Something went wrong")).toBeInTheDocument();
17
+ });
18
+
19
+ test("Shows custom error title", () => {
20
+ render(PageLoader, {
21
+ props: {
22
+ isLoading: false,
23
+ error: "Failed",
24
+ errorTitle: "Loading Error",
25
+ },
26
+ });
27
+ expect(screen.getByText("Loading Error")).toBeInTheDocument();
28
+ });
29
+
30
+ test("Does not show spinner when not loading", () => {
31
+ render(PageLoader, { props: { isLoading: false } });
32
+ expect(screen.queryByRole("status")).not.toBeInTheDocument();
33
+ });
34
+
35
+ test("Does not show error when no error", () => {
36
+ render(PageLoader, { props: { isLoading: false, error: null } });
37
+ expect(screen.queryByRole("alert")).not.toBeInTheDocument();
38
+ });
39
+
40
+ test("Has custom min height class", () => {
41
+ const { container } = render(PageLoader, {
42
+ props: { isLoading: true, minHeight: "h-96" },
43
+ });
44
+ const loadingDiv = container.querySelector(".h-96");
45
+ expect(loadingDiv).toBeInTheDocument();
46
+ });
47
+
48
+ test("Shows loading message when provided", () => {
49
+ render(PageLoader, {
50
+ props: { isLoading: true, loadingMessage: "Please wait..." },
51
+ });
52
+ expect(screen.getByText("Please wait...")).toBeInTheDocument();
53
+ });
54
+ });
@@ -1,173 +1,173 @@
1
- import { render, screen, waitFor } from "@testing-library/svelte";
2
- import { expect, describe, test, vi } from "vitest";
3
- import PasswordStrengthIndicator from "./PasswordStrengthIndicator.svelte";
4
-
5
- // Debounce delay + buffer
6
- const DEBOUNCE_WAIT = 500;
7
-
8
- function setupTest(args = {}) {
9
- const { component, container } = render(PasswordStrengthIndicator, {
10
- props: {
11
- password: "",
12
- ...args,
13
- },
14
- });
15
- return { component, container };
16
- }
17
-
18
- describe("PasswordStrengthIndicator Component Tests", () => {
19
- test("Does not render when password is empty", () => {
20
- const { container } = setupTest({ password: "" });
21
- const indicator = container.querySelector(".pt-2");
22
- expect(indicator).not.toBeInTheDocument();
23
- });
24
-
25
- test("Renders after debounce when password has value", async () => {
26
- const { container } = setupTest({ password: "test" });
27
- await waitFor(
28
- () => {
29
- const indicator = container.querySelector(".pt-2");
30
- expect(indicator).toBeInTheDocument();
31
- },
32
- { timeout: DEBOUNCE_WAIT }
33
- );
34
- });
35
-
36
- test("Has three strength bars", async () => {
37
- const { container } = setupTest({ password: "test" });
38
- await waitFor(
39
- () => {
40
- const bars = container.querySelectorAll(".h-1.flex-1.rounded-full");
41
- expect(bars.length).toBe(3);
42
- },
43
- { timeout: DEBOUNCE_WAIT }
44
- );
45
- });
46
-
47
- test("Shows filled bars for weak password", async () => {
48
- const { container } = setupTest({ password: "ab" });
49
- await waitFor(
50
- () => {
51
- // At least one bar should be filled with a color
52
- const coloredBars = container.querySelectorAll(
53
- ".bg-accent-Danger, .bg-accent-success"
54
- );
55
- expect(coloredBars.length).toBeGreaterThan(0);
56
- },
57
- { timeout: DEBOUNCE_WAIT }
58
- );
59
- });
60
-
61
- test("Shows filled bars for good password", async () => {
62
- const { container } = setupTest({ password: "Abc12345" });
63
- await waitFor(
64
- () => {
65
- // All 3 bars should be filled for a good password
66
- const successBars = container.querySelectorAll(".bg-accent-success");
67
- expect(successBars.length).toBe(3);
68
- },
69
- { timeout: DEBOUNCE_WAIT }
70
- );
71
- });
72
-
73
- test("Exports score prop", () => {
74
- const { component } = setupTest({ password: "test123" });
75
- // Score should be accessible
76
- expect(component).toBeDefined();
77
- });
78
-
79
- test("Exports strengthText prop", () => {
80
- const { component } = setupTest({ password: "test123" });
81
- expect(component).toBeDefined();
82
- });
83
-
84
- test("Exports textColor prop", () => {
85
- const { component } = setupTest({ password: "test123" });
86
- expect(component).toBeDefined();
87
- });
88
-
89
- test("Uses danger color for weak passwords", async () => {
90
- const { container } = setupTest({ password: "weak" });
91
- await waitFor(
92
- () => {
93
- const dangerBars = container.querySelectorAll(".bg-accent-Danger");
94
- expect(dangerBars.length).toBeGreaterThan(0);
95
- },
96
- { timeout: DEBOUNCE_WAIT }
97
- );
98
- });
99
-
100
- test("Uses success color for good/strong passwords", async () => {
101
- const { container } = setupTest({ password: "StrongP@ss123" });
102
- await waitFor(
103
- () => {
104
- const successBars = container.querySelectorAll(".bg-accent-success");
105
- expect(successBars.length).toBe(3);
106
- },
107
- { timeout: DEBOUNCE_WAIT }
108
- );
109
- });
110
-
111
- test("Has transition animation classes on bars", async () => {
112
- const { container } = setupTest({ password: "test" });
113
- await waitFor(
114
- () => {
115
- const bars = container.querySelectorAll(".h-1.flex-1.rounded-full");
116
- expect(bars.length).toBe(3);
117
- bars.forEach((bar) => {
118
- expect(bar).toHaveClass("transition-colors");
119
- expect(bar).toHaveClass("duration-300");
120
- });
121
- },
122
- { timeout: DEBOUNCE_WAIT }
123
- );
124
- });
125
-
126
- test("Very long password shows strong indicator", async () => {
127
- const { container } = setupTest({ password: "1234567890123" }); // 13 chars
128
- await waitFor(
129
- () => {
130
- const successBars = container.querySelectorAll(".bg-accent-success");
131
- expect(successBars.length).toBe(3);
132
- },
133
- { timeout: DEBOUNCE_WAIT }
134
- );
135
- });
136
- });
137
-
138
- describe("Password Strength Scoring", () => {
139
- test("Score 2+ (Good) shows 3 success bars - 8+ chars with 2 diversity", async () => {
140
- const { container } = setupTest({ password: "Abcdefgh" }); // Upper + lower
141
- await waitFor(
142
- () => {
143
- const successBars = container.querySelectorAll(".bg-accent-success");
144
- expect(successBars.length).toBe(3);
145
- },
146
- { timeout: DEBOUNCE_WAIT }
147
- );
148
- });
149
-
150
- test("Score 3 (Strong) - 10+ chars, multiple diversity", async () => {
151
- const { container } = setupTest({ password: "Abcdefgh1!" }); // Upper, lower, number, symbol
152
- await waitFor(
153
- () => {
154
- const successBars = container.querySelectorAll(".bg-accent-success");
155
- expect(successBars.length).toBe(3);
156
- },
157
- { timeout: DEBOUNCE_WAIT }
158
- );
159
- });
160
-
161
- test("Weak password shows danger color bars", async () => {
162
- const { container } = setupTest({ password: "abcdef" });
163
- await waitFor(
164
- () => {
165
- const coloredBars = container.querySelectorAll(
166
- ".bg-accent-Danger, .bg-accent-success"
167
- );
168
- expect(coloredBars.length).toBeGreaterThan(0);
169
- },
170
- { timeout: DEBOUNCE_WAIT }
171
- );
172
- });
173
- });
1
+ import { render, screen, waitFor } from "@testing-library/svelte";
2
+ import { expect, describe, test, vi } from "vitest";
3
+ import PasswordStrengthIndicator from "./PasswordStrengthIndicator.svelte";
4
+
5
+ // Debounce delay + buffer
6
+ const DEBOUNCE_WAIT = 500;
7
+
8
+ function setupTest(args = {}) {
9
+ const { component, container } = render(PasswordStrengthIndicator, {
10
+ props: {
11
+ password: "",
12
+ ...args,
13
+ },
14
+ });
15
+ return { component, container };
16
+ }
17
+
18
+ describe("PasswordStrengthIndicator Component Tests", () => {
19
+ test("Does not render when password is empty", () => {
20
+ const { container } = setupTest({ password: "" });
21
+ const indicator = container.querySelector(".pt-2");
22
+ expect(indicator).not.toBeInTheDocument();
23
+ });
24
+
25
+ test("Renders after debounce when password has value", async () => {
26
+ const { container } = setupTest({ password: "test" });
27
+ await waitFor(
28
+ () => {
29
+ const indicator = container.querySelector(".pt-2");
30
+ expect(indicator).toBeInTheDocument();
31
+ },
32
+ { timeout: DEBOUNCE_WAIT }
33
+ );
34
+ });
35
+
36
+ test("Has three strength bars", async () => {
37
+ const { container } = setupTest({ password: "test" });
38
+ await waitFor(
39
+ () => {
40
+ const bars = container.querySelectorAll(".h-1.flex-1.rounded-full");
41
+ expect(bars.length).toBe(3);
42
+ },
43
+ { timeout: DEBOUNCE_WAIT }
44
+ );
45
+ });
46
+
47
+ test("Shows filled bars for weak password", async () => {
48
+ const { container } = setupTest({ password: "ab" });
49
+ await waitFor(
50
+ () => {
51
+ // At least one bar should be filled with a color
52
+ const coloredBars = container.querySelectorAll(
53
+ ".bg-accent-Danger, .bg-accent-success"
54
+ );
55
+ expect(coloredBars.length).toBeGreaterThan(0);
56
+ },
57
+ { timeout: DEBOUNCE_WAIT }
58
+ );
59
+ });
60
+
61
+ test("Shows filled bars for good password", async () => {
62
+ const { container } = setupTest({ password: "Abc12345" });
63
+ await waitFor(
64
+ () => {
65
+ // All 3 bars should be filled for a good password
66
+ const successBars = container.querySelectorAll(".bg-accent-success");
67
+ expect(successBars.length).toBe(3);
68
+ },
69
+ { timeout: DEBOUNCE_WAIT }
70
+ );
71
+ });
72
+
73
+ test("Exports score prop", () => {
74
+ const { component } = setupTest({ password: "test123" });
75
+ // Score should be accessible
76
+ expect(component).toBeDefined();
77
+ });
78
+
79
+ test("Exports strengthText prop", () => {
80
+ const { component } = setupTest({ password: "test123" });
81
+ expect(component).toBeDefined();
82
+ });
83
+
84
+ test("Exports textColor prop", () => {
85
+ const { component } = setupTest({ password: "test123" });
86
+ expect(component).toBeDefined();
87
+ });
88
+
89
+ test("Uses danger color for weak passwords", async () => {
90
+ const { container } = setupTest({ password: "weak" });
91
+ await waitFor(
92
+ () => {
93
+ const dangerBars = container.querySelectorAll(".bg-accent-Danger");
94
+ expect(dangerBars.length).toBeGreaterThan(0);
95
+ },
96
+ { timeout: DEBOUNCE_WAIT }
97
+ );
98
+ });
99
+
100
+ test("Uses success color for good/strong passwords", async () => {
101
+ const { container } = setupTest({ password: "StrongP@ss123" });
102
+ await waitFor(
103
+ () => {
104
+ const successBars = container.querySelectorAll(".bg-accent-success");
105
+ expect(successBars.length).toBe(3);
106
+ },
107
+ { timeout: DEBOUNCE_WAIT }
108
+ );
109
+ });
110
+
111
+ test("Has transition animation classes on bars", async () => {
112
+ const { container } = setupTest({ password: "test" });
113
+ await waitFor(
114
+ () => {
115
+ const bars = container.querySelectorAll(".h-1.flex-1.rounded-full");
116
+ expect(bars.length).toBe(3);
117
+ bars.forEach((bar) => {
118
+ expect(bar).toHaveClass("transition-colors");
119
+ expect(bar).toHaveClass("duration-300");
120
+ });
121
+ },
122
+ { timeout: DEBOUNCE_WAIT }
123
+ );
124
+ });
125
+
126
+ test("Very long password shows strong indicator", async () => {
127
+ const { container } = setupTest({ password: "1234567890123" }); // 13 chars
128
+ await waitFor(
129
+ () => {
130
+ const successBars = container.querySelectorAll(".bg-accent-success");
131
+ expect(successBars.length).toBe(3);
132
+ },
133
+ { timeout: DEBOUNCE_WAIT }
134
+ );
135
+ });
136
+ });
137
+
138
+ describe("Password Strength Scoring", () => {
139
+ test("Score 2+ (Good) shows 3 success bars - 8+ chars with 2 diversity", async () => {
140
+ const { container } = setupTest({ password: "Abcdefgh" }); // Upper + lower
141
+ await waitFor(
142
+ () => {
143
+ const successBars = container.querySelectorAll(".bg-accent-success");
144
+ expect(successBars.length).toBe(3);
145
+ },
146
+ { timeout: DEBOUNCE_WAIT }
147
+ );
148
+ });
149
+
150
+ test("Score 3 (Strong) - 10+ chars, multiple diversity", async () => {
151
+ const { container } = setupTest({ password: "Abcdefgh1!" }); // Upper, lower, number, symbol
152
+ await waitFor(
153
+ () => {
154
+ const successBars = container.querySelectorAll(".bg-accent-success");
155
+ expect(successBars.length).toBe(3);
156
+ },
157
+ { timeout: DEBOUNCE_WAIT }
158
+ );
159
+ });
160
+
161
+ test("Weak password shows danger color bars", async () => {
162
+ const { container } = setupTest({ password: "abcdef" });
163
+ await waitFor(
164
+ () => {
165
+ const coloredBars = container.querySelectorAll(
166
+ ".bg-accent-Danger, .bg-accent-success"
167
+ );
168
+ expect(coloredBars.length).toBeGreaterThan(0);
169
+ },
170
+ { timeout: DEBOUNCE_WAIT }
171
+ );
172
+ });
173
+ });