@htlkg/components 0.0.1 → 0.0.2

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.
@@ -24,38 +24,37 @@ describe('Tabs Component', () => {
24
24
  const wrapper = mount(Tabs, {
25
25
  props: {
26
26
  tabs: mockTabs,
27
- activeTab: 'tab1',
28
- 'onUpdate:activeTab': (value: string) => wrapper.setProps({ activeTab: value })
27
+ modelValue: 'tab1',
28
+ 'onUpdate:modelValue': (value: string) => wrapper.setProps({ modelValue: value })
29
29
  }
30
30
  });
31
31
 
32
- expect(wrapper.props('activeTab')).toBe('tab1');
32
+ expect(wrapper.props('modelValue')).toBe('tab1');
33
33
 
34
- // Change active tab
35
- const component = wrapper.vm as any;
36
- component.handleTabClick('tab2');
34
+ // Click on tab2
35
+ const buttons = wrapper.findAll('button');
36
+ await buttons[1].trigger('click');
37
37
 
38
- await wrapper.vm.$nextTick();
39
- expect(wrapper.emitted('update:activeTab')).toBeTruthy();
40
- expect(wrapper.emitted('update:activeTab')?.[0]).toEqual(['tab2']);
38
+ expect(wrapper.emitted('update:modelValue')).toBeTruthy();
39
+ expect(wrapper.emitted('update:modelValue')?.[0]).toEqual(['tab2']);
41
40
  });
42
41
 
43
42
  it('emits tab-change event when tab is clicked', async () => {
44
43
  const wrapper = mount(Tabs, {
45
44
  props: {
46
45
  tabs: mockTabs,
47
- activeTab: 'tab1'
46
+ modelValue: 'tab1'
48
47
  }
49
48
  });
50
49
 
51
- const component = wrapper.vm as any;
52
- component.handleTabClick('tab2');
50
+ const buttons = wrapper.findAll('button');
51
+ await buttons[1].trigger('click');
53
52
 
54
53
  expect(wrapper.emitted('tab-change')).toBeTruthy();
55
54
  expect(wrapper.emitted('tab-change')?.[0]).toEqual(['tab2']);
56
55
  });
57
56
 
58
- it('defaults to first tab when no activeTab is provided', () => {
57
+ it('defaults to first tab when no modelValue is provided', () => {
59
58
  const wrapper = mount(Tabs, {
60
59
  props: {
61
60
  tabs: mockTabs
@@ -63,14 +62,14 @@ describe('Tabs Component', () => {
63
62
  });
64
63
 
65
64
  const component = wrapper.vm as any;
66
- expect(component.currentTab).toBe('tab1');
65
+ expect(component.getActiveTab()).toBe('tab1');
67
66
  });
68
67
 
69
- it('exposes setActiveTab method', () => {
68
+ it('exposes setActiveTab method', async () => {
70
69
  const wrapper = mount(Tabs, {
71
70
  props: {
72
71
  tabs: mockTabs,
73
- activeTab: 'tab1'
72
+ modelValue: 'tab1'
74
73
  }
75
74
  });
76
75
 
@@ -79,14 +78,15 @@ describe('Tabs Component', () => {
79
78
  expect(typeof component.setActiveTab).toBe('function');
80
79
 
81
80
  component.setActiveTab('tab3');
82
- expect(wrapper.emitted('update:activeTab')).toBeTruthy();
81
+ await wrapper.vm.$nextTick();
82
+ expect(wrapper.emitted('update:modelValue')).toBeTruthy();
83
83
  });
84
84
 
85
85
  it('exposes getActiveTab method', () => {
86
86
  const wrapper = mount(Tabs, {
87
87
  props: {
88
88
  tabs: mockTabs,
89
- activeTab: 'tab2'
89
+ modelValue: 'tab2'
90
90
  }
91
91
  });
92
92
 
@@ -100,7 +100,7 @@ describe('Tabs Component', () => {
100
100
  const wrapper = mount(Tabs, {
101
101
  props: {
102
102
  tabs: mockTabs,
103
- activeTab: 'tab1'
103
+ modelValue: 'tab1'
104
104
  }
105
105
  });
106
106
 
@@ -108,15 +108,15 @@ describe('Tabs Component', () => {
108
108
  component.nextTab();
109
109
 
110
110
  await wrapper.vm.$nextTick();
111
- expect(wrapper.emitted('update:activeTab')).toBeTruthy();
112
- expect(wrapper.emitted('update:activeTab')?.[0]).toEqual(['tab2']);
111
+ expect(wrapper.emitted('update:modelValue')).toBeTruthy();
112
+ expect(wrapper.emitted('update:modelValue')?.[0]).toEqual(['tab2']);
113
113
  });
114
114
 
115
115
  it('exposes previousTab method', async () => {
116
116
  const wrapper = mount(Tabs, {
117
117
  props: {
118
118
  tabs: mockTabs,
119
- activeTab: 'tab2'
119
+ modelValue: 'tab2'
120
120
  }
121
121
  });
122
122
 
@@ -124,15 +124,15 @@ describe('Tabs Component', () => {
124
124
  component.previousTab();
125
125
 
126
126
  await wrapper.vm.$nextTick();
127
- expect(wrapper.emitted('update:activeTab')).toBeTruthy();
128
- expect(wrapper.emitted('update:activeTab')?.[0]).toEqual(['tab1']);
127
+ expect(wrapper.emitted('update:modelValue')).toBeTruthy();
128
+ expect(wrapper.emitted('update:modelValue')?.[0]).toEqual(['tab1']);
129
129
  });
130
130
 
131
131
  it('does not go beyond last tab with nextTab', async () => {
132
132
  const wrapper = mount(Tabs, {
133
133
  props: {
134
134
  tabs: mockTabs,
135
- activeTab: 'tab3'
135
+ modelValue: 'tab3'
136
136
  }
137
137
  });
138
138
 
@@ -142,13 +142,14 @@ describe('Tabs Component', () => {
142
142
  await wrapper.vm.$nextTick();
143
143
  // Should not emit since we're already at the last tab
144
144
  expect(component.getActiveTab()).toBe('tab3');
145
+ expect(wrapper.emitted('update:modelValue')).toBeFalsy();
145
146
  });
146
147
 
147
148
  it('does not go before first tab with previousTab', async () => {
148
149
  const wrapper = mount(Tabs, {
149
150
  props: {
150
151
  tabs: mockTabs,
151
- activeTab: 'tab1'
152
+ modelValue: 'tab1'
152
153
  }
153
154
  });
154
155
 
@@ -158,13 +159,14 @@ describe('Tabs Component', () => {
158
159
  await wrapper.vm.$nextTick();
159
160
  // Should not emit since we're already at the first tab
160
161
  expect(component.getActiveTab()).toBe('tab1');
162
+ expect(wrapper.emitted('update:modelValue')).toBeFalsy();
161
163
  });
162
164
 
163
165
  it('renders tab content slot', () => {
164
166
  const wrapper = mount(Tabs, {
165
167
  props: {
166
168
  tabs: mockTabs,
167
- activeTab: 'tab1'
169
+ modelValue: 'tab1'
168
170
  },
169
171
  slots: {
170
172
  tab1: '<div class="tab1-content">Tab 1 Content</div>'
@@ -172,5 +174,31 @@ describe('Tabs Component', () => {
172
174
  });
173
175
 
174
176
  expect(wrapper.find('.tabs-content').exists()).toBe(true);
177
+ expect(wrapper.html()).toContain('Tab 1 Content');
178
+ });
179
+
180
+ it('renders tab labels', () => {
181
+ const wrapper = mount(Tabs, {
182
+ props: {
183
+ tabs: mockTabs
184
+ }
185
+ });
186
+
187
+ expect(wrapper.text()).toContain('Tab 1');
188
+ expect(wrapper.text()).toContain('Tab 2');
189
+ expect(wrapper.text()).toContain('Tab 3');
190
+ });
191
+
192
+ it('shows count badges when provided', () => {
193
+ const wrapper = mount(Tabs, {
194
+ props: {
195
+ tabs: mockTabs,
196
+ modelValue: 'tab1'
197
+ }
198
+ });
199
+
200
+ // Tab 1 has count 5, Tab 2 has count 10
201
+ expect(wrapper.text()).toContain('5');
202
+ expect(wrapper.text()).toContain('10');
175
203
  });
176
204
  });
@@ -3,3 +3,4 @@ export type { Tab } from './Tabs.vue';
3
3
  export { default as Stepper } from './Stepper.vue';
4
4
  export type { Step } from './Stepper.vue';
5
5
  export { default as Breadcrumbs } from './Breadcrumbs.vue';
6
+ export { default as AdminWrapper } from './AdminWrapper.vue';
@@ -1,10 +1,35 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { mount } from '@vue/test-utils';
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { shallowMount } from '@vue/test-utils';
3
+ import { h, defineComponent } from 'vue';
4
+
5
+ // Mock the @hotelinking/ui module before importing the component
6
+ vi.mock('@hotelinking/ui', () => ({
7
+ uiAlert: defineComponent({
8
+ name: 'uiAlert',
9
+ props: ['title', 'type', 'actions', 'loading'],
10
+ emits: ['alert-event'],
11
+ setup(props, { slots, emit }) {
12
+ return () => h('div', { class: 'ui-alert', 'data-type': props.type }, [
13
+ h('div', { class: 'alert-title' }, props.title),
14
+ slots.default?.(),
15
+ props.actions?.map((action: any, index: number) =>
16
+ h('button', {
17
+ key: index,
18
+ class: 'alert-action',
19
+ onClick: () => emit('alert-event', action.event)
20
+ }, action.name)
21
+ )
22
+ ]);
23
+ }
24
+ })
25
+ }));
26
+
27
+ // Import after mocking
3
28
  import Alert from './Alert.vue';
4
29
 
5
30
  describe('Alert Component', () => {
6
31
  it('renders with basic props', () => {
7
- const wrapper = mount(Alert, {
32
+ const wrapper = shallowMount(Alert, {
8
33
  props: {
9
34
  title: 'Test Alert',
10
35
  type: 'info'
@@ -18,7 +43,7 @@ describe('Alert Component', () => {
18
43
  const types = ['info', 'success', 'warning', 'danger'] as const;
19
44
 
20
45
  types.forEach(type => {
21
- const wrapper = mount(Alert, {
46
+ const wrapper = shallowMount(Alert, {
22
47
  props: {
23
48
  title: 'Test Alert',
24
49
  type
@@ -35,7 +60,7 @@ describe('Alert Component', () => {
35
60
  { name: 'Cancel', event: 'cancel' }
36
61
  ];
37
62
 
38
- const wrapper = mount(Alert, {
63
+ const wrapper = shallowMount(Alert, {
39
64
  props: {
40
65
  title: 'Test Alert',
41
66
  type: 'warning',
@@ -47,25 +72,8 @@ describe('Alert Component', () => {
47
72
  expect(wrapper.props('actions')).toEqual(actions);
48
73
  });
49
74
 
50
- it('emits alertEvent when action is triggered', async () => {
51
- const wrapper = mount(Alert, {
52
- props: {
53
- title: 'Test Alert',
54
- type: 'info',
55
- actions: [{ name: 'OK', event: 'ok' }]
56
- }
57
- });
58
-
59
- const component = wrapper.vm as any;
60
- if (component.handleAlertEvent) {
61
- component.handleAlertEvent('ok');
62
- expect(wrapper.emitted('alertEvent')).toBeTruthy();
63
- expect(wrapper.emitted('alertEvent')?.[0]).toEqual(['ok']);
64
- }
65
- });
66
-
67
75
  it('renders with show prop', () => {
68
- const wrapper = mount(Alert, {
76
+ const wrapper = shallowMount(Alert, {
69
77
  props: {
70
78
  title: 'Test Alert',
71
79
  type: 'info',
@@ -78,7 +86,7 @@ describe('Alert Component', () => {
78
86
  });
79
87
 
80
88
  it('hides when show is false', () => {
81
- const wrapper = mount(Alert, {
89
+ const wrapper = shallowMount(Alert, {
82
90
  props: {
83
91
  title: 'Test Alert',
84
92
  type: 'info',
@@ -86,28 +94,12 @@ describe('Alert Component', () => {
86
94
  }
87
95
  });
88
96
 
89
- expect(wrapper.find('div').exists()).toBe(false);
90
- });
91
-
92
- it('supports v-model for show state', async () => {
93
- const wrapper = mount(Alert, {
94
- props: {
95
- title: 'Test Alert',
96
- type: 'info',
97
- show: false,
98
- 'onUpdate:show': (value: boolean) => wrapper.setProps({ show: value })
99
- }
100
- });
101
-
102
- const component = wrapper.vm as any;
103
- component.show();
104
-
105
- await wrapper.vm.$nextTick();
106
- expect(wrapper.emitted('update:show')).toBeTruthy();
97
+ // When show is false, the alert should not render its content
98
+ expect(wrapper.find('.ui-alert').exists()).toBe(false);
107
99
  });
108
100
 
109
101
  it('exposes show, hide, and toggle methods', () => {
110
- const wrapper = mount(Alert, {
102
+ const wrapper = shallowMount(Alert, {
111
103
  props: {
112
104
  title: 'Test Alert',
113
105
  type: 'info'
@@ -115,40 +107,13 @@ describe('Alert Component', () => {
115
107
  });
116
108
 
117
109
  const component = wrapper.vm as any;
118
- expect(component.show).toBeDefined();
119
- expect(component.hide).toBeDefined();
120
- expect(component.toggle).toBeDefined();
121
- });
122
-
123
- it('renders with loading state', () => {
124
- const wrapper = mount(Alert, {
125
- props: {
126
- title: 'Loading Alert',
127
- type: 'info',
128
- loading: true
129
- }
130
- });
131
-
132
- expect(wrapper.exists()).toBe(true);
133
- expect(wrapper.props('loading')).toBe(true);
134
- });
135
-
136
- it('renders slot content', () => {
137
- const wrapper = mount(Alert, {
138
- props: {
139
- title: 'Test Alert',
140
- type: 'info'
141
- },
142
- slots: {
143
- default: '<p>Custom alert content</p>'
144
- }
145
- });
146
-
147
- expect(wrapper.html()).toContain('Custom alert content');
110
+ expect(typeof component.show).toBe('function');
111
+ expect(typeof component.hide).toBe('function');
112
+ expect(typeof component.toggle).toBe('function');
148
113
  });
149
114
 
150
115
  it('emits close event when hidden', async () => {
151
- const wrapper = mount(Alert, {
116
+ const wrapper = shallowMount(Alert, {
152
117
  props: {
153
118
  title: 'Test Alert',
154
119
  type: 'info',
@@ -12,24 +12,18 @@ describe('Drawer Component', () => {
12
12
  });
13
13
 
14
14
  expect(wrapper.exists()).toBe(true);
15
+ expect(wrapper.find('.fixed').exists()).toBe(true);
15
16
  });
16
17
 
17
- it('supports v-model for open state', async () => {
18
+ it('does not render when closed', () => {
18
19
  const wrapper = mount(Drawer, {
19
20
  props: {
20
21
  open: false,
21
- 'onUpdate:open': (value: boolean) => wrapper.setProps({ open: value })
22
+ title: 'Test Drawer'
22
23
  }
23
24
  });
24
25
 
25
- expect(wrapper.props('open')).toBe(false);
26
-
27
- const component = wrapper.vm as any;
28
- if (component.open) {
29
- component.open();
30
- await wrapper.vm.$nextTick();
31
- expect(wrapper.emitted('update:open')).toBeTruthy();
32
- }
26
+ expect(wrapper.find('.fixed').exists()).toBe(false);
33
27
  });
34
28
 
35
29
  it('emits close event when drawer is closed', async () => {
@@ -40,15 +34,15 @@ describe('Drawer Component', () => {
40
34
  });
41
35
 
42
36
  const component = wrapper.vm as any;
43
- if (component.close) {
44
- component.close();
45
- await wrapper.vm.$nextTick();
46
- expect(wrapper.emitted('update:open')).toBeTruthy();
47
- expect(wrapper.emitted('close')).toBeTruthy();
48
- }
37
+ component.close();
38
+
39
+ await wrapper.vm.$nextTick();
40
+ expect(wrapper.emitted('update:open')).toBeTruthy();
41
+ expect(wrapper.emitted('update:open')?.[0]).toEqual([false]);
42
+ expect(wrapper.emitted('close')).toBeTruthy();
49
43
  });
50
44
 
51
- it('exposes open and close methods', () => {
45
+ it('exposes open, close, and toggle methods', () => {
52
46
  const wrapper = mount(Drawer, {
53
47
  props: {
54
48
  open: false
@@ -56,20 +50,19 @@ describe('Drawer Component', () => {
56
50
  });
57
51
 
58
52
  const component = wrapper.vm as any;
59
- if (component.open && component.close) {
60
- expect(typeof component.open).toBe('function');
61
- expect(typeof component.close).toBe('function');
62
- }
53
+ expect(typeof component.open).toBe('function');
54
+ expect(typeof component.close).toBe('function');
55
+ expect(typeof component.toggle).toBe('function');
63
56
  });
64
57
 
65
58
  it('renders with different positions', () => {
66
- const positions = ['left', 'right', 'top', 'bottom'];
59
+ const positions = ['left', 'right', 'top', 'bottom'] as const;
67
60
 
68
61
  positions.forEach(position => {
69
62
  const wrapper = mount(Drawer, {
70
63
  props: {
71
64
  open: true,
72
- position: position as any
65
+ position
73
66
  }
74
67
  });
75
68
 
@@ -88,5 +81,46 @@ describe('Drawer Component', () => {
88
81
  });
89
82
 
90
83
  expect(wrapper.html()).toContain('drawer-content');
84
+ expect(wrapper.html()).toContain('Custom Content');
85
+ });
86
+
87
+ it('closes when clicking overlay', async () => {
88
+ const wrapper = mount(Drawer, {
89
+ props: {
90
+ open: true
91
+ }
92
+ });
93
+
94
+ // Click the overlay (first fixed div)
95
+ await wrapper.find('.bg-black').trigger('click');
96
+
97
+ expect(wrapper.emitted('update:open')).toBeTruthy();
98
+ expect(wrapper.emitted('update:open')?.[0]).toEqual([false]);
99
+ });
100
+
101
+ it('does not close when clicking drawer content', async () => {
102
+ const wrapper = mount(Drawer, {
103
+ props: {
104
+ open: true
105
+ }
106
+ });
107
+
108
+ // Click the drawer content area (the white bg div)
109
+ const drawerContent = wrapper.find('.bg-white');
110
+ await drawerContent.trigger('click');
111
+
112
+ // Should not emit close
113
+ expect(wrapper.emitted('update:open')).toBeFalsy();
114
+ });
115
+
116
+ it('displays title', () => {
117
+ const wrapper = mount(Drawer, {
118
+ props: {
119
+ open: true,
120
+ title: 'My Drawer Title'
121
+ }
122
+ });
123
+
124
+ expect(wrapper.text()).toContain('My Drawer Title');
91
125
  });
92
126
  });
@@ -1,5 +1,31 @@
1
- import { describe, it, expect, beforeAll } from 'vitest';
2
- import { mount } from '@vue/test-utils';
1
+ import { describe, it, expect, vi, beforeAll, beforeEach } from 'vitest';
2
+ import { mount, shallowMount } from '@vue/test-utils';
3
+ import { h, defineComponent } from 'vue';
4
+
5
+ // Mock the @hotelinking/ui module before importing the component
6
+ vi.mock('@hotelinking/ui', () => ({
7
+ uiModal: defineComponent({
8
+ name: 'uiModal',
9
+ props: ['title', 'content', 'modalName', 'open', 'actions'],
10
+ emits: ['modalAction'],
11
+ setup(props, { slots, emit }) {
12
+ return () => props.open ? h('div', { class: 'ui-modal' }, [
13
+ h('div', { class: 'modal-title' }, props.title),
14
+ h('div', { class: 'modal-content' }, props.content),
15
+ slots.default?.(),
16
+ props.actions?.map((action: any, index: number) =>
17
+ h('button', {
18
+ key: index,
19
+ class: 'modal-action',
20
+ onClick: () => emit('modalAction', { modal: props.modalName, action: action.value })
21
+ }, action.text)
22
+ )
23
+ ]) : null;
24
+ }
25
+ })
26
+ }));
27
+
28
+ // Import after mocking
3
29
  import Modal from './Modal.vue';
4
30
 
5
31
  // Mock ResizeObserver
@@ -13,7 +39,7 @@ beforeAll(() => {
13
39
 
14
40
  describe('Modal Component', () => {
15
41
  it('renders with basic props', () => {
16
- const wrapper = mount(Modal, {
42
+ const wrapper = shallowMount(Modal, {
17
43
  props: {
18
44
  open: true,
19
45
  title: 'Test Modal',
@@ -24,8 +50,19 @@ describe('Modal Component', () => {
24
50
  expect(wrapper.exists()).toBe(true);
25
51
  });
26
52
 
53
+ it('does not render modal content when closed', () => {
54
+ const wrapper = shallowMount(Modal, {
55
+ props: {
56
+ open: false,
57
+ title: 'Test Modal'
58
+ }
59
+ });
60
+
61
+ expect(wrapper.find('.ui-modal').exists()).toBe(false);
62
+ });
63
+
27
64
  it('supports v-model for open state', async () => {
28
- const wrapper = mount(Modal, {
65
+ const wrapper = shallowMount(Modal, {
29
66
  props: {
30
67
  open: false,
31
68
  'onUpdate:open': (value: boolean) => wrapper.setProps({ open: value })
@@ -34,7 +71,6 @@ describe('Modal Component', () => {
34
71
 
35
72
  expect(wrapper.props('open')).toBe(false);
36
73
 
37
- // Open the modal using exposed method
38
74
  const component = wrapper.vm as any;
39
75
  component.open();
40
76
 
@@ -44,7 +80,7 @@ describe('Modal Component', () => {
44
80
  });
45
81
 
46
82
  it('emits close event when modal is closed', async () => {
47
- const wrapper = mount(Modal, {
83
+ const wrapper = shallowMount(Modal, {
48
84
  props: {
49
85
  open: true
50
86
  }
@@ -60,23 +96,20 @@ describe('Modal Component', () => {
60
96
  });
61
97
 
62
98
  it('exposes open, close, and toggle methods', () => {
63
- const wrapper = mount(Modal, {
99
+ const wrapper = shallowMount(Modal, {
64
100
  props: {
65
101
  open: false
66
102
  }
67
103
  });
68
104
 
69
105
  const component = wrapper.vm as any;
70
- expect(component.open).toBeDefined();
71
- expect(component.close).toBeDefined();
72
- expect(component.toggle).toBeDefined();
73
106
  expect(typeof component.open).toBe('function');
74
107
  expect(typeof component.close).toBe('function');
75
108
  expect(typeof component.toggle).toBe('function');
76
109
  });
77
110
 
78
- it('handles action events', async () => {
79
- const wrapper = mount(Modal, {
111
+ it('renders with actions', () => {
112
+ const wrapper = shallowMount(Modal, {
80
113
  props: {
81
114
  open: true,
82
115
  actions: [
@@ -86,43 +119,22 @@ describe('Modal Component', () => {
86
119
  }
87
120
  });
88
121
 
89
- const component = wrapper.vm as any;
90
- component.handleAction({ value: 'confirm' });
91
-
92
- expect(wrapper.emitted('action')).toBeTruthy();
93
- expect(wrapper.emitted('action')?.[0]).toEqual([{ value: 'confirm' }]);
122
+ expect(wrapper.exists()).toBe(true);
123
+ expect(wrapper.props('actions')).toHaveLength(2);
94
124
  });
95
125
 
96
- it('closes modal when action value is close or cancel', async () => {
97
- const wrapper = mount(Modal, {
126
+ it('toggle method switches open state', async () => {
127
+ const wrapper = shallowMount(Modal, {
98
128
  props: {
99
- open: true
129
+ open: false
100
130
  }
101
131
  });
102
132
 
103
133
  const component = wrapper.vm as any;
104
- component.handleAction({ value: 'cancel' });
105
-
134
+
135
+ // Toggle to open
136
+ component.toggle();
106
137
  await wrapper.vm.$nextTick();
107
- expect(wrapper.emitted('update:open')).toBeTruthy();
108
- expect(wrapper.emitted('update:open')?.[0]).toEqual([false]);
109
- });
110
-
111
- it('renders slots correctly', () => {
112
- const wrapper = mount(Modal, {
113
- props: {
114
- open: true
115
- },
116
- slots: {
117
- default: '<div class="custom-content">Custom Content</div>',
118
- header: '<div class="custom-header">Custom Header</div>',
119
- footer: '<div class="custom-footer">Custom Footer</div>'
120
- }
121
- });
122
-
123
- // Modal uses uiModal which may not render slots immediately in test environment
124
- // Just verify the component exists and has the right props
125
- expect(wrapper.exists()).toBe(true);
126
- expect(wrapper.props('open')).toBe(true);
138
+ expect(wrapper.emitted('update:open')?.[0]).toEqual([true]);
127
139
  });
128
140
  });
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Stores
3
+ *
4
+ * Nanostores for shared state management
5
+ */
6
+
7
+ export { $user, setUser, clearUser, type User } from './user';