@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.
- package/dist/components/Alert/Alert.spec.js +170 -170
- package/dist/components/Badges/Badge.spec.js +103 -103
- package/dist/components/BottomSheet/BottomSheet.spec.js +127 -127
- package/dist/components/Breadcrumb/Breadcrumb.spec.js +120 -120
- package/dist/components/Button/Button.spec.js +211 -211
- package/dist/components/Button/ButtonSaveDemo.spec.js +48 -48
- package/dist/components/Calendar/Calendar.spec.js +131 -131
- package/dist/components/Calendar/QuarterView.spec.js +394 -394
- package/dist/components/Card.spec.js +47 -47
- package/dist/components/CropImage/CropImage.spec.js +216 -216
- package/dist/components/DarkModeToggle.spec.js +357 -357
- package/dist/components/ErrorDisplay.spec.js +69 -69
- package/dist/components/FormActions.spec.js +88 -88
- package/dist/components/FormValidationSummary.spec.js +203 -203
- package/dist/components/Icons/Icon.spec.js +175 -175
- package/dist/components/Icons/MoreHori.spec.js +67 -67
- package/dist/components/Icons/WarningIcon.spec.js +30 -30
- package/dist/components/Input/Input.spec.js +573 -573
- package/dist/components/Input/MultiSelect.spec.js +257 -257
- package/dist/components/Input/OTPInput.spec.js +238 -238
- package/dist/components/Input/Select.spec.js +218 -218
- package/dist/components/Layout/BottomNav.spec.js +130 -130
- package/dist/components/Layout/Header.spec.js +203 -203
- package/dist/components/Modal/ConfirmationModal.spec.js +191 -191
- package/dist/components/Modal/Modal.spec.js +95 -95
- package/dist/components/Modal/ModalStateManager.spec.js +100 -100
- package/dist/components/PageLoader.spec.js +54 -54
- package/dist/components/PasswordStrengthIndicator/PasswordStrengthIndicator.spec.js +173 -173
- package/dist/components/PlaceAutocomplete/PlaceAutocomplete.spec.js +300 -300
- package/dist/components/Spinner/Spinner.spec.js +75 -75
- package/dist/components/StatusIndicator/StatusIndicator.spec.js +129 -129
- package/dist/components/Toaster/Toaster.stories.svelte +1 -1
- package/dist/components/Toggle.spec.js +158 -158
- package/dist/components/ValidationError.spec.js +79 -79
- package/dist/components/pages/performers/AvailabilityCalendarModal.spec.js +606 -606
- package/dist/components/pages/performers/AvailabilityCalendarModal.svelte +4 -4
- package/dist/components/pages/performers/ModalShowInfo.spec.js +124 -124
- package/dist/components/pages/performers/ModalShowInfo.svelte +1 -1
- package/dist/components/pages/performers/PageBackButton.spec.js +89 -89
- package/dist/components/pages/performers/SectionHeader.spec.js +75 -75
- package/dist/components/pages/performers/ShowDetails.spec.js +166 -166
- package/dist/components/pages/performers/ShowItemCard.spec.js +793 -793
- package/dist/components/pages/performers/ShowItemCard.svelte +4 -4
- package/dist/components/pages/performers/SwitchOption.spec.js +127 -127
- package/dist/components/pages/performers/VenueInfo.spec.js +167 -167
- package/dist/components/pages/performers/VenueInfo.svelte +1 -1
- package/dist/components/pages/performers/VenueItemCard.spec.js +763 -763
- package/dist/components/pages/performers/VenueItemCard.svelte +4 -4
- package/dist/components/pages/profile/profile-form.spec.js +9 -9
- package/dist/components/pages/settings/tabs/CustomImageDropzone.svelte +3 -3
- package/dist/components/pages/shows/ShowList.spec.js +33 -33
- package/dist/components/pages/shows/TabContent.spec.js +90 -90
- package/dist/components/pages/shows/TabNavigation.spec.js +143 -143
- package/dist/config.js +5 -5
- package/dist/config.spec.js +29 -29
- package/dist/constants/formOptions.js +25 -25
- package/dist/constants/formOptions.spec.js +88 -88
- package/dist/index.js +111 -111
- package/dist/stores/auth.d.ts +9 -0
- package/dist/stores/auth.d.ts.map +1 -0
- package/dist/stores/auth.js +36 -0
- package/dist/stores/auth.spec.d.ts +2 -0
- package/dist/stores/auth.spec.d.ts.map +1 -0
- package/dist/stores/auth.spec.js +139 -0
- package/dist/stores/formDataStore.d.ts +17 -0
- package/dist/stores/formDataStore.d.ts.map +1 -0
- package/dist/stores/formDataStore.js +25 -0
- package/dist/stores/formDataStore.spec.d.ts +2 -0
- package/dist/stores/formDataStore.spec.d.ts.map +1 -0
- package/dist/stores/formDataStore.spec.js +257 -0
- package/dist/stores/formSave.d.ts +24 -0
- package/dist/stores/formSave.d.ts.map +1 -0
- package/dist/stores/formSave.js +132 -0
- package/dist/stores/formSave.spec.d.ts +2 -0
- package/dist/stores/formSave.spec.d.ts.map +1 -0
- package/dist/stores/formSave.spec.js +296 -0
- package/dist/stores/index.d.ts +1 -0
- package/dist/stores/index.d.ts.map +1 -0
- package/dist/stores/index.js +0 -0
- package/dist/stores/navigation.d.ts +5 -0
- package/dist/stores/navigation.d.ts.map +1 -0
- package/dist/stores/navigation.js +12 -0
- package/dist/stores/navigation.spec.d.ts +2 -0
- package/dist/stores/navigation.spec.d.ts.map +1 -0
- package/dist/stores/navigation.spec.js +136 -0
- package/dist/stores/toaster.d.ts +4 -0
- package/dist/stores/toaster.d.ts.map +1 -0
- package/dist/stores/toaster.js +13 -0
- package/dist/stores/toaster.spec.d.ts +2 -0
- package/dist/stores/toaster.spec.d.ts.map +1 -0
- package/dist/stores/toaster.spec.js +59 -0
- package/dist/telemetry.js +357 -357
- package/dist/telemetry.server.js +211 -211
- package/dist/telemetry.server.spec.js +434 -434
- package/dist/telemetry.spec.js +660 -660
- package/dist/utils/apiConfig.js +49 -49
- package/dist/utils/apiConfig.spec.js +118 -118
- package/dist/utils/greetings.js +187 -187
- package/dist/utils/greetings.spec.js +337 -337
- package/dist/utils/imageValidation.js +121 -121
- package/dist/utils/imageValidation.spec.js +220 -220
- package/dist/utils/portal.js +25 -25
- package/dist/utils/portal.spec.js +143 -143
- package/dist/utils/utils/utils.js +323 -323
- package/dist/utils/utils/utils.spec.js +698 -698
- package/dist/utils/utils.spec.js +643 -643
- 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
|
+
});
|