@dpa-id-components/dpa-shared-components 20.0.6 → 20.0.7

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 (81) hide show
  1. package/dist/src/components/DpaMediaItem/DpaMediaItem.spec.ts +123 -0
  2. package/dist/src/components/DpaMediaItem/DpaMediaItem.stories.ts +140 -0
  3. package/dist/src/components/UiAutocomplete/UiAutocomplete.spec.ts +39 -0
  4. package/dist/src/components/UiAutocomplete/UiAutocomplete.stories.ts +46 -0
  5. package/dist/src/components/UiBadge/UiBadge.spec.ts +32 -0
  6. package/dist/src/components/UiBadge/UiBadge.stories.ts +80 -0
  7. package/dist/src/components/UiButton/UiButton.spec.ts +136 -0
  8. package/dist/src/components/UiButton/UiButton.stories.ts +57 -0
  9. package/dist/src/components/UiButtonGroup/UiButtonGroup.spec.ts +16 -0
  10. package/dist/src/components/UiButtonGroup/UiButtonGroup.stories.ts +50 -0
  11. package/dist/src/components/UiCard/UiCard.spec.ts +16 -0
  12. package/dist/src/components/UiCard/UiCard.stories.ts +30 -0
  13. package/dist/src/components/UiCheckBoxGroup/UiCheckBoxGroup.spec.ts +67 -0
  14. package/dist/src/components/UiCheckBoxGroup/UiCheckBoxGroup.stories.ts +59 -0
  15. package/dist/src/components/UiCheckbox/UiCheckbox.spec.ts +173 -0
  16. package/dist/src/components/UiCheckbox/UiCheckbox.stories.ts +99 -0
  17. package/dist/src/components/UiChip/UiChip.spec.ts +75 -0
  18. package/dist/src/components/UiChip/UiChip.stories.ts +39 -0
  19. package/dist/src/components/UiCollapseNavigation/UiCollapseNavigation.spec.ts +21 -0
  20. package/dist/src/components/UiCollapseNavigation/UiCollapseNavigation.stories.ts +66 -0
  21. package/dist/src/components/UiColorPicker/UiColorPicker.spec.ts +52 -0
  22. package/dist/src/components/UiColorPicker/UiColorPicker.stories.ts +44 -0
  23. package/dist/src/components/UiDatePicker/UiDatePicker.spec.ts +335 -0
  24. package/dist/src/components/UiDatePicker/UiDatePicker.stories.ts +273 -0
  25. package/dist/src/components/UiDialog/UiDialog.spec.ts +160 -0
  26. package/dist/src/components/UiDialog/UiDialog.stories.ts +79 -0
  27. package/dist/src/components/UiFilterBadge/UiFilterBadge.spec.ts +17 -0
  28. package/dist/src/components/UiFilterBadge/UiFilterBadge.stories.ts +44 -0
  29. package/dist/src/components/UiFilterBadgeButton/UiFilterBadgeButton.spec.ts +41 -0
  30. package/dist/src/components/UiFilterBadgeButton/UiFilterBadgeButton.stories.ts +55 -0
  31. package/dist/src/components/UiFilterButton/UiFilterButton.spec.ts +79 -0
  32. package/dist/src/components/UiFilterButton/UiFilterButton.stories.ts +88 -0
  33. package/dist/src/components/UiIcon/IconOverview.stories.vue +23 -0
  34. package/dist/src/components/UiIcon/UiIcon.spec.ts +56 -0
  35. package/dist/src/components/UiIcon/UiIcon.stories.ts +48 -0
  36. package/dist/src/components/UiIconButton/UiIconButton.spec.ts +78 -0
  37. package/dist/src/components/UiIconButton/UiIconButton.stories.ts +63 -0
  38. package/dist/src/components/UiInfoContent/UiInfoContent.spec.ts +43 -0
  39. package/dist/src/components/UiInfoContent/UiInfoContent.stories.ts +56 -0
  40. package/dist/src/components/UiInput/UiInput.spec.ts +239 -0
  41. package/dist/src/components/UiInput/UiInput.stories.ts +127 -0
  42. package/dist/src/components/UiList/UiList.spec.ts +22 -0
  43. package/dist/src/components/UiList/UiList.stories.ts +64 -0
  44. package/dist/src/components/UiListItem/UiListItem.spec.ts +99 -0
  45. package/dist/src/components/UiListItem/UiListItem.stories.ts +83 -0
  46. package/dist/src/components/UiMenu/UiMenu.spec.ts +319 -0
  47. package/dist/src/components/UiMenu/UiMenu.stories.ts +634 -0
  48. package/dist/src/components/UiOverlay/UiOverlay.spec.ts +16 -0
  49. package/dist/src/components/UiOverlay/UiOverlay.stories.ts +22 -0
  50. package/dist/src/components/UiOverlayMenu/UiOverlayMenu.spec.ts +32 -0
  51. package/dist/src/components/UiOverlayMenu/UiOverlayMenu.stories.ts +39 -0
  52. package/dist/src/components/UiRadioInputGroup/UiRadioInputGroup.spec.ts +66 -0
  53. package/dist/src/components/UiRadioInputGroup/UiRadioInputGroup.stories.ts +70 -0
  54. package/dist/src/components/UiSearchBar/UiSearchBar.spec.ts +82 -0
  55. package/dist/src/components/UiSearchBar/UiSearchBar.stories.ts +191 -0
  56. package/dist/src/components/UiSearchInput/UiSearchInput.spec.ts +45 -0
  57. package/dist/src/components/UiSearchInput/UiSearchInput.stories.ts +61 -0
  58. package/dist/src/components/UiSection/UiSection.spec.ts +49 -0
  59. package/dist/src/components/UiSection/UiSection.stories.ts +61 -0
  60. package/dist/src/components/UiSectionDivider/UiSectionDivider.spec.ts +19 -0
  61. package/dist/src/components/UiSectionDivider/UiSectionDivider.stories.ts +48 -0
  62. package/dist/src/components/UiSelect/UIiSelect.spec.ts +102 -0
  63. package/dist/src/components/UiSelect/UiSelect.stories.ts +94 -0
  64. package/dist/src/components/UiSimpleInput/UiSimpleInput.spec.ts +58 -0
  65. package/dist/src/components/UiSimpleInput/UiSimpleInput.stories.ts +53 -0
  66. package/dist/src/components/UiSkeletonBox/UiSkeletonBox.spec.ts +15 -0
  67. package/dist/src/components/UiSkeletonBox/UiSkeletonBox.stories.ts +33 -0
  68. package/dist/src/components/UiSnackbar/UiSnackbar.spec.ts +63 -0
  69. package/dist/src/components/UiSnackbar/UiSnackbar.stories.ts +65 -0
  70. package/dist/src/components/UiSpinner/UiSpinner.spec.ts +30 -0
  71. package/dist/src/components/UiSpinner/UiSpinner.stories.ts +48 -0
  72. package/dist/src/components/UiTextButton/UiTextButton.spec.ts +99 -0
  73. package/dist/src/components/UiTextButton/UiTextButton.stories.ts +60 -0
  74. package/dist/src/components/UiToggleButton/UiToggleButton.spec.ts +89 -0
  75. package/dist/src/components/UiToggleButton/UiToggleButton.stories.ts +102 -0
  76. package/dist/src/components/UiTooltip/UiTooltip.spec.ts +139 -0
  77. package/dist/src/components/UiTooltip/UiTooltip.stories.ts +107 -0
  78. package/dist/src/compositions/useBreakpoints/UseBreakpoints.stories.ts +23 -0
  79. package/dist/src/compositions/useBreakpoints/UseBreakpoints.stories.vue +12 -0
  80. package/dist/src/utils/index.spec.ts +12 -0
  81. package/package.json +5 -4
@@ -0,0 +1,123 @@
1
+ import { mount } from "@vue/test-utils";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ import DpaMediaItem from "./DpaMediaItem.vue";
5
+
6
+ describe("DpaMediaItem", () => {
7
+ it("displays items in the time published slot", () => {
8
+ const wrapper = mount(DpaMediaItem, {
9
+ slots: {
10
+ timePublished: "Time Slot",
11
+ },
12
+ });
13
+ expect(wrapper.text()).toBe("Time Slot");
14
+ });
15
+
16
+ it("displays items in the description slot", () => {
17
+ const wrapper = mount(DpaMediaItem, {
18
+ slots: {
19
+ description: "Description",
20
+ },
21
+ });
22
+ expect(wrapper.text()).toBe("Description");
23
+ });
24
+
25
+ it("displays items in the planning slot", () => {
26
+ const wrapper = mount(DpaMediaItem, {
27
+ slots: {
28
+ planning: "Planning",
29
+ },
30
+ });
31
+ expect(wrapper.text()).toBe("Planning");
32
+ });
33
+
34
+ it("displays items in the textLength slot", () => {
35
+ const wrapper = mount(DpaMediaItem, {
36
+ slots: {
37
+ textLength: "Text Length",
38
+ },
39
+ });
40
+ expect(wrapper.text()).toBe("Text Length");
41
+ });
42
+
43
+ it("changes icon according to the genre", () => {
44
+ const wrapper = mount(DpaMediaItem, {
45
+ props: {
46
+ genre: "audio",
47
+ },
48
+ });
49
+
50
+ expect(wrapper.findComponent({ name: "UiIcon" }).props()).toMatchObject({
51
+ name: "audio-circled",
52
+ });
53
+ });
54
+
55
+ it("changes icon when fulfilled", () => {
56
+ const wrapper = mount(DpaMediaItem, {
57
+ props: {
58
+ genre: "audio",
59
+
60
+ isFulfilled: true,
61
+ },
62
+ });
63
+
64
+ expect(wrapper.findComponent({ name: "UiIcon" }).props()).toMatchObject({
65
+ name: "audio-filled",
66
+ });
67
+ });
68
+
69
+ it("is styled differently when fulfilled", () => {
70
+ const wrapper = mount(DpaMediaItem, {
71
+ props: {
72
+ isFulfilled: true,
73
+ },
74
+ });
75
+
76
+ const rootDiv = wrapper.find('[data-testid="rootDiv"]');
77
+ expect(rootDiv.classes("border-gray-300")).toBe(true);
78
+ });
79
+
80
+ it("renders images with the correct source", () => {
81
+ const wrapper = mount(DpaMediaItem, {
82
+ props: {
83
+ imgSrc: "Source",
84
+ },
85
+ });
86
+
87
+ expect(wrapper.find("img").attributes().src).toBe("Source");
88
+ });
89
+
90
+ it("renders images with correct alt-text", () => {
91
+ const wrapper = mount(DpaMediaItem, {
92
+ props: {
93
+ imgSrc: "Source",
94
+ imgAlt: "Alternative",
95
+ },
96
+ });
97
+
98
+ expect(wrapper.find("img").attributes().alt).toBe("Thumbnail :Alternative");
99
+ });
100
+
101
+ it("displays the correct image count", () => {
102
+ const wrapper = mount(DpaMediaItem, {
103
+ props: {
104
+ imgSrc: "Source",
105
+ imgCount: 2,
106
+ },
107
+ });
108
+
109
+ expect(wrapper.find("[data-testid='imageCount']").text()).toBe("2");
110
+ });
111
+
112
+ it("is styled differently when disabled", () => {
113
+ const wrapper = mount(DpaMediaItem, {
114
+ props: {
115
+ isFulfilled: true,
116
+ disabled: true,
117
+ },
118
+ });
119
+
120
+ const rootDiv = wrapper.find('[data-testid="rootDiv"]');
121
+ expect(rootDiv.classes("cursor-not-allowed")).toBe(true);
122
+ });
123
+ });
@@ -0,0 +1,140 @@
1
+ import type { Meta, StoryObj } from "@storybook/vue3-vite";
2
+
3
+ import DpaMediaItem from "./DpaMediaItem.vue";
4
+
5
+ const meta = {
6
+ title: "Ui/DpaMediaItem",
7
+ component: DpaMediaItem,
8
+ argTypes: {
9
+ genre: {
10
+ control: {
11
+ type: "select",
12
+ options: ["audio", "video", "text", "picture", "graphic"],
13
+ },
14
+ },
15
+ isFulfilled: {
16
+ control: "boolean",
17
+ },
18
+ imgSrc: {
19
+ control: "text",
20
+ },
21
+ imgAlt: {
22
+ control: "text",
23
+ },
24
+ imgCount: {
25
+ control: "number",
26
+ },
27
+ },
28
+ args: {
29
+ genre: "text",
30
+ isFulfilled: true,
31
+ imgSrc: "",
32
+ imgAlt: "",
33
+ imgCount: 0,
34
+ },
35
+ tags: ["deprecated"],
36
+ } satisfies Meta<typeof DpaMediaItem>;
37
+
38
+ export default meta;
39
+ type Story = StoryObj<typeof meta>;
40
+
41
+ export const Default: Story = {
42
+ render: (args) => ({
43
+ setup() {
44
+ return { args };
45
+ },
46
+ components: { DpaMediaItem },
47
+ template: `
48
+ <DpaMediaItem v-bind="args" auto-size style="cursor: pointer;">
49
+ <template #timePublished>15.11.2021 16:41</template>
50
+ <template #description>News Feature im Basisdienst</template>
51
+ <span>BKA-Chef: Cannabis bleibt beliebteste Droge in Deutschland</span>
52
+ <template #textLength>104 dpa-Zeilen / 7176 Zeichen</template>
53
+ </DpaMediaItem>
54
+ `,
55
+ }),
56
+ };
57
+
58
+ export const Picture: Story = {
59
+ render: (args) => ({
60
+ setup() {
61
+ return { args };
62
+ },
63
+ components: { DpaMediaItem },
64
+ template: `
65
+ <dpa-media-item v-bind="args" auto-size style="cursor: pointer;">
66
+ <template #timePublished>15.11.2021 16:41</template>
67
+ <template #description>Aktuelle Fotos</template>
68
+ <span>Wahl des neuen EKD-Ratsvorsitzes</span>
69
+ </dpa-media-item>
70
+ `,
71
+ }),
72
+ args: {
73
+ genre: "picture",
74
+ isFulfilled: true,
75
+ imgSrc: `data:image/jpeg;base64,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`,
76
+ imgAlt: "Wahl des neuen EKD-Ratsvorsitzes",
77
+ imgCount: 12,
78
+ },
79
+ };
80
+
81
+ export const Disabled: Story = {
82
+ render: (args) => ({
83
+ setup() {
84
+ return { args };
85
+ },
86
+ components: { DpaMediaItem },
87
+ template: `
88
+ <dpa-media-item v-bind="args" auto-size>
89
+ <template #timePublished>15.11.2021 16:41</template>
90
+ <template #description>Video-Beitrag</template>
91
+ <span>Wahl des neuen EKD-Ratsvorsitzes</span>
92
+ </dpa-media-item>
93
+ `,
94
+ }),
95
+ args: {
96
+ genre: "video",
97
+ isFulfilled: true,
98
+ imgCount: 1,
99
+ disabled: true,
100
+ },
101
+ };
102
+
103
+ export const Planned: Story = {
104
+ render: (args) => ({
105
+ setup() {
106
+ return { args };
107
+ },
108
+ components: { DpaMediaItem },
109
+ template: `
110
+ <dpa-media-item v-bind="args" auto-size style="cursor: pointer;">
111
+ <template #description>Zusammenfassung im Basisdienst</template>
112
+ <template #planning>bis 16:30</template>
113
+ <template #textLength>ca. 60 dpa-Zeilen / 4140 Zeichen</template>
114
+ </dpa-media-item>
115
+ `,
116
+ }),
117
+ args: {
118
+ isFulfilled: false,
119
+ },
120
+ };
121
+
122
+ export const PlannedWithHeadline: Story = {
123
+ render: (args) => ({
124
+ setup() {
125
+ return { args };
126
+ },
127
+ components: { DpaMediaItem },
128
+ template: `
129
+ <dpa-media-item v-bind="args" auto-size style="cursor: pointer;">
130
+ <span>Planned with headline: BKA-Chef: Cannabis bleibt beliebteste Droge in Deutschland</span>
131
+ <template #description>Zusammenfassung im Basisdienst</template>
132
+ <template #planning>bis 16:30</template>
133
+ <template #textLength>ca. 60 dpa-Zeilen / 4140 Zeichen</template>
134
+ </dpa-media-item>
135
+ `,
136
+ }),
137
+ args: {
138
+ isFulfilled: false,
139
+ },
140
+ };
@@ -0,0 +1,39 @@
1
+ import { mount } from "@vue/test-utils";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ import UiAutocomplete from "./UiAutocomplete.vue";
5
+
6
+ const wrapper = mount(UiAutocomplete, {
7
+ props: {
8
+ value: "",
9
+ label: "Sprecher/in",
10
+ placeholder: "",
11
+ options: ["Olaf Scholz", "Christian Lindner"],
12
+ },
13
+ });
14
+ describe("UiAutocomplete", () => {
15
+ it("renders options correctly", async () => {
16
+ const firstOption = wrapper.findAll('[data-testid="innerText"]')[0];
17
+ expect(firstOption).toBeTruthy();
18
+
19
+ const secondOption = wrapper.findAll('[data-testid="innerText"]')[1];
20
+ expect(secondOption).toBeTruthy();
21
+ });
22
+
23
+ it("should emit a select event when an option is clicked", async () => {
24
+ const secondOption = wrapper.findAll('[data-testid="innerText"]')[1];
25
+
26
+ await secondOption.trigger("click");
27
+
28
+ expect(wrapper.emitted().select[0]).toEqual(["Christian Lindner"]);
29
+ });
30
+
31
+ it("should emit a select event when an option is selected and entered via keyboard events", async () => {
32
+ const input = wrapper.find("input");
33
+ await input.trigger("keyup.down");
34
+ await input.trigger("keyup.down");
35
+ await input.trigger("keyup.enter");
36
+
37
+ expect(wrapper.emitted().select[0]).toEqual(["Christian Lindner"]);
38
+ });
39
+ });
@@ -0,0 +1,46 @@
1
+ import type { Meta, StoryObj } from "@storybook/vue3-vite";
2
+ import { action } from "storybook/actions";
3
+
4
+ import UiAutocomplete from "./UiAutocomplete.vue";
5
+
6
+ const meta = {
7
+ title: "Ui/UiAutocomplete",
8
+ component: UiAutocomplete,
9
+ argTypes: {
10
+ label: { control: "text" },
11
+ placeholder: { control: "text" },
12
+ value: { control: "text" },
13
+ chevron: { control: "boolean" },
14
+ readonly: { control: "boolean" },
15
+ options: {
16
+ control: false,
17
+ },
18
+ },
19
+ args: {
20
+ label: "Label",
21
+ placeholder: "Autocomplete",
22
+ value: "",
23
+ readonly: false,
24
+ chevron: false,
25
+ },
26
+ } satisfies Meta<typeof UiAutocomplete>;
27
+
28
+ export default meta;
29
+ type Story = StoryObj<typeof meta>;
30
+ export const Default: Story = {
31
+ render: (args) => ({
32
+ setup() {
33
+ return { args };
34
+ },
35
+ components: { UiAutocomplete },
36
+ template:
37
+ "<UiAutocomplete v-bind='args' @input='input' @select='select'></UiAutocomplete>",
38
+ methods: { input: action("input"), select: action("select") },
39
+ }),
40
+ args: {
41
+ label: "Sprecher/in",
42
+ placeholder: "Beispiel: Scholz",
43
+ value: "",
44
+ options: ["Olaf Scholz", "Christian Lindner", "Annalena Baerbock"],
45
+ },
46
+ };
@@ -0,0 +1,32 @@
1
+ import { mount } from "@vue/test-utils";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ import UiBadge from "./UiBadge.vue";
5
+
6
+ describe("UiBadge", () => {
7
+ it("renders red color by default", () => {
8
+ const wrapper = mount(UiBadge);
9
+ expect(wrapper.classes("bg-rainbow-red")).toBe(true);
10
+ });
11
+
12
+ it("renders white color with different text color", () => {
13
+ const wrapper = mount(UiBadge, {
14
+ props: {
15
+ color: "white",
16
+ },
17
+ });
18
+ expect(wrapper.classes("bg-white")).toBe(true);
19
+ expect(wrapper.classes("text-black")).toBe(true);
20
+ });
21
+
22
+ it("renders audio icon when iconName prop is set to 'audio'", () => {
23
+ const wrapper = mount(UiBadge, {
24
+ props: {
25
+ iconName: "audio",
26
+ },
27
+ });
28
+ const uiIcon = wrapper.findComponent({ name: "UiIcon" });
29
+ expect(uiIcon.exists()).toBe(true);
30
+ expect(uiIcon.props("name")).toBe("audio");
31
+ });
32
+ });
@@ -0,0 +1,80 @@
1
+ import type { Meta, StoryObj } from "@storybook/vue3-vite";
2
+
3
+ import { icons } from "../UiIcon/icons.js";
4
+ import UiBadge from "./UiBadge.vue";
5
+
6
+ const meta = {
7
+ title: "Ui/UiBadge",
8
+ component: UiBadge,
9
+ argTypes: {
10
+ text: { control: "text" },
11
+ color: {
12
+ control: "select",
13
+ options: [
14
+ "red",
15
+ "red-dark",
16
+ "orange",
17
+ "purple",
18
+ "blue",
19
+ "white",
20
+ "gray-300",
21
+ "gray-600",
22
+ "gray-800",
23
+ "black",
24
+ "green-neon",
25
+ "green-primary",
26
+ ],
27
+ },
28
+ iconName: {
29
+ control: "select",
30
+ options: [null, ...Object.keys(icons)],
31
+ },
32
+ mobileTrim: { control: "boolean" },
33
+ trim: { control: "boolean" },
34
+ small: { control: "boolean" },
35
+ screenReaderText: { control: "text" },
36
+ },
37
+ args: {
38
+ text: "Badge Content",
39
+ color: "red",
40
+ iconName: null,
41
+ mobileTrim: false,
42
+ trim: false,
43
+ small: false,
44
+ screenReaderText: "Screenreader Text",
45
+ },
46
+ } satisfies Meta<typeof UiBadge>;
47
+
48
+ export default meta;
49
+ type Story = StoryObj<typeof meta>;
50
+
51
+ export const Default: Story = {};
52
+
53
+ export const PlanningItemBadge: Story = {
54
+ render: (args) => ({
55
+ components: { UiBadge },
56
+ setup() {
57
+ return { args };
58
+ },
59
+ template: "<UiBadge v-bind='args'></UiBadge>",
60
+ }),
61
+ args: {
62
+ color: "gray-800",
63
+ iconName: "audio",
64
+ text: "3",
65
+ screenReaderText: "Inhalte geplant",
66
+ trim: false,
67
+ mobileTrim: false,
68
+ small: false,
69
+ },
70
+ };
71
+
72
+ export const WithSlot: Story = {
73
+ render: (args) => ({
74
+ setup() {
75
+ return { args };
76
+ },
77
+ components: { UiBadge },
78
+ template: "<UiBadge v-bind='args'>Badge with slot</UiBadge>",
79
+ }),
80
+ };
@@ -0,0 +1,136 @@
1
+ import { type ComponentMountingOptions, mount } from "@vue/test-utils";
2
+ import { describe, expect, it } from "vitest";
3
+ import { createRouter, createWebHistory } from "vue-router";
4
+
5
+ import UiButton from "./UiButton.vue";
6
+
7
+ const router = createRouter({
8
+ history: createWebHistory(import.meta.env.BASE_URL),
9
+ routes: [
10
+ {
11
+ path: "/",
12
+ component: {
13
+ template: "<RouterView />",
14
+ },
15
+ },
16
+ ],
17
+ });
18
+
19
+ function createWrapper(
20
+ options: ComponentMountingOptions<typeof UiButton> = {},
21
+ ) {
22
+ return mount(UiButton, {
23
+ global: {
24
+ plugins: [router],
25
+ },
26
+ ...options,
27
+ });
28
+ }
29
+
30
+ describe("UiButton", () => {
31
+ it("renders medium size by default", () => {
32
+ const wrapper = createWrapper();
33
+ expect(wrapper.classes("h-10")).toBe(true);
34
+ });
35
+
36
+ it.each(["button", "submit"])("has expected type attribute", (type) => {
37
+ const wrapper = createWrapper({ attrs: { type } });
38
+ expect(wrapper.attributes("type")).toBe(type);
39
+ });
40
+
41
+ it.each([
42
+ ["https://example.org/", "https://example.org/"],
43
+ [{ path: "/" }, "/"],
44
+ [undefined, undefined],
45
+ ])("has expected href attribute", (to, expectedHref) => {
46
+ const wrapper = createWrapper({ attrs: { to } });
47
+ expect(wrapper.attributes("href")).toBe(expectedHref);
48
+ });
49
+
50
+ it("renders small size when prop size is 'small'", () => {
51
+ const wrapper = createWrapper({
52
+ props: {
53
+ size: "small",
54
+ },
55
+ });
56
+
57
+ expect(wrapper.classes("h-8")).toBe(true);
58
+ });
59
+
60
+ it("renders large size when prop size is 'large'", () => {
61
+ const wrapper = createWrapper({
62
+ props: {
63
+ size: "large",
64
+ },
65
+ });
66
+
67
+ expect(wrapper.classes("h-12")).toBe(true);
68
+ });
69
+
70
+ it("should render blue config as default when no color prop is defined", () => {
71
+ const wrapper = createWrapper();
72
+ expect(wrapper.classes("bg-blue-600"));
73
+ expect(wrapper.classes("text-white"));
74
+ });
75
+
76
+ it("should render gray when gray as color prop is set", () => {
77
+ const wrapper = createWrapper({
78
+ props: {
79
+ color: "gray",
80
+ },
81
+ });
82
+ expect(wrapper.classes("text-white"));
83
+ expect(wrapper.classes("bg-gray-700"));
84
+ expect(wrapper.classes("hover:bg-gray-800"));
85
+ });
86
+
87
+ it("should disable button when prop is set", () => {
88
+ const wrapper = createWrapper({
89
+ props: {
90
+ disabled: true,
91
+ },
92
+ });
93
+ expect(wrapper.attributes().disabled).toBeDefined();
94
+ });
95
+
96
+ it("should render <button> tag when to prop is not set", () => {
97
+ const wrapper = createWrapper();
98
+ expect(wrapper.element.tagName).toBe("BUTTON");
99
+ expect(wrapper.attributes("href")).toBe(undefined);
100
+ expect(wrapper.element.hasAttribute("type")).toBe(true);
101
+ });
102
+
103
+ it("should render <a> tag when to prop is set", () => {
104
+ const wrapper = createWrapper({
105
+ props: {
106
+ to: "https://www.google.de",
107
+ },
108
+ });
109
+ expect(wrapper.element.tagName).toBe("A");
110
+ expect(wrapper.attributes("href")).toBe("https://www.google.de");
111
+ expect(wrapper.element.hasAttribute("type")).toBe(false);
112
+ });
113
+
114
+ it("should render icon when icon name is set", () => {
115
+ const iconName = "alert";
116
+ const wrapper = createWrapper({
117
+ props: {
118
+ iconName,
119
+ },
120
+ });
121
+ expect(wrapper.findComponent({ name: "UiIcon" }).props()).toMatchObject({
122
+ name: iconName,
123
+ });
124
+ });
125
+
126
+ it("can overwrite display class", () => {
127
+ const wrapper = createWrapper({
128
+ props: {
129
+ class: "flex",
130
+ },
131
+ });
132
+
133
+ expect(wrapper.classes("inline-flex")).toBe(false);
134
+ expect(wrapper.classes("flex")).toBe(true);
135
+ });
136
+ });
@@ -0,0 +1,57 @@
1
+ import type { Meta, StoryObj } from "@storybook/vue3-vite";
2
+
3
+ import { icons } from "../UiIcon/icons.js";
4
+ import UiButton from "./UiButton.vue";
5
+
6
+ const meta = {
7
+ title: "Ui/UiButton",
8
+ component: UiButton,
9
+ argTypes: {
10
+ iconName: {
11
+ control: "select",
12
+ options: Object.keys(icons),
13
+ },
14
+ disabled: { control: "boolean" },
15
+ to: { control: "text" },
16
+ color: {
17
+ control: "select",
18
+ options: [
19
+ "blue",
20
+ "primary-green",
21
+ "transparent",
22
+ "white",
23
+ "gray",
24
+ "light-gray",
25
+ ],
26
+ },
27
+ disabledVariant: {
28
+ control: "select",
29
+ options: ["primary", "secondary"],
30
+ },
31
+ size: {
32
+ control: "select",
33
+ options: ["xs", "small", "medium", "large"],
34
+ },
35
+ },
36
+ args: {
37
+ iconName: null,
38
+ disabled: false,
39
+ color: "blue",
40
+ size: "large",
41
+ disabledVariant: "primary",
42
+ to: undefined,
43
+ },
44
+ } satisfies Meta<typeof UiButton>;
45
+
46
+ export default meta;
47
+ type Story = StoryObj<typeof meta>;
48
+
49
+ export const Default: Story = {
50
+ render: (args) => ({
51
+ setup() {
52
+ return { args };
53
+ },
54
+ components: { UiButton },
55
+ template: "<UiButton v-bind='args'>Submit</UiButton>",
56
+ }),
57
+ };
@@ -0,0 +1,16 @@
1
+ import { mount } from "@vue/test-utils";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ import UiButtonGroup from "./UiButtonGroup.vue";
5
+
6
+ describe("UiButtonGroup", () => {
7
+ it("renders UiButtonGroup with default slot content", () => {
8
+ const wrapper = mount(UiButtonGroup, {
9
+ slots: {
10
+ default: "Default Slot",
11
+ },
12
+ });
13
+
14
+ expect(wrapper.text()).toBe("Default Slot");
15
+ });
16
+ });