@veritree/ui 0.36.0 → 0.38.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/.vscode/settings.json +1 -0
- package/mixins/floating-ui-content.js +1 -1
- package/package.json +13 -2
- package/src/components/Alert/VTAlert.vue +25 -11
- package/src/components/Tabs/VTTabGroup.vue +14 -14
- package/src/components/Tooltip/VTTooltipTrigger.vue +1 -3
- package/src/components/Utils/FloatingUi.vue +20 -4
- package/test/alert.test.js +158 -0
- package/test/button.test.js +134 -0
- package/vitest.config.js +22 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veritree/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "veritree ui library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -10,14 +10,25 @@
|
|
|
10
10
|
"publishConfig": {
|
|
11
11
|
"access": "public"
|
|
12
12
|
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"test": "vitest",
|
|
15
|
+
"coverage": "vitest run --coverage"
|
|
16
|
+
},
|
|
13
17
|
"dependencies": {
|
|
14
18
|
"@floating-ui/dom": "^1.2.0",
|
|
15
19
|
"@linusborg/vue-simple-portal": "^0.1.5",
|
|
16
20
|
"@veritree/icons": "^0.43.0"
|
|
17
21
|
},
|
|
18
22
|
"devDependencies": {
|
|
23
|
+
"@vitejs/plugin-vue2": "^1.1.2",
|
|
24
|
+
"@vue/test-utils": "^1.3.0",
|
|
25
|
+
"jsdom": "latest",
|
|
19
26
|
"prettier": "^2.7.1",
|
|
20
27
|
"prettier-plugin-tailwindcss": "^0.1.13",
|
|
21
|
-
"tailwindcss": "^3.2.4"
|
|
28
|
+
"tailwindcss": "^3.2.4",
|
|
29
|
+
"vite": "latest",
|
|
30
|
+
"vitest": "latest",
|
|
31
|
+
"vue": "^2.7.2",
|
|
32
|
+
"vue-template-compiler": "^2.7.2"
|
|
22
33
|
}
|
|
23
34
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
-
v-if="
|
|
3
|
+
v-if="visible"
|
|
4
4
|
:class="[
|
|
5
5
|
// default styles
|
|
6
6
|
headless ? 'alert' : 'flex items-start gap-3 rounded border border-solid',
|
|
@@ -29,9 +29,15 @@
|
|
|
29
29
|
<button
|
|
30
30
|
v-if="dismissable"
|
|
31
31
|
:class="[
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
// default styles
|
|
33
|
+
headless ? 'alert-close' : 'ml-auto h-4 w-4 shrink-0 text-current',
|
|
34
|
+
headless
|
|
35
|
+
? `alert-close--${variant}`
|
|
36
|
+
: isLarge
|
|
37
|
+
? 'mt-1'
|
|
38
|
+
: isSmall
|
|
39
|
+
? 'mt-0.5'
|
|
40
|
+
: null,
|
|
35
41
|
]"
|
|
36
42
|
@click="hide"
|
|
37
43
|
>
|
|
@@ -41,9 +47,19 @@
|
|
|
41
47
|
</template>
|
|
42
48
|
|
|
43
49
|
<script>
|
|
50
|
+
import IconClose from '@veritree/icons/src/components/IconClose.vue';
|
|
51
|
+
|
|
44
52
|
export default {
|
|
45
53
|
name: 'VTAlert',
|
|
46
54
|
|
|
55
|
+
components: {
|
|
56
|
+
IconClose,
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
model: {
|
|
60
|
+
prop: 'visible',
|
|
61
|
+
},
|
|
62
|
+
|
|
47
63
|
props: {
|
|
48
64
|
variant: {
|
|
49
65
|
type: String,
|
|
@@ -61,12 +77,10 @@ export default {
|
|
|
61
77
|
type: Boolean,
|
|
62
78
|
default: false,
|
|
63
79
|
},
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
show: true,
|
|
69
|
-
};
|
|
80
|
+
visible: {
|
|
81
|
+
type: Boolean,
|
|
82
|
+
default: false,
|
|
83
|
+
},
|
|
70
84
|
},
|
|
71
85
|
|
|
72
86
|
computed: {
|
|
@@ -93,8 +107,8 @@ export default {
|
|
|
93
107
|
|
|
94
108
|
methods: {
|
|
95
109
|
hide() {
|
|
110
|
+
this.$emit('input', false);
|
|
96
111
|
this.$emit('dismiss');
|
|
97
|
-
this.show = false;
|
|
98
112
|
},
|
|
99
113
|
},
|
|
100
114
|
};
|
|
@@ -4,24 +4,14 @@
|
|
|
4
4
|
</div>
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
|
-
<style scoped>
|
|
8
|
-
.TabGroup.vertical{
|
|
9
|
-
display: flex;
|
|
10
|
-
}
|
|
11
|
-
.TabGroup.vertical .TabList{
|
|
12
|
-
display: flex;
|
|
13
|
-
flex-direction: column;
|
|
14
|
-
}
|
|
15
|
-
</style>
|
|
16
|
-
|
|
17
7
|
<script>
|
|
18
8
|
export default {
|
|
19
9
|
name: 'VTTabGroup',
|
|
20
10
|
props: {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
11
|
+
vertical: {
|
|
12
|
+
type: Boolean,
|
|
13
|
+
default: false,
|
|
14
|
+
},
|
|
25
15
|
},
|
|
26
16
|
provide() {
|
|
27
17
|
return {
|
|
@@ -113,3 +103,13 @@ export default {
|
|
|
113
103
|
},
|
|
114
104
|
};
|
|
115
105
|
</script>
|
|
106
|
+
|
|
107
|
+
<style scoped>
|
|
108
|
+
.TabGroup.vertical {
|
|
109
|
+
display: flex;
|
|
110
|
+
}
|
|
111
|
+
.TabGroup.vertical .TabList {
|
|
112
|
+
display: flex;
|
|
113
|
+
flex-direction: column;
|
|
114
|
+
}
|
|
115
|
+
</style>
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
<div
|
|
3
3
|
:id="id"
|
|
4
4
|
:aria-describedby="ariaDescribedBy"
|
|
5
|
-
class="flex min-w-min"
|
|
6
5
|
@mouseenter="onMouseenter"
|
|
7
6
|
@mouseleave="onmouseout"
|
|
8
7
|
>
|
|
@@ -75,8 +74,7 @@ export default {
|
|
|
75
74
|
// delay stop propagation to close other visible
|
|
76
75
|
// dropdowns and delay click event to control
|
|
77
76
|
// this dropdown visibility
|
|
78
|
-
|
|
79
|
-
setTimeout(() => this.showComponentContent(), 100);
|
|
77
|
+
this.showComponentContent();
|
|
80
78
|
},
|
|
81
79
|
|
|
82
80
|
cancel() {
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
<Portal>
|
|
3
3
|
<transition
|
|
4
4
|
enter-active-class="duration-200 ease-out"
|
|
5
|
-
enter-class="
|
|
6
|
-
enter-to-class="
|
|
5
|
+
:enter-class="transitionEnterClass"
|
|
6
|
+
:enter-to-class="transitionEnterToClass"
|
|
7
7
|
leave-active-class="duration-200 ease-in"
|
|
8
|
-
leave-class="
|
|
9
|
-
leave-to-class="
|
|
8
|
+
:leave-class="transitionLeaveClass"
|
|
9
|
+
:leave-to-class="transitionLeaveToClass"
|
|
10
10
|
@after-leave="hidden"
|
|
11
11
|
@after-enter="shown"
|
|
12
12
|
>
|
|
@@ -62,6 +62,22 @@ export default {
|
|
|
62
62
|
? 'bg-gray-800 text-sm text-white py-1 px-2'
|
|
63
63
|
: 'bg-white py-2 px-3';
|
|
64
64
|
},
|
|
65
|
+
|
|
66
|
+
transitionEnterClass() {
|
|
67
|
+
return this.isTooltip ? 'opacity-0' : 'translate-y-[15px] opacity-0';
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
transitionEnterToClass() {
|
|
71
|
+
return this.isTooltip ? 'opacity-100' : 'translate-y-0 opacity-100';
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
transitionLeaveClass() {
|
|
75
|
+
return this.transitionEnterToClass;
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
transitionLeaveToClass() {
|
|
79
|
+
return this.transitionEnterClass;
|
|
80
|
+
},
|
|
65
81
|
},
|
|
66
82
|
|
|
67
83
|
methods: {
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import IconClose from '@veritree/icons/src/components/IconClose.vue';
|
|
3
|
+
import VTAlert from '@/components/Alert/VTAlert.vue';
|
|
4
|
+
|
|
5
|
+
describe('VTAlert.vue', () => {
|
|
6
|
+
let wrapper;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
wrapper = mount(VTAlert, {
|
|
10
|
+
slots: {
|
|
11
|
+
default: '<p>Alert message goes here</p>',
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
wrapper.destroy();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('renders the component', () => {
|
|
21
|
+
expect(VTAlert).toBeTruthy();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('has the correct default props', () => {
|
|
25
|
+
expect(wrapper.props().variant).toBe('success');
|
|
26
|
+
expect(wrapper.props().size).toBe('large');
|
|
27
|
+
expect(wrapper.props().headless).toBe(false);
|
|
28
|
+
expect(wrapper.props().dismissable).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('displays the component with default styles', () => {
|
|
32
|
+
expect(wrapper.classes()).toEqual(
|
|
33
|
+
expect.arrayContaining([
|
|
34
|
+
'flex',
|
|
35
|
+
'items-start',
|
|
36
|
+
'gap-3',
|
|
37
|
+
'rounded',
|
|
38
|
+
'border',
|
|
39
|
+
'border-solid',
|
|
40
|
+
])
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
expect(wrapper.classes()).not.toContain('alert');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('displays the component with success variant styles', async () => {
|
|
47
|
+
await wrapper.setProps({ variant: 'success' });
|
|
48
|
+
|
|
49
|
+
expect(wrapper.classes()).toEqual(
|
|
50
|
+
expect.arrayContaining([
|
|
51
|
+
'border-success-300',
|
|
52
|
+
'bg-success-200',
|
|
53
|
+
'text-success-700',
|
|
54
|
+
])
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
expect(wrapper.classes()).not.toContain('border-error-300');
|
|
58
|
+
expect(wrapper.classes()).not.toContain('bg-error-200');
|
|
59
|
+
expect(wrapper.classes()).not.toContain('text-error-700');
|
|
60
|
+
expect(wrapper.classes()).not.toContain('border-warning-300');
|
|
61
|
+
expect(wrapper.classes()).not.toContain('bg-warning-200');
|
|
62
|
+
expect(wrapper.classes()).not.toContain('text-warning-700');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('displays the component with error variant styles', async () => {
|
|
66
|
+
await wrapper.setProps({ variant: 'error' });
|
|
67
|
+
|
|
68
|
+
expect(wrapper.classes()).toEqual(
|
|
69
|
+
expect.arrayContaining([
|
|
70
|
+
'border-error-300',
|
|
71
|
+
'bg-error-200',
|
|
72
|
+
'text-error-700',
|
|
73
|
+
])
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
expect(wrapper.classes()).not.toContain('border-success-300');
|
|
77
|
+
expect(wrapper.classes()).not.toContain('bg-success-200');
|
|
78
|
+
expect(wrapper.classes()).not.toContain('text-success-700');
|
|
79
|
+
expect(wrapper.classes()).not.toContain('border-warning-300');
|
|
80
|
+
expect(wrapper.classes()).not.toContain('bg-warning-200');
|
|
81
|
+
expect(wrapper.classes()).not.toContain('text-warning-700');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('displays the component with warning variant styles', async () => {
|
|
85
|
+
await wrapper.setProps({ variant: 'warning' });
|
|
86
|
+
|
|
87
|
+
expect(wrapper.classes()).toEqual(
|
|
88
|
+
expect.arrayContaining([
|
|
89
|
+
'border-warning-300',
|
|
90
|
+
'bg-warning-200',
|
|
91
|
+
'text-warning-700',
|
|
92
|
+
])
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
expect(wrapper.classes()).not.toContain('border-success-300');
|
|
96
|
+
expect(wrapper.classes()).not.toContain('bg-success-200');
|
|
97
|
+
expect(wrapper.classes()).not.toContain('text-success-700');
|
|
98
|
+
expect(wrapper.classes()).not.toContain('border-error-300');
|
|
99
|
+
expect(wrapper.classes()).not.toContain('bg-error-200');
|
|
100
|
+
expect(wrapper.classes()).not.toContain('text-error-700');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('displays the default large styles', () => {
|
|
104
|
+
expect(wrapper.classes()).toContain('p-3');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('displays the component with small size styles', async () => {
|
|
108
|
+
await wrapper.setProps({ size: 'small' });
|
|
109
|
+
|
|
110
|
+
expect(wrapper.classes()).toEqual(
|
|
111
|
+
expect.arrayContaining(['py-1', 'px-2', 'text-sm'])
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('dismiss button', () => {
|
|
116
|
+
it('displays dismiss button default classes', async () => {
|
|
117
|
+
await wrapper.setProps({ dismissable: true });
|
|
118
|
+
|
|
119
|
+
expect(wrapper.isVisible()).toBe(true);
|
|
120
|
+
|
|
121
|
+
// Find dismiss button
|
|
122
|
+
const dismissButton = wrapper.find('button');
|
|
123
|
+
|
|
124
|
+
expect(dismissButton.classes()).toEqual(
|
|
125
|
+
expect.arrayContaining([
|
|
126
|
+
'ml-auto',
|
|
127
|
+
'mt-1',
|
|
128
|
+
'h-4',
|
|
129
|
+
'w-4',
|
|
130
|
+
'shrink-0',
|
|
131
|
+
'text-current',
|
|
132
|
+
])
|
|
133
|
+
);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('renders the icon close when dismiss is visible', async () => {
|
|
137
|
+
await wrapper.setProps({ dismissable: true });
|
|
138
|
+
|
|
139
|
+
expect(wrapper.findComponent(IconClose).exists()).toBe(true);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('hides the alert when the dismiss button is clicked', async () => {
|
|
143
|
+
await wrapper.setProps({ dismissable: true });
|
|
144
|
+
|
|
145
|
+
expect(wrapper.isVisible()).toBe(true);
|
|
146
|
+
|
|
147
|
+
// Click the dismiss button
|
|
148
|
+
const dismissButton = wrapper.find('button');
|
|
149
|
+
await dismissButton.trigger('click');
|
|
150
|
+
|
|
151
|
+
// Verify that the alert is now hidden
|
|
152
|
+
expect(wrapper.isVisible()).toBe(false);
|
|
153
|
+
|
|
154
|
+
// Verify that the 'dismiss' event was emitted
|
|
155
|
+
expect(wrapper.emitted('dismiss')).toBeTruthy();
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import VTButton from '@/components/Button/VTButton.vue';
|
|
3
|
+
|
|
4
|
+
describe('VTButton.vue', () => {
|
|
5
|
+
let wrapper;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
wrapper = mount(VTButton, {
|
|
9
|
+
slots: {
|
|
10
|
+
default: 'Submit',
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
wrapper.destroy();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('renders the button if "to" and "href" props are not provided', () => {
|
|
20
|
+
expect(wrapper.find('button').exists()).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('renders a NuxtLink when the "to" prop is provided', async () => {
|
|
24
|
+
await wrapper.setProps({ to: '/some-page' });
|
|
25
|
+
|
|
26
|
+
expect(wrapper.find('NuxtLink').exists()).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('renders an "a" tag when the "href" prop is provided', async () => {
|
|
30
|
+
await wrapper.setProps({ href: 'https://example.com' });
|
|
31
|
+
|
|
32
|
+
expect(wrapper.find('a').exists()).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('has the correct default props', () => {
|
|
36
|
+
expect(wrapper.props().variant).toBe('primary');
|
|
37
|
+
expect(wrapper.props().size).toBe('large');
|
|
38
|
+
expect(wrapper.props().to).toBe(null);
|
|
39
|
+
expect(wrapper.props().href).toBe(null);
|
|
40
|
+
expect(wrapper.props().headless).toBe(false);
|
|
41
|
+
expect(wrapper.props().busy).toBe(false);
|
|
42
|
+
expect(wrapper.props().disabled).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('displays the component default styles', () => {
|
|
46
|
+
expect(wrapper.classes()).toEqual(
|
|
47
|
+
expect.arrayContaining([
|
|
48
|
+
'relative',
|
|
49
|
+
'inline-flex',
|
|
50
|
+
'rounded',
|
|
51
|
+
'border',
|
|
52
|
+
'border-solid',
|
|
53
|
+
'px-4',
|
|
54
|
+
'text-sm',
|
|
55
|
+
'font-semibold',
|
|
56
|
+
'leading-none',
|
|
57
|
+
'no-underline',
|
|
58
|
+
'transition-all',
|
|
59
|
+
])
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
expect(wrapper.classes()).not.toContain('button');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('displays the component with primary variant styles', async () => {
|
|
66
|
+
await wrapper.setProps({ variant: 'primary' });
|
|
67
|
+
|
|
68
|
+
expect(wrapper.classes()).toEqual(
|
|
69
|
+
expect.arrayContaining([
|
|
70
|
+
'bg-secondary-400',
|
|
71
|
+
'hover:bg-secondary-500',
|
|
72
|
+
'focus:bg-secondary-600',
|
|
73
|
+
'active:bg-secondary-600',
|
|
74
|
+
'border-transparent',
|
|
75
|
+
'text-white',
|
|
76
|
+
'disabled:bg-gray-200',
|
|
77
|
+
'disabled:text-gray-400'
|
|
78
|
+
])
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
expect(wrapper.classes()).not.toContain('button');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('displays the component with secondary variant styles', async () => {
|
|
85
|
+
await wrapper.setProps({ variant: 'secondary' });
|
|
86
|
+
|
|
87
|
+
expect(wrapper.classes()).toEqual(
|
|
88
|
+
expect.arrayContaining([
|
|
89
|
+
'border-gray-400',
|
|
90
|
+
'bg-white',
|
|
91
|
+
'text-gray-700',
|
|
92
|
+
'hover:bg-gray-100',
|
|
93
|
+
'hover:bg-gray-200',
|
|
94
|
+
'active:bg-gray-200',
|
|
95
|
+
'disabled:border-gray-300',
|
|
96
|
+
'disabled:text-gray-400'
|
|
97
|
+
])
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
expect(wrapper.classes()).not.toContain('button');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('displays the component with tertiary variant styles', async () => {
|
|
104
|
+
await wrapper.setProps({ variant: 'tertiary' });
|
|
105
|
+
|
|
106
|
+
expect(wrapper.classes()).toEqual(
|
|
107
|
+
expect.arrayContaining([
|
|
108
|
+
'text-secondary-400',
|
|
109
|
+
'hover:text-secondary-500',
|
|
110
|
+
'focus:text-secondary-600',
|
|
111
|
+
'active:text-secondary-600',
|
|
112
|
+
'border-transparent',
|
|
113
|
+
'disabled:text-gray-400'
|
|
114
|
+
])
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
expect(wrapper.classes()).not.toContain('button');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('displays the component with icon variant styles', async () => {
|
|
121
|
+
await wrapper.setProps({ variant: 'icon' });
|
|
122
|
+
|
|
123
|
+
expect(wrapper.classes()).toEqual(
|
|
124
|
+
expect.arrayContaining([
|
|
125
|
+
'text-primary-100',
|
|
126
|
+
'focus-within:bg-gray-200',
|
|
127
|
+
'hover:bg-gray-200',
|
|
128
|
+
'active:bg-gray-300'
|
|
129
|
+
])
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
expect(wrapper.classes()).not.toContain('button');
|
|
133
|
+
});
|
|
134
|
+
});
|
package/vitest.config.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import Vue2 from '@vitejs/plugin-vue2';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [Vue2()],
|
|
7
|
+
test: {
|
|
8
|
+
globals: true,
|
|
9
|
+
environment: 'jsdom',
|
|
10
|
+
alias: [
|
|
11
|
+
{
|
|
12
|
+
find: /^vue$/,
|
|
13
|
+
replacement: 'vue/dist/vue.runtime.common.js',
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
},
|
|
17
|
+
resolve: {
|
|
18
|
+
alias: {
|
|
19
|
+
'@': path.resolve(__dirname, './src'),
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
});
|