@code-coaching/vuetiful 0.8.1 → 0.9.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-coaching/vuetiful",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "scripts": {
5
5
  "dev": "onchange 'src/**/*.vue' 'src/**/*.ts' 'src/**/*.css' -- npm run build",
6
6
  "prebuild": "node 'scripts/intellisense.js'",
@@ -1,10 +1,12 @@
1
1
  import { mount } from "@vue/test-utils";
2
- import { expect, test } from "vitest";
2
+ import { describe, expect, test, vi } from "vitest";
3
3
  import { VButton } from ".";
4
4
 
5
- test("VButton using slot", async () => {
5
+ test("VButton", () => {
6
6
  expect(VButton).toBeTruthy();
7
+ });
7
8
 
9
+ test("VButton using slot", () => {
8
10
  const vButtonElement = mount(VButton, {
9
11
  slots: {
10
12
  default: "John Duck",
@@ -13,3 +15,108 @@ test("VButton using slot", async () => {
13
15
 
14
16
  expect(vButtonElement.text()).toContain("John Duck");
15
17
  });
18
+
19
+ describe("VButton props", () => {
20
+ describe("given icon is true", () => {
21
+ test("should have btn-icon class, not have btn class", () => {
22
+ const vButtonElement = mount(VButton, {
23
+ props: {
24
+ icon: true,
25
+ },
26
+ });
27
+ expect(vButtonElement.classes()).toContain("btn-icon");
28
+ expect(vButtonElement.classes()).not.toContain("btn");
29
+ });
30
+ });
31
+ describe("given icon is false", () => {
32
+ test("should have btn class, not have btn-icon class", () => {
33
+ const vButtonElement = mount(VButton, {
34
+ props: {
35
+ icon: false,
36
+ },
37
+ });
38
+ expect(vButtonElement.classes()).not.toContain("btn-icon");
39
+ expect(vButtonElement.classes()).toContain("btn");
40
+ });
41
+ });
42
+ });
43
+
44
+ describe("VButton events", () => {
45
+ describe("given click event", () => {
46
+ test("should preventDefault and emit click event", async () => {
47
+ const vButtonElement = mount(VButton);
48
+ const clickEvent = { preventDefault: () => {} };
49
+ const preventDefaultSpy = vi.spyOn(clickEvent, "preventDefault");
50
+ vButtonElement.trigger("click", clickEvent);
51
+ await vButtonElement.vm.$nextTick();
52
+ expect(preventDefaultSpy).toHaveBeenCalled();
53
+ expect(vButtonElement.emitted("click")).toBeTruthy();
54
+ });
55
+ });
56
+ });
57
+
58
+ describe("VButton a11y", () => {
59
+ describe("a11y role", () => {
60
+ test("should have role button", () => {
61
+ const vButtonElement = mount(VButton);
62
+ expect(vButtonElement.attributes("role")).toBe("button");
63
+ });
64
+ });
65
+ describe("a11y tabindex", () => {
66
+ test("should have tabindex 0", () => {
67
+ const vButtonElement = mount(VButton);
68
+ expect(vButtonElement.attributes("tabindex")).toBe("0");
69
+ });
70
+ });
71
+ describe("given keydown event", () => {
72
+ describe("given key is Enter", () => {
73
+ test("should preventDefault and emit click event", async () => {
74
+ const vButtonElement = mount(VButton);
75
+ const keydownEvent = { key: "Enter", preventDefault: () => {} };
76
+ const preventDefaultSpy = vi.spyOn(keydownEvent, "preventDefault");
77
+ vButtonElement.trigger("keydown", keydownEvent);
78
+ await vButtonElement.vm.$nextTick();
79
+ expect(preventDefaultSpy).toHaveBeenCalled();
80
+ expect(vButtonElement.emitted("click")).toBeTruthy();
81
+ });
82
+ });
83
+
84
+ describe("given key is Space", () => {
85
+ test("should preventDefault and not emit click event", async () => {
86
+ const vButtonElement = mount(VButton);
87
+ const keydownEvent = { key: " ", preventDefault: () => {} };
88
+ const preventDefaultSpy = vi.spyOn(keydownEvent, "preventDefault");
89
+ vButtonElement.trigger("keydown", keydownEvent);
90
+ await vButtonElement.vm.$nextTick();
91
+ expect(preventDefaultSpy).toHaveBeenCalled();
92
+ expect(vButtonElement.emitted("click")).toBeFalsy();
93
+ });
94
+ });
95
+
96
+ describe("given key is not Enter or Space", () => {
97
+ test("should not preventDefault and not emit click event", async () => {
98
+ const vButtonElement = mount(VButton);
99
+ const keydownEvent = { key: "a", preventDefault: () => {} };
100
+ const preventDefaultSpy = vi.spyOn(keydownEvent, "preventDefault");
101
+ vButtonElement.trigger("keydown", keydownEvent);
102
+ await vButtonElement.vm.$nextTick();
103
+ expect(preventDefaultSpy).not.toHaveBeenCalled();
104
+ expect(vButtonElement.emitted("click")).toBeFalsy();
105
+ });
106
+ });
107
+ });
108
+
109
+ describe("given keyup event", () => {
110
+ describe("given key is Space", () => {
111
+ test("should preventDefault and emit click event", async () => {
112
+ const vButtonElement = mount(VButton);
113
+ const keyupEvent = { key: " ", preventDefault: () => {} };
114
+ const preventDefaultSpy = vi.spyOn(keyupEvent, "preventDefault");
115
+ vButtonElement.trigger("keyup", keyupEvent);
116
+ await vButtonElement.vm.$nextTick();
117
+ expect(preventDefaultSpy).toHaveBeenCalled();
118
+ expect(vButtonElement.emitted("click")).toBeTruthy();
119
+ });
120
+ });
121
+ });
122
+ });
@@ -2,19 +2,51 @@
2
2
  import { useAttrs } from "vue";
3
3
 
4
4
  defineProps({
5
+ icon: {
6
+ type: Boolean as () => boolean,
7
+ default: false,
8
+ },
5
9
  tag: {
6
10
  type: String as () => string,
7
11
  default: "button",
8
12
  },
9
13
  });
10
14
  const attrs = useAttrs();
11
- defineEmits(["click"]);
15
+ const emit = defineEmits<{ (event: "click"): void }>();
16
+
17
+ const activate = () => {
18
+ emit("click");
19
+ };
20
+
21
+ const clickHandler = (event: MouseEvent) => {
22
+ event.preventDefault();
23
+ activate();
24
+ };
25
+
26
+ const keydownHandler = (event: KeyboardEvent) => {
27
+ if (["Enter", " "].includes(event.key)) event.preventDefault();
28
+ if (event.key === "Enter") activate();
29
+ };
30
+
31
+ const keyupHandler = (event: KeyboardEvent) => {
32
+ if (event.key === " ") {
33
+ event.preventDefault();
34
+ activate();
35
+ }
36
+ };
12
37
  </script>
13
38
 
14
39
  <template>
15
40
  <component
41
+ tabindex="0"
42
+ role="button"
16
43
  :is="tag"
17
- :class="`vuetiful-button btn border-token hover:cursor-pointer ${attrs.class ?? ''}`"
44
+ :class="`vuetiful-button ${icon ? 'btn-icon' : 'btn'} border-token hover:cursor-pointer ${
45
+ attrs.class ?? ''
46
+ }`"
47
+ @click="clickHandler"
48
+ @keydown="keydownHandler"
49
+ @keyup="keyupHandler"
18
50
  >
19
51
  <slot />
20
52
  </component>
@@ -37,21 +37,31 @@ const { selectedRailTile } = useRail();
37
37
  const active = inject("active");
38
38
  const hover = inject("hover");
39
39
 
40
- const onClickHandler = () => {
41
- if (!props.value) return;
40
+ const activate = () => {
42
41
  selectedRailTile.value = props.value;
43
42
  emit("click");
44
43
  };
45
- const onKeyHandler = (event: KeyboardEvent) => {
46
- if (!props.value) return;
47
- if (!["Enter", "Space"].includes(event.key)) return;
48
- selectedRailTile.value = props.value;
49
- emit("click");
44
+
45
+ const clickHandler = (event: MouseEvent) => {
46
+ event.preventDefault();
47
+ activate();
48
+ };
49
+
50
+ const keydownHandler = (event: KeyboardEvent) => {
51
+ if (["Enter", " "].includes(event.key)) event.preventDefault();
52
+ if (event.key === "Enter") activate();
53
+ };
54
+
55
+ const keyupHandler = (event: KeyboardEvent) => {
56
+ if (event.key === " ") {
57
+ event.preventDefault();
58
+ activate();
59
+ }
50
60
  };
51
61
  </script>
52
62
 
53
63
  <template>
54
- <div @click="onClickHandler" @keydown="onKeyHandler">
64
+ <div @click="clickHandler" @keydown="keydownHandler" @keyup="keyupHandler">
55
65
  <component
56
66
  :is="tag"
57
67
  v-bind="attrs"
@@ -1,11 +1,13 @@
1
- import { describe, expect } from "vitest";
1
+ import { describe, expect, it } from "vitest";
2
2
  import { useRail } from "./rail.service";
3
3
 
4
4
  const { selectedRailTile } = useRail();
5
5
 
6
6
  describe("useRail", () => {
7
7
  describe("selectedRailTile", () => {
8
- selectedRailTile.value = "John Duck";
9
- expect(selectedRailTile.value).toBe("John Duck");
8
+ it("should expose selectedRailTile", () => {
9
+ selectedRailTile.value = "John Duck";
10
+ expect(selectedRailTile.value).toBe("John Duck");
11
+ });
10
12
  });
11
13
  });