@weni/unnnic-system 2.14.2 → 2.15.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": "@weni/unnnic-system",
3
- "version": "2.14.2",
3
+ "version": "2.15.0",
4
4
  "type": "commonjs",
5
5
  "files": [
6
6
  "dist",
@@ -1,6 +1,7 @@
1
1
  <!-- eslint-disable vue/multi-word-component-names -->
2
2
  <template>
3
3
  <div
4
+ data-testid="collapse"
4
5
  :class="[
5
6
  'unnnic-collapse',
6
7
  `unnnic-collapse--size-${size}`,
@@ -12,6 +13,7 @@
12
13
  ]"
13
14
  >
14
15
  <div
16
+ data-testid="collapse-header"
15
17
  class="unnnic-collapse__header"
16
18
  @click="localActive = !localActive"
17
19
  >
@@ -0,0 +1,117 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { describe, it, expect, beforeEach } from 'vitest';
3
+ import Collapse from '../Collapse.vue';
4
+
5
+ describe('Collapse.vue', () => {
6
+ let wrapper;
7
+
8
+ beforeEach(() => {
9
+ wrapper = mount(Collapse, {
10
+ props: { title: 'Test Title' },
11
+ });
12
+ });
13
+
14
+ it('matches the snapshot', () => {
15
+ expect(wrapper.html()).toMatchSnapshot();
16
+ });
17
+
18
+ describe('Props', () => {
19
+ it('should accept title prop and render it correctly', () => {
20
+ expect(wrapper.find('[data-testid="collapse-header"]').text()).toContain(
21
+ 'Test Title',
22
+ );
23
+ });
24
+
25
+ it('should accept active prop and set localActive accordingly', async () => {
26
+ await wrapper.setProps({ active: true });
27
+ expect(wrapper.vm.localActive).toBe(true);
28
+
29
+ await wrapper.setProps({ active: false });
30
+ expect(wrapper.vm.localActive).toBe(false);
31
+ });
32
+
33
+ it('should apply classes based on props', async () => {
34
+ await wrapper.setProps({ borderBottom: true });
35
+ expect(wrapper.classes()).toContain('unnnic-collapse--border-bottom');
36
+
37
+ await wrapper.setProps({ unspacedIcon: true });
38
+ expect(wrapper.classes()).toContain('unnnic-collapse--unspaced-icon');
39
+
40
+ await wrapper.setProps({ size: 'lg' });
41
+ expect(wrapper.classes()).toContain('unnnic-collapse--size-lg');
42
+
43
+ await wrapper.setProps({ size: 'md' });
44
+ expect(wrapper.classes()).toContain('unnnic-collapse--size-md');
45
+
46
+ await wrapper.setProps({ size: undefined });
47
+ expect(wrapper.classes()).toContain('unnnic-collapse--size-lg'); // default size
48
+
49
+ await wrapper.setProps({ modelValue: true });
50
+ expect(wrapper.classes()).toContain('unnnic-collapse--active');
51
+
52
+ await wrapper.setProps({ modelValue: false });
53
+ expect(wrapper.classes()).not.toContain('unnnic-collapse--active');
54
+ });
55
+ });
56
+
57
+ describe('Interactions', () => {
58
+ it('should toggle localActive when header is clicked', async () => {
59
+ const header = wrapper.find('[data-testid="collapse-header"]');
60
+
61
+ expect(wrapper.vm.localActive).toBe(false);
62
+ await header.trigger('click');
63
+ expect(wrapper.vm.localActive).toBe(true);
64
+ await header.trigger('click');
65
+ expect(wrapper.vm.localActive).toBe(false);
66
+ });
67
+
68
+ it('should emit change and update:modelValue on toggle', async () => {
69
+ const header = wrapper.find('[data-testid="collapse-header"]');
70
+
71
+ await header.trigger('click');
72
+
73
+ expect(wrapper.emitted('change')).toEqual([[true]]);
74
+ expect(wrapper.emitted('update:modelValue')).toEqual([[true]]);
75
+
76
+ await header.trigger('click');
77
+
78
+ expect(wrapper.emitted('change')).toEqual([[true], [false]]);
79
+ expect(wrapper.emitted('update:modelValue')).toEqual([[true], [false]]);
80
+ });
81
+ });
82
+
83
+ describe('Slots', () => {
84
+ it('should render default slot content when active', async () => {
85
+ const defaultSlotContent = 'This is default slot content';
86
+ wrapper = mount(Collapse, {
87
+ props: { title: 'Test Title', active: true },
88
+ slots: { default: defaultSlotContent },
89
+ });
90
+ expect(wrapper.html()).toContain(defaultSlotContent);
91
+ });
92
+
93
+ it('should render header slot content if provided', async () => {
94
+ const headerSlotContent =
95
+ '<header data-testid="header-slot">Header Slot Content</header>';
96
+ wrapper = mount(Collapse, {
97
+ props: { title: 'Test Title' },
98
+ slots: { header: headerSlotContent },
99
+ });
100
+ expect(wrapper.find('[data-testid="header-slot"]').exists()).toBe(true);
101
+ });
102
+ });
103
+
104
+ describe('Watchers', () => {
105
+ it('should update localActive when active prop changes', async () => {
106
+ expect(wrapper.vm.localActive).toBe(false);
107
+ await wrapper.setProps({ active: true });
108
+ expect(wrapper.vm.localActive).toBe(true);
109
+ });
110
+
111
+ it('should update localActive when modelValue prop changes', async () => {
112
+ expect(wrapper.vm.localActive).toBe(false);
113
+ await wrapper.setProps({ modelValue: true });
114
+ expect(wrapper.vm.localActive).toBe(true);
115
+ });
116
+ });
117
+ });
@@ -0,0 +1,10 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Collapse.vue > matches the snapshot 1`] = `
4
+ "<div data-v-7d0d9fbd="" data-testid="collapse" class="unnnic-collapse unnnic-collapse--size-lg">
5
+ <div data-v-7d0d9fbd="" data-testid="collapse-header" class="unnnic-collapse__header">Test Title<svg data-v-26446d8e="" data-v-7d0d9fbd="" width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg" class="unnnic-icon unnnic-icon__size--xs unnnic-icon-scheme--neutral-cloudy" data-testid="old-map-icons">
6
+ <path d="M5.31471 14.0096L19.0432 29.5967C19.1676 29.7264 19.3169 29.8296 19.4822 29.9001C19.6474 29.9707 19.8253 30.007 20.005 30.007C20.1847 30.007 20.3625 29.9707 20.5278 29.9001C20.6931 29.8296 20.8424 29.7264 20.9668 29.5967L34.689 14.0096C34.7987 13.886 34.8825 13.7415 34.9353 13.5849C34.9882 13.4282 35.009 13.2625 34.9965 13.0977C34.984 12.9328 34.9385 12.7721 34.8627 12.6252C34.7869 12.4783 34.6824 12.3481 34.5553 12.2423L32.243 10.2963C31.9852 10.0789 31.6522 9.97163 31.316 9.99759C30.9797 10.0235 30.6671 10.1807 30.4457 10.435L20.2406 22.25C20.2112 22.2841 20.1749 22.3114 20.134 22.3302C20.0931 22.3489 20.0487 22.3587 20.0037 22.3587C19.9588 22.3587 19.9143 22.3489 19.8734 22.3302C19.8326 22.3114 19.7962 22.2841 19.7669 22.25L9.558 10.4338C9.33639 10.1806 9.02374 10.0252 8.68809 10.0013C8.52167 9.9865 8.35397 10.0052 8.19489 10.0563C8.03582 10.1074 7.8886 10.1898 7.76195 10.2988L5.44845 12.2423C5.32061 12.3479 5.21534 12.4781 5.13889 12.6252C5.06245 12.7723 5.0164 12.9332 5.0035 13.0985C4.99099 13.2635 5.01212 13.4294 5.06562 13.586C5.11911 13.7426 5.20386 13.8868 5.31471 14.0096Z" fill="#3B414D" class="primary"></path>
7
+ </svg></div>
8
+ <div data-v-7d0d9fbd="" class="unnnic-collapse__body" style="display: none;"></div>
9
+ </div>"
10
+ `;
@@ -2,10 +2,12 @@
2
2
  <aside
3
3
  v-if="modelValue"
4
4
  class="unnnic-drawer"
5
+ data-testid="drawer"
5
6
  >
6
7
  <section
7
8
  v-if="!withoutOverlay"
8
9
  class="unnnic-drawer__overlay"
10
+ data-testid="overlay"
9
11
  @click.stop="close"
10
12
  />
11
13
  <Transition
@@ -14,6 +16,7 @@
14
16
  >
15
17
  <section
16
18
  v-if="showDrawer"
19
+ data-testid="drawer-container"
17
20
  :class="[
18
21
  'unnnic-drawer__container',
19
22
  `unnnic-drawer__container--${size}`,
@@ -21,16 +24,23 @@
21
24
  >
22
25
  <header class="unnnic-drawer__header">
23
26
  <section class="unnnic-drawer__title-container">
24
- <h1 class="unnnic-drawer__title">{{ title }}</h1>
27
+ <h1
28
+ class="unnnic-drawer__title"
29
+ data-testid="drawer-title"
30
+ >
31
+ {{ title }}
32
+ </h1>
25
33
  <p
26
34
  v-if="description"
27
35
  class="unnnic-drawer__description"
36
+ data-testid="drawer-description"
28
37
  >
29
38
  {{ description }}
30
39
  </p>
31
40
  </section>
32
41
  <UnnnicIcon
33
42
  class="unnnic-drawer__close"
43
+ data-testid="close-icon"
34
44
  :icon="closeIcon"
35
45
  size="avatar-nano"
36
46
  clickable
@@ -43,9 +53,11 @@
43
53
  <footer
44
54
  v-if="showFooter"
45
55
  class="unnnic-drawer__footer"
56
+ data-testid="footer"
46
57
  >
47
58
  <UnnnicButton
48
59
  v-if="secondaryButtonText"
60
+ data-testid="secondary-button"
49
61
  size="large"
50
62
  type="tertiary"
51
63
  :disabled="disabledSecondaryButton"
@@ -55,6 +67,7 @@
55
67
  />
56
68
  <UnnnicButton
57
69
  v-if="primaryButtonText"
70
+ data-testid="primary-button"
58
71
  size="large"
59
72
  :disabled="disabledPrimaryButton"
60
73
  :loading="loadingPrimaryButton"
@@ -0,0 +1,253 @@
1
+ import { flushPromises, mount } from '@vue/test-utils';
2
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
3
+ import Drawer from '../Drawer.vue';
4
+ import { nextTick } from 'vue';
5
+
6
+ describe('Drawer.vue', () => {
7
+ let wrapper;
8
+
9
+ beforeEach(() => {
10
+ wrapper = mount(Drawer, {
11
+ props: {
12
+ modelValue: true,
13
+ title: 'Test Title',
14
+ description: 'Test Description',
15
+ primaryButtonText: 'Primary Action',
16
+ secondaryButtonText: 'Secondary Action',
17
+ },
18
+ global: {
19
+ stubs: ['UnnnicIcon', 'UnnnicButton'],
20
+ },
21
+ });
22
+ });
23
+
24
+ const element = (id) => wrapper.find(`[data-testid="${id}"]`);
25
+ const component = (id) => wrapper.findComponent(`[data-testid="${id}"]`);
26
+ const drawer = () => element('drawer');
27
+ const overlay = () => element('overlay');
28
+ const title = () => element('drawer-title');
29
+ const description = () => element('drawer-description');
30
+ const primaryButton = () => component('primary-button');
31
+ const secondaryButton = () => component('secondary-button');
32
+ const footer = () => element('footer');
33
+ const closeIcon = () => component('close-icon');
34
+ const drawerContainer = () => element('drawer-container');
35
+
36
+ describe('Component Rendering', () => {
37
+ describe('Component Rendering', () => {
38
+ it('matches the snapshot', () => {
39
+ expect(wrapper.html()).toMatchSnapshot();
40
+ });
41
+
42
+ it('should render the drawer when modelValue is true', () => {
43
+ expect(drawer().exists()).toBe(true);
44
+ });
45
+
46
+ it('should not render the drawer when modelValue is false', async () => {
47
+ await wrapper.setProps({ modelValue: false });
48
+ expect(drawer().exists()).toBe(false);
49
+ });
50
+
51
+ it('should render the overlay when withoutOverlay is false', () => {
52
+ expect(overlay().exists()).toBe(true);
53
+ });
54
+
55
+ it('should not render the overlay when withoutOverlay is true', async () => {
56
+ await wrapper.setProps({ withoutOverlay: true });
57
+ expect(overlay().exists()).toBe(false);
58
+ });
59
+
60
+ it('should display the title and description correctly', () => {
61
+ expect(title().text()).toBe('Test Title');
62
+ expect(description().text()).toBe('Test Description');
63
+ });
64
+
65
+ it('should not display the description when not provided', async () => {
66
+ await wrapper.setProps({ description: '' });
67
+ expect(description().exists()).toBe(false);
68
+ });
69
+
70
+ it('should render the slot content correctly', () => {
71
+ wrapper = mount(Drawer, {
72
+ props: {
73
+ modelValue: true,
74
+ title: 'Test Title',
75
+ },
76
+ slots: {
77
+ content: '<div data-testid="slot-content">Slot Content</div>',
78
+ },
79
+ });
80
+ expect(wrapper.find('[data-testid="slot-content"]').exists()).toBe(
81
+ true,
82
+ );
83
+ expect(wrapper.find('[data-testid="slot-content"]').text()).toBe(
84
+ 'Slot Content',
85
+ );
86
+ });
87
+ });
88
+ });
89
+
90
+ describe('Button Behavior', () => {
91
+ it('should emit the primaryButtonClick event when the primary button is clicked', async () => {
92
+ await primaryButton().trigger('click');
93
+ expect(wrapper.emitted('primaryButtonClick')).toBeTruthy();
94
+ });
95
+
96
+ it('should disable the primary button when disabledPrimaryButton is true', async () => {
97
+ await wrapper.setProps({ disabledPrimaryButton: true });
98
+ expect(primaryButton().attributes('disabled')).toBeDefined();
99
+ });
100
+
101
+ it('should display the correct text on the primary button', () => {
102
+ expect(primaryButton().props('text')).toBe('Primary Action');
103
+ });
104
+
105
+ it('should emit the secondaryButtonClick event when the secondary button is clicked', async () => {
106
+ await secondaryButton().trigger('click');
107
+ expect(wrapper.emitted('secondaryButtonClick')).toBeTruthy();
108
+ });
109
+
110
+ it('should disable the secondary button when disabledSecondaryButton is true', async () => {
111
+ await wrapper.setProps({ disabledSecondaryButton: true });
112
+ expect(secondaryButton().attributes('disabled')).toBeDefined();
113
+ });
114
+
115
+ it('should display the correct text on the secondary button', () => {
116
+ expect(secondaryButton().props('text')).toBe('Secondary Action');
117
+ });
118
+
119
+ it('should render the footer only if showFooter is true', async () => {
120
+ expect(footer().exists()).toBe(true);
121
+
122
+ await wrapper.setProps({
123
+ primaryButtonText: '',
124
+ secondaryButtonText: '',
125
+ });
126
+
127
+ expect(footer().exists()).toBe(false);
128
+ });
129
+ });
130
+
131
+ describe('Interactions and Transitions', () => {
132
+ beforeEach(() => {
133
+ vi.useFakeTimers();
134
+ });
135
+ afterEach(() => {
136
+ vi.clearAllTimers();
137
+ });
138
+
139
+ it('should close the drawer when the close icon is clicked', async () => {
140
+ await closeIcon().trigger('click');
141
+
142
+ vi.advanceTimersByTime(200);
143
+
144
+ expect(wrapper.emitted('close')).toBeTruthy();
145
+ });
146
+
147
+ it('should call back method when back icon is clicked and distinctCloseBack is true', async () => {
148
+ await wrapper.setProps({ distinctCloseBack: true });
149
+ await closeIcon().trigger('click');
150
+
151
+ vi.advanceTimersByTime(200);
152
+
153
+ expect(wrapper.emitted('back')).toBeTruthy();
154
+ });
155
+
156
+ it('should not emit back event when back icon is clicked and distinctCloseBack is false', async () => {
157
+ await closeIcon().trigger('click');
158
+ expect(wrapper.emitted('back')).toBeUndefined();
159
+ });
160
+
161
+ it('should correctly handle transitions when closing the drawer', async () => {
162
+ await wrapper.vm.close();
163
+ expect(wrapper.vm.showDrawer).toBe(false);
164
+
165
+ setTimeout(() => {
166
+ expect(drawer().exists()).toBe(false);
167
+ }, 200);
168
+ });
169
+
170
+ it('should handle overlay clicks to close the drawer when withoutOverlay is false', async () => {
171
+ expect(overlay().exists()).toBe(true);
172
+ await overlay().trigger('click');
173
+
174
+ vi.advanceTimersByTime(200);
175
+
176
+ expect(wrapper.emitted('close')).toBeTruthy();
177
+ });
178
+
179
+ it('should execute the callback after 200ms timeout and reset showDrawer', async () => {
180
+ const callbackMock = vi.fn();
181
+ wrapper.vm.transitionClose(callbackMock);
182
+
183
+ expect(wrapper.vm.showDrawer).toBe(false);
184
+
185
+ vi.advanceTimersByTime(200);
186
+
187
+ expect(callbackMock).toHaveBeenCalled();
188
+ expect(wrapper.vm.showDrawer).toBe(true);
189
+ });
190
+ });
191
+
192
+ describe('Props and Computed Properties', () => {
193
+ it('should render the correct size class based on size prop', async () => {
194
+ await wrapper.setProps({ size: 'lg' });
195
+ expect(drawerContainer().classes()).toContain(
196
+ 'unnnic-drawer__container--lg',
197
+ );
198
+
199
+ await wrapper.setProps({ size: 'xl' });
200
+ expect(drawerContainer().classes()).toContain(
201
+ 'unnnic-drawer__container--xl',
202
+ );
203
+ });
204
+
205
+ it('should display footer if either primaryButtonText or secondaryButtonText is provided', async () => {
206
+ expect(footer().exists()).toBe(true);
207
+
208
+ await wrapper.setProps({
209
+ primaryButtonText: '',
210
+ secondaryButtonText: 'Secondary Button',
211
+ });
212
+ expect(footer().exists()).toBe(true);
213
+ });
214
+
215
+ it('should not display footer if both primaryButtonText and secondaryButtonText are not provided', async () => {
216
+ await wrapper.setProps({
217
+ primaryButtonText: '',
218
+ secondaryButtonText: '',
219
+ });
220
+
221
+ expect(footer().exists()).toBe(false);
222
+ });
223
+
224
+ it('should disable primary button when disabledPrimaryButton prop is true', async () => {
225
+ await wrapper.setProps({
226
+ primaryButtonText: 'Primary Button',
227
+ disabledPrimaryButton: true,
228
+ });
229
+ expect(primaryButton().attributes('disabled')).toBe('true');
230
+ });
231
+
232
+ it('should disable secondary button when disabledSecondaryButton prop is true', async () => {
233
+ await wrapper.setProps({
234
+ secondaryButtonText: 'Secondary Button',
235
+ disabledSecondaryButton: true,
236
+ });
237
+ expect(secondaryButton().attributes('disabled')).toBe('true');
238
+ });
239
+
240
+ it('should use correct icon for close button based on closeIcon prop', async () => {
241
+ await wrapper.setProps({ closeIcon: 'custom_close_icon' });
242
+ expect(closeIcon().props('icon')).toBe('custom_close_icon');
243
+ });
244
+
245
+ it('should validate size prop to accept only md, lg, or xl values', async () => {
246
+ const validator = Drawer.props.size.validator;
247
+ expect(validator('md')).toBe(true);
248
+ expect(validator('lg')).toBe(true);
249
+ expect(validator('xl')).toBe(true);
250
+ expect(validator('sm')).toBe(false);
251
+ });
252
+ });
253
+ });
@@ -0,0 +1,23 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Drawer.vue > Component Rendering > Component Rendering > matches the snapshot 1`] = `
4
+ "<aside data-v-196de012="" class="unnnic-drawer" data-testid="drawer">
5
+ <section data-v-196de012="" class="unnnic-drawer__overlay" data-testid="overlay"></section>
6
+ <transition-stub data-v-196de012="" name="drawer" appear="true" persisted="false" css="true">
7
+ <section data-v-196de012="" data-testid="drawer-container" class="unnnic-drawer__container unnnic-drawer__container--md">
8
+ <header data-v-196de012="" class="unnnic-drawer__header">
9
+ <section data-v-196de012="" class="unnnic-drawer__title-container">
10
+ <h1 data-v-196de012="" class="unnnic-drawer__title" data-testid="drawer-title">Test Title</h1>
11
+ <p data-v-196de012="" class="unnnic-drawer__description" data-testid="drawer-description">Test Description</p>
12
+ </section>
13
+ <unnnic-icon-stub data-v-196de012="" filled="false" next="false" icon="arrow_back" clickable="true" size="avatar-nano" scheme="neutral-darkest" class="unnnic-drawer__close" data-testid="close-icon"></unnnic-icon-stub>
14
+ </header>
15
+ <section data-v-196de012="" class="unnnic-drawer__content"></section>
16
+ <footer data-v-196de012="" class="unnnic-drawer__footer" data-testid="footer">
17
+ <unnnic-button-stub data-v-196de012="" size="large" text="Secondary Action" type="tertiary" float="false" iconleft="" iconright="" iconcenter="" next="false" disabled="false" loading="false" data-testid="secondary-button"></unnnic-button-stub>
18
+ <unnnic-button-stub data-v-196de012="" size="large" text="Primary Action" type="primary" float="false" iconleft="" iconright="" iconcenter="" next="false" disabled="false" loading="false" data-testid="primary-button"></unnnic-button-stub>
19
+ </footer>
20
+ </section>
21
+ </transition-stub>
22
+ </aside>"
23
+ `;
@@ -2,9 +2,11 @@
2
2
  <section
3
3
  v-if="modelValue"
4
4
  class="unnnic-modal-dialog"
5
+ data-testid="modal-dialog"
5
6
  >
6
7
  <section
7
8
  class="unnnic-modal-dialog__overlay"
9
+ data-testid="modal-overlay"
8
10
  @click.stop="!persistent && close()"
9
11
  />
10
12
  <section
@@ -12,6 +14,7 @@
12
14
  'unnnic-modal-dialog__container',
13
15
  `unnnic-modal-dialog__container--${size}`,
14
16
  ]"
17
+ data-testid="modal-container"
15
18
  >
16
19
  <section
17
20
  v-if="$slots.leftSidebar"
@@ -28,17 +31,22 @@
28
31
  <section class="unnnic-modal-dialog__container__title-container">
29
32
  <UnnnicIcon
30
33
  v-if="icon || type"
34
+ data-testid="title-icon"
31
35
  class="unnnic-modal-dialog__container__title-icon"
32
36
  :icon="icon || iconsMapper[type]?.icon"
33
37
  :scheme="iconScheme || iconsMapper[type]?.scheme"
34
38
  size="md"
35
39
  />
36
- <h1 class="unnnic-modal-dialog__container__title-text">
40
+ <h1
41
+ class="unnnic-modal-dialog__container__title-text"
42
+ data-testid="title-text"
43
+ >
37
44
  {{ title }}
38
45
  </h1>
39
46
  </section>
40
47
  <UnnnicIcon
41
48
  v-if="showCloseIcon"
49
+ data-testid="close-icon"
42
50
  icon="close"
43
51
  clickable
44
52
  @click="close()"
@@ -49,6 +57,7 @@
49
57
  </section>
50
58
  <section
51
59
  v-if="primaryButtonProps.text"
60
+ data-testid="actions-section"
52
61
  :class="[
53
62
  'unnnic-modal-dialog__container__actions',
54
63
  {
@@ -60,6 +69,7 @@
60
69
  <UnnnicButton
61
70
  v-if="!hideSecondaryButton"
62
71
  v-bind="secondaryButtonProps"
72
+ data-testid="secondary-button"
63
73
  type="tertiary"
64
74
  :text="secondaryButtonProps.text || i18n('cancel')"
65
75
  class="unnnic-modal-dialog__container__actions__secondary-button"
@@ -71,6 +81,7 @@
71
81
  />
72
82
  <UnnnicButton
73
83
  v-bind="primaryButtonProps"
84
+ data-testid="primary-button"
74
85
  :type="
75
86
  primaryButtonProps.type ||
76
87
  primaryButtonTypeMapper[type] ||