@code-coaching/vuetiful 0.1.4 → 0.3.0

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 (70) hide show
  1. package/dist/style.css +2 -2
  2. package/dist/styles/all.css +323 -52
  3. package/dist/types/components/atoms/VButton.test.d.ts +1 -0
  4. package/dist/types/components/atoms/VButton.vue.d.ts +6 -72
  5. package/dist/types/components/index.d.ts +2 -1
  6. package/dist/types/components/index.test.d.ts +1 -0
  7. package/dist/types/components/molecules/VRail.vue.d.ts +51 -0
  8. package/dist/types/components/molecules/VRailTile.vue.d.ts +55 -0
  9. package/dist/types/components/molecules/VShell.vue.d.ts +78 -0
  10. package/dist/types/components/molecules/index.d.ts +4 -0
  11. package/dist/types/directives/clipboard.test.d.ts +1 -0
  12. package/dist/types/directives/index.d.ts +1 -1
  13. package/dist/types/index.d.ts +1 -1
  14. package/dist/types/index.test.d.ts +1 -0
  15. package/dist/types/services/index.d.ts +2 -0
  16. package/dist/types/services/rail.service.d.ts +4 -0
  17. package/dist/types/utils/code-block/code-block.vue.d.ts +2 -2
  18. package/dist/types/utils/code-block/highlight.service.test.d.ts +1 -0
  19. package/dist/types/utils/dark-mode/dark-mode.service.test.d.ts +1 -0
  20. package/dist/types/utils/dark-mode/dark-mode.vue.d.ts +3 -3
  21. package/dist/types/utils/index.d.ts +3 -3
  22. package/dist/types/utils/index.test.d.ts +1 -0
  23. package/dist/types/utils/platform/platform.service.test.d.ts +1 -0
  24. package/dist/types/utils/theme/callback.test.d.ts +1 -0
  25. package/dist/types/utils/theme/remove.test.d.ts +1 -0
  26. package/dist/types/utils/theme/theme-switcher.vue.d.ts +3 -3
  27. package/dist/types/utils/theme/{theme.d.ts → theme.service.d.ts} +2 -1
  28. package/dist/types/utils/theme/theme.service.test.d.ts +1 -0
  29. package/dist/vuetiful.es.mjs +658 -499
  30. package/dist/vuetiful.umd.js +13 -20
  31. package/package.json +8 -2
  32. package/src/components/atoms/VButton.test.ts +27 -0
  33. package/src/components/atoms/VButton.vue +19 -73
  34. package/src/components/index.test.ts +10 -0
  35. package/src/components/index.ts +2 -1
  36. package/src/components/molecules/VRail.vue +46 -0
  37. package/src/components/molecules/VRailTile.vue +75 -0
  38. package/src/components/molecules/VShell.vue +71 -0
  39. package/src/components/molecules/index.ts +5 -0
  40. package/src/directives/clipboard.test.ts +26 -0
  41. package/src/directives/index.ts +2 -4
  42. package/src/index.test.ts +26 -0
  43. package/src/index.ts +1 -1
  44. package/src/services/index.ts +3 -0
  45. package/src/services/rail.service.ts +11 -0
  46. package/src/styles/all.css +9 -6
  47. package/src/styles/transitions/fade.css +14 -0
  48. package/src/styles/transitions/slide.css +83 -0
  49. package/src/styles/transitions.css +2 -0
  50. package/src/utils/code-block/code-block.vue +1 -1
  51. package/src/utils/code-block/highlight.service.test.ts +24 -0
  52. package/src/utils/dark-mode/dark-mode.service.test.ts +234 -0
  53. package/src/utils/dark-mode/{dark-mode.ts → dark-mode.service.ts} +5 -4
  54. package/src/utils/dark-mode/dark-mode.vue +1 -1
  55. package/src/utils/index.test.ts +11 -0
  56. package/src/utils/index.ts +3 -4
  57. package/src/utils/platform/platform.service.test.ts +19 -0
  58. package/src/utils/theme/callback.test.ts +24 -0
  59. package/src/utils/theme/remove.test.ts +25 -0
  60. package/src/utils/theme/theme.service.test.ts +160 -0
  61. package/src/utils/theme/{theme.ts → theme.service.ts} +6 -7
  62. package/dist/types/constants/MyConstants.d.ts +0 -1
  63. package/dist/types/constants/index.d.ts +0 -2
  64. package/src/constants/MyConstants.ts +0 -1
  65. package/src/constants/index.ts +0 -5
  66. /package/dist/types/utils/code-block/{highlight.d.ts → highlight.service.d.ts} +0 -0
  67. /package/dist/types/utils/dark-mode/{dark-mode.d.ts → dark-mode.service.d.ts} +0 -0
  68. /package/dist/types/utils/platform/{platform.d.ts → platform.service.d.ts} +0 -0
  69. /package/src/utils/code-block/{highlight.ts → highlight.service.ts} +0 -0
  70. /package/src/utils/platform/{platform.ts → platform.service.ts} +0 -0
@@ -0,0 +1,234 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+
3
+ const localStorageMock = {
4
+ getItem: vi.fn(),
5
+ setItem: vi.fn(),
6
+ };
7
+ const matchMediaMock = (matches: boolean) => vi.fn(() => ({ matches, onchange: vi.fn() }));
8
+
9
+ describe("useDarkMode", () => {
10
+ afterEach(() => {
11
+ vi.resetModules();
12
+ });
13
+ describe("getModeUserPrefers", () => {
14
+ describe("given not in browser", () => {
15
+ it("should return default modeUserPrefers", async () => {
16
+ const platform = await import("../platform/platform.service");
17
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: false });
18
+
19
+ const { useDarkMode } = await import("./dark-mode.service");
20
+ const { getModeUserPrefers } = useDarkMode();
21
+ expect(getModeUserPrefers()).toBe(undefined);
22
+ });
23
+ });
24
+
25
+ describe("given in browser", () => {
26
+ describe("given no modeUserPrefers in localStorage", () => {
27
+ it("should return default modeUserPrefers", async () => {
28
+ const platform = await import("../platform/platform.service");
29
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: true });
30
+
31
+ const { useDarkMode } = await import("./dark-mode.service");
32
+ const { getModeUserPrefers } = useDarkMode();
33
+
34
+ window.localStorage = localStorageMock as any;
35
+ vi.spyOn(window.localStorage, "getItem").mockReturnValueOnce(null);
36
+
37
+ expect(getModeUserPrefers()).toBe(undefined);
38
+ });
39
+ });
40
+ describe("given modeUserPrefers in localStorage", () => {
41
+ it("should return the value", async () => {
42
+ const platform = await import("../platform/platform.service");
43
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: true });
44
+
45
+ const { useDarkMode } = await import("./dark-mode.service");
46
+ const { getModeUserPrefers } = useDarkMode();
47
+
48
+ window.localStorage = localStorageMock as any;
49
+ vi.spyOn(window.localStorage, "getItem").mockReturnValueOnce("true");
50
+
51
+ expect(getModeUserPrefers()).toBe(true);
52
+ });
53
+ });
54
+ });
55
+ });
56
+
57
+ describe("getModeOsPrefers", () => {
58
+ describe("given not in browser", () => {
59
+ it("should return default modeOsPrefers", async () => {
60
+ const platform = await import("../platform/platform.service");
61
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: false });
62
+
63
+ const { useDarkMode } = await import("./dark-mode.service");
64
+ const { getModeOsPrefers } = useDarkMode();
65
+ expect(getModeOsPrefers()).toBe(false);
66
+ });
67
+ });
68
+
69
+ describe("given in browser", () => {
70
+ describe("given prefers-color-scheme: light", () => {
71
+ it("should return true", async () => {
72
+ const platform = await import("../platform/platform.service");
73
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: true });
74
+ const localStorageSpy = vi.spyOn(window.localStorage, "setItem");
75
+
76
+ const { useDarkMode } = await import("./dark-mode.service");
77
+ const { getModeOsPrefers, MODE } = useDarkMode();
78
+
79
+ window.matchMedia = matchMediaMock(MODE.LIGHT) as any;
80
+ expect(getModeOsPrefers()).toBe(MODE.LIGHT);
81
+ expect(localStorageSpy).toHaveBeenCalledWith("modeOsPrefers", "true");
82
+ });
83
+ });
84
+ describe("given prefers-color-scheme: dark", () => {
85
+ it("should return false", async () => {
86
+ const platform = await import("../platform/platform.service");
87
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: true });
88
+ const localStorageSpy = vi.spyOn(window.localStorage, "setItem");
89
+
90
+ const { useDarkMode } = await import("./dark-mode.service");
91
+ const { getModeOsPrefers, MODE } = useDarkMode();
92
+
93
+ window.matchMedia = matchMediaMock(MODE.DARK) as any;
94
+ expect(getModeOsPrefers()).toBe(MODE.DARK);
95
+ expect(localStorageSpy).toHaveBeenCalledWith("modeOsPrefers", "false");
96
+ });
97
+ });
98
+ });
99
+ });
100
+
101
+ describe("getModeAutoPrefers", () => {
102
+ describe("given not in browser", () => {
103
+ it("should return default modeAutoPrefers", async () => {
104
+ const platform = await import("../platform/platform.service");
105
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: false });
106
+
107
+ const { useDarkMode } = await import("./dark-mode.service");
108
+ const { getModeAutoPrefers } = useDarkMode();
109
+ expect(getModeAutoPrefers()).toBe(false);
110
+ });
111
+ });
112
+
113
+ describe("given in browser", () => {
114
+ describe("given no modeUserPrefers in localStorage", () => {
115
+ it("should return default modeAutoPrefers", async () => {
116
+ const platform = await import("../platform/platform.service");
117
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: true });
118
+
119
+ const { useDarkMode } = await import("./dark-mode.service");
120
+ const { getModeAutoPrefers } = useDarkMode();
121
+
122
+ window.localStorage = localStorageMock as any;
123
+ vi.spyOn(window.localStorage, "getItem").mockReturnValueOnce(null);
124
+
125
+ expect(getModeAutoPrefers()).toBe(false);
126
+ });
127
+ });
128
+ describe("given modeUserPrefers in localStorage", () => {
129
+ it("should return the value", async () => {
130
+ const platform = await import("../platform/platform.service");
131
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: true });
132
+
133
+ const { useDarkMode } = await import("./dark-mode.service");
134
+ const { getModeAutoPrefers } = useDarkMode();
135
+
136
+ window.localStorage = localStorageMock as any;
137
+ vi.spyOn(window.localStorage, "getItem").mockReturnValueOnce("true");
138
+
139
+ expect(getModeAutoPrefers()).toBe(true);
140
+ });
141
+ });
142
+ });
143
+ });
144
+
145
+ describe("setModeUserPrefers", () => {
146
+ describe("given not in browser", () => {
147
+ it("should set modeUserPrefers", async () => {
148
+ const platform = await import("../platform/platform.service");
149
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: false });
150
+ vi.spyOn(window.localStorage, "setItem");
151
+
152
+ const { useDarkMode } = await import("./dark-mode.service");
153
+ const { setModeUserPrefers, modeUserPrefers } = useDarkMode();
154
+
155
+ setModeUserPrefers(true);
156
+ expect(modeUserPrefers.value).toBe(true);
157
+ expect(window.localStorage.setItem).not.toHaveBeenCalled();
158
+ });
159
+ });
160
+
161
+ describe("given in browser", () => {
162
+ it("should set modeUserPrefers and localStorage", async () => {
163
+ const platform = await import("../platform/platform.service");
164
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: true });
165
+
166
+ const { useDarkMode } = await import("./dark-mode.service");
167
+ const { setModeUserPrefers, modeUserPrefers } = useDarkMode();
168
+
169
+ const localStorageSpy = vi.spyOn(window.localStorage, "setItem");
170
+
171
+ setModeUserPrefers(true);
172
+ expect(modeUserPrefers.value).toBe(true);
173
+ expect(localStorageSpy).toHaveBeenCalledWith("modeUserPrefers", "true");
174
+ });
175
+ });
176
+ });
177
+
178
+ describe("setModeCurrent", () => {
179
+ it("light mode set", async () => {
180
+ const { useDarkMode } = await import("./dark-mode.service");
181
+ const { setModeCurrent, currentMode, MODE } = useDarkMode();
182
+
183
+ setModeCurrent(MODE.LIGHT);
184
+ expect(currentMode.value).toBe(MODE.LIGHT);
185
+ expect(document.documentElement.classList.contains("dark")).toBe(false);
186
+ });
187
+ it("dark mode set", async () => {
188
+ const { useDarkMode } = await import("./dark-mode.service");
189
+ const { setModeCurrent, currentMode, MODE } = useDarkMode();
190
+
191
+ setModeCurrent(MODE.DARK);
192
+ expect(currentMode.value).toBe(MODE.DARK);
193
+ expect(document.documentElement.classList.contains("dark")).toBe(true);
194
+ });
195
+ });
196
+
197
+ describe("initializeMode", () => {
198
+ it("should set currentMode", async () => {
199
+ const { useDarkMode } = await import("./dark-mode.service");
200
+ const { initializeMode, currentMode, getModeAutoPrefers } = useDarkMode();
201
+
202
+ const mode = getModeAutoPrefers();
203
+ initializeMode();
204
+ expect(currentMode.value).toBe(mode);
205
+ });
206
+ });
207
+
208
+ describe("autoModeWatcher", () => {
209
+ describe("given mode changes", () => {
210
+ it("should set modeCurrent", async () => {
211
+ const { useDarkMode } = await import("./dark-mode.service");
212
+ const darkMode = useDarkMode();
213
+
214
+ const mql = {
215
+ matches: true,
216
+ onchange: () => {
217
+ darkMode.setModeCurrent(mql.matches);
218
+ },
219
+ };
220
+ vi.spyOn(window, "matchMedia").mockReturnValueOnce(mql as any);
221
+
222
+ darkMode.autoModeWatcher();
223
+
224
+ mql.matches = false;
225
+ mql.onchange?.();
226
+ expect(darkMode.currentMode.value).toBe(false);
227
+
228
+ mql.matches = true;
229
+ mql.onchange?.();
230
+ expect(darkMode.currentMode.value).toBe(true);
231
+ });
232
+ });
233
+ });
234
+ });
@@ -1,5 +1,5 @@
1
1
  import { readonly, Ref, ref } from "vue";
2
- import { usePlatform } from "../platform/platform";
2
+ import { usePlatform } from "../platform/platform.service";
3
3
 
4
4
  const { isBrowser } = usePlatform();
5
5
 
@@ -14,7 +14,8 @@ const modeUserPrefers: Ref<boolean | undefined> = ref(undefined);
14
14
 
15
15
  const useDarkMode = () => {
16
16
  const getModeOsPrefers = (): boolean => {
17
- const prefersLightMode = window.matchMedia("(prefers-color-scheme: light)").matches;
17
+ let prefersLightMode = false;
18
+ if (isBrowser) prefersLightMode = window.matchMedia("(prefers-color-scheme: light)").matches;
18
19
  setModeOsPrefers(prefersLightMode);
19
20
  return prefersLightMode;
20
21
  };
@@ -30,8 +31,8 @@ const useDarkMode = () => {
30
31
  const getModeAutoPrefers = (): boolean => {
31
32
  const os = getModeOsPrefers();
32
33
  const user = getModeUserPrefers();
33
- const modeValue = user !== undefined ? user : os;
34
- return modeValue;
34
+ if (user === undefined) return os;
35
+ return user;
35
36
  };
36
37
 
37
38
  const setModeOsPrefers = (value: boolean) => {
@@ -26,7 +26,7 @@
26
26
  <script lang="ts">
27
27
  import type { CssClasses } from "@/index";
28
28
  import { computed, ComputedRef, defineComponent, onMounted } from "vue";
29
- import { useDarkMode } from "./dark-mode";
29
+ import { useDarkMode } from "./dark-mode.service";
30
30
 
31
31
  export default defineComponent({
32
32
  props: {
@@ -0,0 +1,11 @@
1
+ // test that all exports are defined
2
+ import * as utils from "./index";
3
+ import { describe, it, expect } from "vitest";
4
+
5
+ describe("utils", () => {
6
+ Object.entries(utils).forEach(([key, value]) => {
7
+ it(`${key} is defined`, () => {
8
+ expect(value).toBeDefined();
9
+ });
10
+ });
11
+ })
@@ -1,8 +1,7 @@
1
- import { useDarkMode } from "./dark-mode/dark-mode";
1
+ import CodeBlock from "./code-block/code-block.vue";
2
+ import { useDarkMode } from "./dark-mode/dark-mode.service";
2
3
  import DarkModeSwitch from "./dark-mode/dark-mode.vue";
3
- import { useTheme } from "./theme/theme";
4
4
  import ThemeSwitcher from "./theme/theme-switcher.vue";
5
-
6
- import CodeBlock from "./code-block/code-block.vue";
5
+ import { useTheme } from "./theme/theme.service";
7
6
 
8
7
  export { DarkModeSwitch, ThemeSwitcher, useDarkMode, useTheme, CodeBlock };
@@ -0,0 +1,19 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { usePlatform } from "./platform.service";
3
+
4
+ const matchMediaMock = (matches: boolean) => vi.fn(() => ({ matches, onchange: vi.fn() }));
5
+
6
+ describe("usePlatform", () => {
7
+ describe("isBrowser", () => {
8
+ it("should return true when window is defined", () => {
9
+ const { isBrowser } = usePlatform();
10
+ expect(isBrowser).toBe(true);
11
+ });
12
+
13
+ it("should return false when window is not defined", () => {
14
+ window = undefined as any;
15
+ const { isBrowser } = usePlatform();
16
+ expect(isBrowser).toBe(false);
17
+ });
18
+ });
19
+ });
@@ -0,0 +1,24 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+
3
+ /**
4
+ * No clue why, but when this test is added to theme.service.test.ts, it fails.
5
+ * Running it in isolation works fine.
6
+ */
7
+
8
+ describe("given there is a callback", () => {
9
+ it("should call the callback", async () => {
10
+ const { useTheme } = await import("./theme.service");
11
+ const { loadTheme } = useTheme();
12
+
13
+ const callbackSpy = vi.fn();
14
+ const callbackFunction = () => {
15
+ callbackSpy();
16
+ };
17
+ loadTheme("vuetiful", callbackFunction);
18
+ const link = document.querySelector("#theme") as HTMLLinkElement;
19
+ // @ts-ignore
20
+ link.onload();
21
+
22
+ expect(callbackSpy).toHaveBeenCalled();
23
+ });
24
+ });
@@ -0,0 +1,25 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+
3
+ /**
4
+ * No clue why, but when this test is added to theme.service.test.ts, it fails.
5
+ * Running it in isolation works fine.
6
+ */
7
+
8
+ describe("given there is no existing theme style tag", () => {
9
+ it.only("should create a new theme style tag", async () => {
10
+ const { useTheme } = await import("./theme.service");
11
+ const { loadTheme } = useTheme();
12
+
13
+ const removeObject = { remove: () => {} };
14
+ const removeSpy = vi.spyOn(removeObject, "remove");
15
+ vi.spyOn(window.document, "getElementById").mockReturnValueOnce(removeObject as any);
16
+
17
+ loadTheme("vuetiful");
18
+
19
+ const link = document.querySelector("#theme") as HTMLLinkElement;
20
+ // @ts-ignore
21
+ link.onload();
22
+
23
+ expect(removeSpy).toHaveBeenCalled();
24
+ });
25
+ });
@@ -0,0 +1,160 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { Theme } from "./theme.service";
3
+
4
+ const localStorageMock = {
5
+ getItem: vi.fn(),
6
+ setItem: vi.fn(),
7
+ };
8
+
9
+ describe("useTheme", () => {
10
+ afterEach(() => {
11
+ vi.resetModules();
12
+ });
13
+ describe("initializetheme", () => {
14
+ describe("given not in browser", () => {
15
+ it("should set the theme to the default theme if no theme is stored", async () => {
16
+ const platform = await import("../platform/platform.service");
17
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: false });
18
+
19
+ const localStorageSpy = vi.spyOn(window.localStorage, "getItem");
20
+
21
+ const { useTheme } = await import("./theme.service");
22
+ const { initializeTheme } = useTheme();
23
+
24
+ initializeTheme();
25
+
26
+ expect(localStorageSpy).not.toHaveBeenCalled();
27
+ });
28
+ });
29
+
30
+ describe("given in browser", () => {
31
+ beforeEach(() => {
32
+ window.localStorage = localStorageMock as any;
33
+ });
34
+ describe("given no theme is stored", () => {
35
+ it("should set the theme to the default theme", async () => {
36
+ const platform = await import("../platform/platform.service");
37
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: true });
38
+
39
+ const localStorageSpy = vi.spyOn(window.localStorage, "getItem");
40
+
41
+ const { useTheme } = await import("./theme.service");
42
+ const { initializeTheme, THEMES, chosenTheme } = useTheme();
43
+
44
+ initializeTheme();
45
+
46
+ expect(localStorageSpy).toHaveBeenCalledWith("vuetiful-theme");
47
+ expect(chosenTheme.value).toBe(THEMES.VUETIFUL);
48
+ });
49
+ });
50
+ describe("given a theme is stored", () => {
51
+ it("should set the theme to the stored theme", async () => {
52
+ const platform = await import("../platform/platform.service");
53
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: true });
54
+
55
+ const { useTheme } = await import("./theme.service");
56
+ const { initializeTheme, THEMES, chosenTheme } = useTheme();
57
+
58
+ const localStorageSpy = vi.spyOn(window.localStorage, "getItem");
59
+ localStorageSpy.mockReturnValueOnce(THEMES.ROCKET);
60
+
61
+ initializeTheme();
62
+
63
+ expect(localStorageSpy).toHaveBeenCalledWith("vuetiful-theme");
64
+ expect(chosenTheme.value).toBe(THEMES.ROCKET);
65
+ });
66
+ });
67
+
68
+ describe("given the theme is not valid", () => {
69
+ it("should set the theme to the default theme", async () => {
70
+ const platform = await import("../platform/platform.service");
71
+ vi.spyOn(platform, "usePlatform").mockReturnValueOnce({ isBrowser: true });
72
+
73
+ const { useTheme } = await import("./theme.service");
74
+ const { initializeTheme, THEMES, chosenTheme } = useTheme();
75
+
76
+ const localStorageSpy = vi.spyOn(window.localStorage, "getItem");
77
+ localStorageSpy.mockReturnValueOnce("invalid-theme");
78
+
79
+ initializeTheme();
80
+
81
+ expect(localStorageSpy).toHaveBeenCalledWith("vuetiful-theme");
82
+ expect(chosenTheme.value).toBe(THEMES.VUETIFUL);
83
+ });
84
+ });
85
+ });
86
+ });
87
+
88
+ describe("loadTheme", () => {
89
+ describe("given theme name exists in themes", () => {
90
+ it("should set the theme to the given theme", async () => {
91
+ const { useTheme } = await import("./theme.service");
92
+ const { loadTheme, THEMES, chosenTheme } = useTheme();
93
+
94
+ loadTheme(THEMES.ROCKET);
95
+
96
+ expect(chosenTheme.value).toBe(THEMES.ROCKET);
97
+ });
98
+ });
99
+ describe("given theme name does not exist in themes", () => {
100
+ it("should set the theme to the default theme", async () => {
101
+ const { useTheme } = await import("./theme.service");
102
+ const { loadTheme, THEMES, chosenTheme } = useTheme();
103
+
104
+ loadTheme("invalid-theme");
105
+
106
+ expect(chosenTheme.value).toBe(THEMES.VUETIFUL);
107
+ });
108
+ });
109
+ describe("given default theme is not in themes", () => {
110
+ it("should set the theme to the first theme in the themes object", async () => {
111
+ const { useTheme } = await import("./theme.service");
112
+ const { loadTheme, THEMES, chosenTheme, overwriteThemes, themes } = useTheme();
113
+
114
+ const theme: Theme = { name: "fake theme", url: "" };
115
+ overwriteThemes([themes.value[1], theme]);
116
+
117
+ loadTheme("invalid-theme");
118
+
119
+ expect(chosenTheme.value).toBe(themes.value[0].name);
120
+ });
121
+ });
122
+ });
123
+
124
+ describe("registerAllBuiltInThemes", () => {
125
+ it("should register all built in themes", async () => {
126
+ const { useTheme } = await import("./theme.service");
127
+ const { registerAllBuiltInThemes, THEMES, themes } = useTheme();
128
+
129
+ registerAllBuiltInThemes();
130
+
131
+ expect(themes.value).toHaveLength(Object.keys(THEMES).length);
132
+ });
133
+ });
134
+
135
+ describe("registerTheme", () => {
136
+ it("should register a theme", async () => {
137
+ const { useTheme } = await import("./theme.service");
138
+ const { registerTheme } = useTheme();
139
+
140
+ const theme: Theme = { name: "fake theme", url: "" };
141
+ expect(registerTheme(theme.name, "")).toEqual(theme);
142
+ });
143
+ });
144
+
145
+ describe("saveThemeToStorage", () => {
146
+ describe("given the theme does not exist", () => {
147
+ it("should not save the theme to storage", async () => {
148
+ const { useTheme } = await import("./theme.service");
149
+ const { saveThemeToStorage } = useTheme();
150
+
151
+ const localStorageSpy = vi.spyOn(window.localStorage, "setItem");
152
+
153
+ saveThemeToStorage("invalid-theme");
154
+
155
+ expect(localStorageSpy).not.toHaveBeenCalled();
156
+ });
157
+ })
158
+ })
159
+
160
+ });
@@ -1,9 +1,9 @@
1
1
  import { readonly, Ref, ref } from "vue";
2
- import { usePlatform } from "../platform/platform";
2
+ import { usePlatform } from "../platform/platform.service";
3
3
 
4
4
  const { isBrowser } = usePlatform();
5
5
 
6
- interface Theme {
6
+ export interface Theme {
7
7
  name: string;
8
8
  url: string;
9
9
  }
@@ -38,7 +38,7 @@ const defaultTheme = THEMES.VUETIFUL;
38
38
  const chosenTheme = ref(defaultTheme);
39
39
 
40
40
  const useTheme = () => {
41
- const setTheme = (name: string): void => {
41
+ const saveThemeToStorage = (name: string): void => {
42
42
  const theme = themes.value.find((t) => t.name === name);
43
43
  if (!theme) return;
44
44
 
@@ -74,10 +74,8 @@ const useTheme = () => {
74
74
  link.rel = "stylesheet";
75
75
  link.onload = () => {
76
76
  if (existingStyle) existingStyle.remove();
77
- setTheme(theme.name);
78
- if (callback) {
79
- callback();
80
- }
77
+ saveThemeToStorage(theme.name);
78
+ if (callback) callback();
81
79
  };
82
80
 
83
81
  const head = document.querySelector("head");
@@ -102,6 +100,7 @@ const useTheme = () => {
102
100
 
103
101
  initializeTheme,
104
102
  loadTheme,
103
+ saveThemeToStorage,
105
104
 
106
105
  THEMES,
107
106
  overwriteThemes,
@@ -1 +0,0 @@
1
- export declare const MAGIC_NUM = 100;
@@ -1,2 +0,0 @@
1
- import * as MyConstants from './MyConstants';
2
- export { MyConstants };
@@ -1 +0,0 @@
1
- export const MAGIC_NUM = 100
@@ -1,5 +0,0 @@
1
- import * as MyConstants from './MyConstants'
2
-
3
- export {
4
- MyConstants
5
- }