create-nuxt-base 0.1.20 → 0.1.21
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/CHANGELOG.md +2 -0
- package/index.js +1 -1
- package/nuxt-base-template/formkit-theme.js +137 -0
- package/nuxt-base-template/formkit.config.js +35 -0
- package/nuxt-base-template/nuxt.config.ts +34 -3
- package/nuxt-base-template/package-lock.json +11248 -14131
- package/nuxt-base-template/package.json +37 -36
- package/nuxt-base-template/src/app.vue +8 -0
- package/nuxt-base-template/src/assets/css/tailwind.css +37 -2
- package/nuxt-base-template/src/components/ModalShare.vue +67 -0
- package/nuxt-base-template/src/components/SocialMediaBubble.vue +16 -0
- package/nuxt-base-template/src/components/base/BaseAccordion.vue +52 -0
- package/nuxt-base-template/src/components/base/BaseButton.vue +106 -0
- package/nuxt-base-template/src/components/base/BaseContainer.vue +5 -0
- package/nuxt-base-template/src/components/base/BaseInfinityList.vue +34 -0
- package/nuxt-base-template/src/components/base/BaseModalContainer.vue +7 -0
- package/nuxt-base-template/src/components/base/BaseNotification.vue +81 -0
- package/nuxt-base-template/src/components/base/BaseNotificationContainer.vue +34 -0
- package/nuxt-base-template/src/components/base/BaseProgressbar.vue +66 -0
- package/nuxt-base-template/src/components/base/BaseToggle.vue +20 -0
- package/nuxt-base-template/src/components/transition/TransitionFade.vue +24 -0
- package/nuxt-base-template/src/components/transition/TransitionFadeScale.vue +24 -0
- package/nuxt-base-template/src/components/transition/TransitionSlide.vue +14 -0
- package/nuxt-base-template/src/components/transition/TransitionSlideBottom.vue +14 -0
- package/nuxt-base-template/src/components/transition/TransitionSlideRevert.vue +14 -0
- package/nuxt-base-template/src/composables/use-auth-fetch.ts +19 -0
- package/nuxt-base-template/src/composables/use-file.ts +21 -0
- package/nuxt-base-template/src/composables/use-form-helper.ts +100 -0
- package/nuxt-base-template/src/composables/use-helper.ts +52 -0
- package/nuxt-base-template/src/composables/use-modal.ts +84 -0
- package/nuxt-base-template/src/composables/use-notification.ts +29 -0
- package/nuxt-base-template/src/composables/use-share.ts +22 -0
- package/nuxt-base-template/src/error.vue +53 -0
- package/nuxt-base-template/src/forms/inputs/InputCheckbox.vue +29 -0
- package/nuxt-base-template/src/forms/inputs/InputFreeTags.vue +98 -0
- package/nuxt-base-template/src/forms/inputs/InputImage.vue +65 -0
- package/nuxt-base-template/src/forms/inputs/InputTags.vue +112 -0
- package/nuxt-base-template/src/forms/inputs/InputToggle.vue +18 -0
- package/nuxt-base-template/src/forms/plugins/asterisk-plugin.ts +29 -0
- package/nuxt-base-template/src/forms/plugins/scroll-error-plugin.ts +36 -0
- package/nuxt-base-template/src/forms/plugins/value-changes-plugin.ts +13 -0
- package/nuxt-base-template/src/middleware/admin.global.ts +9 -0
- package/nuxt-base-template/src/middleware/auth.global.ts +5 -7
- package/nuxt-base-template/src/plugins/4.auth.server.ts +70 -0
- package/nuxt-base-template/src/tests/init.test.ts +12 -0
- package/nuxt-base-template/tailwind.config.js +42 -3
- package/nuxt-base-template/tsconfig.json +4 -1
- package/package.json +1 -1
- package/nuxt-base-template/cypress.config.ts +0 -54
- package/nuxt-base-template/plugins/index.js +0 -5
- package/nuxt-base-template/src/components/.gitkeep +0 -0
- package/nuxt-base-template/src/components/base/.gitkeep +0 -0
- package/nuxt-base-template/src/composables/.gitkeep +0 -0
- package/nuxt-base-template/src/forms/.gitkeep +0 -0
- package/nuxt-base-template/src/pages/.gitkeep +0 -0
- package/nuxt-base-template/src/tests/.gitkeep +0 -0
- package/nuxt-base-template/src/tests/hello-world.spec.ts +0 -11
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
interface TagOption {
|
|
3
|
+
label: string;
|
|
4
|
+
value: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const props = defineProps({
|
|
8
|
+
context: Object,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const inputRef = ref();
|
|
12
|
+
const inputValue = ref<string>();
|
|
13
|
+
const inputFocus = ref();
|
|
14
|
+
const name = props.context?.name;
|
|
15
|
+
const placeholder = props.context?.attrs?.placeholder;
|
|
16
|
+
const tags = ref<TagOption[]>([]);
|
|
17
|
+
const defaultOptions: TagOption[] = [...props?.context?.attrs?.options] || [];
|
|
18
|
+
const selectOptions = ref<TagOption[]>([...props?.context?.attrs?.options]);
|
|
19
|
+
patch();
|
|
20
|
+
|
|
21
|
+
function patch() {
|
|
22
|
+
const values = props.context?._value;
|
|
23
|
+
if (!values) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (Array.isArray(values)) {
|
|
28
|
+
for (let item of values) {
|
|
29
|
+
handleSelect(item);
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
handleSelect(values);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function handleSelect(value: string) {
|
|
37
|
+
const tag = selectOptions.value.find((e) => e.value === value);
|
|
38
|
+
const included = tags.value?.find((e) => e.value === tag?.value) ?? false;
|
|
39
|
+
|
|
40
|
+
if (!tag) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!included) {
|
|
45
|
+
tags.value.push(tag);
|
|
46
|
+
selectOptions.value = defaultOptions.filter((e) => e.value !== tag.value);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
props.context?.node.input(tags.value.map((e) => e.value));
|
|
50
|
+
inputValue.value = '';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function handleInput(event: any) {
|
|
54
|
+
const value = event.target.value.toLowerCase();
|
|
55
|
+
|
|
56
|
+
if (!value) {
|
|
57
|
+
selectOptions.value = defaultOptions.filter((e: TagOption) => !props.context?._value?.includes(e.value));
|
|
58
|
+
} else {
|
|
59
|
+
selectOptions.value = selectOptions.value.filter((e: TagOption) => e.label.toLowerCase().includes(value));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function removeTag(tag: TagOption) {
|
|
64
|
+
tags.value.splice(tags.value.findIndex((e) => e.value === tag.value), 1);
|
|
65
|
+
props.context?.node.input(tags.value.map((e) => e.value));
|
|
66
|
+
selectOptions.value = defaultOptions.filter((e: TagOption) => !props.context?._value?.includes(e.value));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function setFocus() {
|
|
70
|
+
inputFocus.value = true;
|
|
71
|
+
inputValue.value = '';
|
|
72
|
+
selectOptions.value = defaultOptions.filter((e: TagOption) => !props.context?._value?.includes(e.value));
|
|
73
|
+
}
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<template>
|
|
77
|
+
<div class="flex flex-col">
|
|
78
|
+
<div class="flex flex-row flex-wrap gap-2">
|
|
79
|
+
<span v-for="tag of tags" :key="tag.value" :class="context?.classes.tag">{{ tag.label }} <span class="i-bi-x" :class="context?.classes.tagIcon" @click="removeTag(tag)"></span> </span>
|
|
80
|
+
</div>
|
|
81
|
+
<div v-if="selectOptions.length" class="relative" :class="context?.classes.inputWrapper">
|
|
82
|
+
<div class="relative w-full flex items-center">
|
|
83
|
+
<input
|
|
84
|
+
:id="props.context?.id"
|
|
85
|
+
ref="inputRef"
|
|
86
|
+
v-model="inputValue"
|
|
87
|
+
autocomplete="off"
|
|
88
|
+
:name="name" type="text" :placeholder="placeholder" :class="context?.classes.input" @focus="setFocus"
|
|
89
|
+
@blur="inputFocus = false" @input="handleInput"
|
|
90
|
+
/>
|
|
91
|
+
<span :class="context?.classes.selectIcon" class="formkit-select-icon flex p-[3px] shrink-0 w-5 mr-2 -ml-[1.5em] h-full pointer-events-none formkit-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 7"><path d="M8,6.5c-.13,0-.26-.05-.35-.15L3.15,1.85c-.2-.2-.2-.51,0-.71,.2-.2,.51-.2,.71,0l4.15,4.15L12.15,1.15c.2-.2,.51-.2,.71,0,.2,.2,.2,.51,0,.71l-4.5,4.5c-.1,.1-.23,.15-.35,.15Z" fill="currentColor" /></svg></span>
|
|
92
|
+
</div>
|
|
93
|
+
<TransitionFade :start-duration="200" :leave-duration="200">
|
|
94
|
+
<div
|
|
95
|
+
v-show="inputFocus && defaultOptions.length"
|
|
96
|
+
class="absolute right-0 left-0 z-50 h-fit max-h-12 flex flex-col justify-start items-start"
|
|
97
|
+
:style="`top: ${inputRef?.clientHeight + 1}px`"
|
|
98
|
+
:class="context?.classes.dropdown"
|
|
99
|
+
>
|
|
100
|
+
<div v-if="selectOptions.length" class="w-full">
|
|
101
|
+
<button v-for="option of selectOptions" :key="option.value" :class="context?.classes.dropdownItem" @click="handleSelect(option.value)">
|
|
102
|
+
{{ option.label }}
|
|
103
|
+
</button>
|
|
104
|
+
</div>
|
|
105
|
+
<div v-else :class="context?.classes.noItemsFound">
|
|
106
|
+
Keine Einträge gefunden
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</TransitionFade>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
</template>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const props = defineProps({
|
|
3
|
+
context: Object,
|
|
4
|
+
});
|
|
5
|
+
const inputValue = ref(props?.context?._value ?? false);
|
|
6
|
+
|
|
7
|
+
watch(() => inputValue.value, () => {
|
|
8
|
+
props.context?.node.input(inputValue.value);
|
|
9
|
+
});
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<div class="flex justify-between items-center" @click="inputValue = !inputValue">
|
|
14
|
+
<div class="w-8 h-5 flex items-center bg-gray-300 rounded-full p-1 duration-300 ease-in-out" :class="{ 'bg-green-400': inputValue }">
|
|
15
|
+
<div class="bg-white w-4 h-4 rounded-full shadow-md transform duration-300 ease-in-out" :class="{ 'translate-x-2': inputValue }"></div>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const isCheckboxAndRadioMultiple = (node: any) => (node.props.type === 'checkbox' || node.props.type === 'radio') && node.props.options;
|
|
2
|
+
|
|
3
|
+
export function addAsteriskPlugin(node: any) {
|
|
4
|
+
node.on('created', () => {
|
|
5
|
+
const isRequired = node.props.parsedRules.some((rule: any) => rule.name === 'required');
|
|
6
|
+
if (!isRequired) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const isMultiOption = isCheckboxAndRadioMultiple(node);
|
|
11
|
+
|
|
12
|
+
// if we're going to modify the schema then we need
|
|
13
|
+
// to update the schemaMemoKey so we don't get an
|
|
14
|
+
// invalid cached schema.
|
|
15
|
+
node.props.definition.schemaMemoKey = `required_${isMultiOption ? 'multi_' : ''}${node.props.definition.schemaMemoKey}`;
|
|
16
|
+
|
|
17
|
+
const schemaFn = node.props.definition.schema;
|
|
18
|
+
node.props.definition.schema = (sectionsSchema: any = {}) => {
|
|
19
|
+
if (isRequired) {
|
|
20
|
+
if (!isMultiOption) {
|
|
21
|
+
sectionsSchema.label = {
|
|
22
|
+
children: ['$label', ' *'],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return schemaFn(sectionsSchema);
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { FormKitNode } from '@formkit/core';
|
|
2
|
+
|
|
3
|
+
export function scrollToErrors(node: any) {
|
|
4
|
+
if (node.props.type === 'form') {
|
|
5
|
+
function scrollTo(node: FormKitNode) {
|
|
6
|
+
const el = document.getElementById(node.props.id);
|
|
7
|
+
if (el) {
|
|
8
|
+
el.scrollIntoView({ block: 'center', behavior: 'smooth' });
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function scrollToErrors() {
|
|
13
|
+
node.walk((child: any) => {
|
|
14
|
+
// Check if this child has errors
|
|
15
|
+
if (child.ledger.value('blocking') || child.ledger.value('errors')) {
|
|
16
|
+
// We found an input with validation errors
|
|
17
|
+
scrollTo(child);
|
|
18
|
+
// Stop searching
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}, true);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function defaultInvalid(node: FormKitNode) {
|
|
25
|
+
console.error('FormKit::invalidForm', node);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const onSubmitInvalid = node.props.onSubmitInvalid ?? defaultInvalid;
|
|
29
|
+
node.props.onSubmitInvalid = () => {
|
|
30
|
+
onSubmitInvalid(node);
|
|
31
|
+
scrollToErrors();
|
|
32
|
+
};
|
|
33
|
+
node.on('unsettled:errors', scrollToErrors);
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FormKitEvent, FormKitNode } from '@formkit/core';
|
|
2
|
+
|
|
3
|
+
export function valueChangesPlugin(node: FormKitNode) {
|
|
4
|
+
const { getDifferences } = useFormHelper();
|
|
5
|
+
if (node.props.type === 'form') {
|
|
6
|
+
setTimeout(() => {
|
|
7
|
+
node.on('commit', (event: FormKitEvent) => {
|
|
8
|
+
const diff = getDifferences(event.origin.props._init, event.payload);
|
|
9
|
+
node.emit('valueChanges', { init: event.origin.props._init, current: event.payload, diff: diff });
|
|
10
|
+
});
|
|
11
|
+
}, 300);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
export default defineNuxtRouteMiddleware((to, from) => {
|
|
2
|
-
const
|
|
2
|
+
const { accessToken } = useAuthState();
|
|
3
3
|
|
|
4
|
-
if (to.fullPath.startsWith('/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (!store.token || !store.currentUser) {
|
|
9
|
-
return navigateTo('/auth/login');
|
|
4
|
+
if (to.fullPath.startsWith('/app')) {
|
|
5
|
+
if (!accessToken?.value) {
|
|
6
|
+
return navigateTo('/auth/login');
|
|
7
|
+
}
|
|
10
8
|
}
|
|
11
9
|
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { callWithNuxt, defineNuxtPlugin, useNuxtApp, useRuntimeConfig } from 'nuxt/app';
|
|
2
|
+
import { ofetch } from 'ofetch';
|
|
3
|
+
|
|
4
|
+
export default defineNuxtPlugin({
|
|
5
|
+
name: 'auth-server',
|
|
6
|
+
enforce: 'pre',
|
|
7
|
+
async setup() {
|
|
8
|
+
console.debug('4.auth.server.ts::init');
|
|
9
|
+
const _nuxt = useNuxtApp();
|
|
10
|
+
const config = await callWithNuxt(_nuxt, useRuntimeConfig);
|
|
11
|
+
const { refreshToken, accessToken } = await callWithNuxt(_nuxt, useAuthState);
|
|
12
|
+
const { setCurrentUser, getDecodedAccessToken, setTokens } = await callWithNuxt(_nuxt, useAuth);
|
|
13
|
+
const payload = accessToken.value ? getDecodedAccessToken(accessToken.value) : null;
|
|
14
|
+
|
|
15
|
+
if (!refreshToken.value) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const refreshTokenResult = await ofetch(config.public.host, {
|
|
20
|
+
method: 'POST',
|
|
21
|
+
headers: {
|
|
22
|
+
Authorization: `Bearer ${refreshToken.value}`,
|
|
23
|
+
},
|
|
24
|
+
body: JSON.stringify({
|
|
25
|
+
query: 'mutation refreshToken {refreshToken {token, refreshToken}}',
|
|
26
|
+
variables: {},
|
|
27
|
+
}),
|
|
28
|
+
}).catch((err) => {
|
|
29
|
+
console.error('4.auth.server.ts::refreshToken::catch', err.data);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
console.debug('4.auth.server.ts::refreshTokenResult', refreshTokenResult);
|
|
33
|
+
|
|
34
|
+
if (refreshTokenResult?.data) {
|
|
35
|
+
const data = refreshTokenResult.data.refreshToken;
|
|
36
|
+
console.debug('4.auth.server.ts::token', data?.token);
|
|
37
|
+
console.debug('4.auth.server.ts::refreshToken', data?.refreshToken);
|
|
38
|
+
setTokens(data.token, data.refreshToken);
|
|
39
|
+
|
|
40
|
+
if (payload?.id) {
|
|
41
|
+
const userResult = await ofetch(config.public.host, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: {
|
|
44
|
+
Authorization: `Bearer ${refreshTokenResult.data.refreshToken?.token}`,
|
|
45
|
+
},
|
|
46
|
+
body: JSON.stringify({
|
|
47
|
+
query: 'query getUser($id: String!){' +
|
|
48
|
+
'getUser(id: $id){' +
|
|
49
|
+
'id ' +
|
|
50
|
+
'avatar ' +
|
|
51
|
+
'firstName ' +
|
|
52
|
+
'lastName ' +
|
|
53
|
+
'email ' +
|
|
54
|
+
'roles ' +
|
|
55
|
+
'}}',
|
|
56
|
+
variables: {
|
|
57
|
+
id: payload.id,
|
|
58
|
+
},
|
|
59
|
+
}),
|
|
60
|
+
}).catch((err) => {
|
|
61
|
+
console.error('4.auth.server.ts::getUser::catch', err.data);
|
|
62
|
+
});
|
|
63
|
+
console.debug('4.auth.server.ts::getUser::userResult', userResult);
|
|
64
|
+
if (userResult?.data) {
|
|
65
|
+
setCurrentUser(userResult?.data?.getUser);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
});
|
|
@@ -1,9 +1,48 @@
|
|
|
1
1
|
/** @type {import('tailwindcss').Config} */
|
|
2
|
+
const defaultTheme = require('tailwindcss/defaultTheme');
|
|
3
|
+
const { iconsPlugin, getIconCollections } = require('@egoist/tailwindcss-icons');
|
|
4
|
+
const typography = require('@tailwindcss/typography');
|
|
5
|
+
const forms = require('@tailwindcss/forms');
|
|
6
|
+
const formkit = require('@formkit/themes/tailwindcss');
|
|
7
|
+
|
|
2
8
|
module.exports = {
|
|
3
9
|
darkMode: "class",
|
|
4
|
-
content: [],
|
|
10
|
+
content: ['./formkit-theme.js'],
|
|
5
11
|
theme: {
|
|
6
|
-
|
|
12
|
+
// fontFamily: {
|
|
13
|
+
// montserrat: ['Montserrat'],
|
|
14
|
+
// sans: ['Work Sans', 'Montserrat', ...defaultTheme.fontFamily.sans],
|
|
15
|
+
// serif: ['Work Sans', 'Montserrat', ...defaultTheme.fontFamily.serif],
|
|
16
|
+
// },
|
|
17
|
+
extend: {
|
|
18
|
+
// colors: {
|
|
19
|
+
// primary: {
|
|
20
|
+
// DEFAULT: '#57B39A',
|
|
21
|
+
// 50: '#f3faf7',
|
|
22
|
+
// 100: '#d6f1e7',
|
|
23
|
+
// 200: '#ade2d0',
|
|
24
|
+
// 300: '#7cccb3',
|
|
25
|
+
// 400: '#57b39a',
|
|
26
|
+
// 500: '#37957d',
|
|
27
|
+
// 600: '#2a7765',
|
|
28
|
+
// 700: '#256052',
|
|
29
|
+
// 800: '#224d45',
|
|
30
|
+
// 900: '#20413a',
|
|
31
|
+
// 950: '#0d2621',
|
|
32
|
+
// },
|
|
33
|
+
// }
|
|
34
|
+
screens: {
|
|
35
|
+
'3xl': '2400px'
|
|
36
|
+
}
|
|
37
|
+
}
|
|
7
38
|
},
|
|
8
|
-
plugins: [
|
|
39
|
+
plugins: [
|
|
40
|
+
typography,
|
|
41
|
+
formkit,
|
|
42
|
+
forms,
|
|
43
|
+
iconsPlugin({
|
|
44
|
+
// Select the icon collections you want to use
|
|
45
|
+
collections: getIconCollections(['bi']),
|
|
46
|
+
}),
|
|
47
|
+
],
|
|
9
48
|
};
|
package/package.json
CHANGED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { addCucumberPreprocessorPlugin } from '@badeball/cypress-cucumber-preprocessor';
|
|
2
|
-
import * as webpack from '@cypress/webpack-preprocessor';
|
|
3
|
-
import { defineConfig } from 'cypress';
|
|
4
|
-
|
|
5
|
-
async function setupNodeEvents(
|
|
6
|
-
on: Cypress.PluginEvents,
|
|
7
|
-
config: Cypress.PluginConfigOptions,
|
|
8
|
-
): Promise<Cypress.PluginConfigOptions> {
|
|
9
|
-
await addCucumberPreprocessorPlugin(on, config);
|
|
10
|
-
|
|
11
|
-
on(
|
|
12
|
-
'file:preprocessor',
|
|
13
|
-
webpack({
|
|
14
|
-
webpackOptions: {
|
|
15
|
-
resolve: {
|
|
16
|
-
extensions: ['.ts', '.js'],
|
|
17
|
-
},
|
|
18
|
-
module: {
|
|
19
|
-
rules: [
|
|
20
|
-
{
|
|
21
|
-
test: /\.ts$/,
|
|
22
|
-
exclude: [/node_modules/],
|
|
23
|
-
use: [
|
|
24
|
-
{
|
|
25
|
-
loader: 'ts-loader',
|
|
26
|
-
},
|
|
27
|
-
],
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
test: /\.feature$/,
|
|
31
|
-
use: [
|
|
32
|
-
{
|
|
33
|
-
loader: '@badeball/cypress-cucumber-preprocessor/webpack',
|
|
34
|
-
options: config,
|
|
35
|
-
},
|
|
36
|
-
],
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
}),
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
// Make sure to return the config object as it might have been modified by the plugin.
|
|
45
|
-
return config;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export default defineConfig({
|
|
49
|
-
e2e: {
|
|
50
|
-
setupNodeEvents,
|
|
51
|
-
supportFile: false,
|
|
52
|
-
specPattern: ['cypress/e2e/**/*.cy.{js,ts}', 'cypress/integrations/**/*.feature'],
|
|
53
|
-
},
|
|
54
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { mount } from '@vue/test-utils';
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
|
|
4
|
-
import HelloWorld from '../components/hello-world.vue';
|
|
5
|
-
|
|
6
|
-
describe('HelloWorld', () => {
|
|
7
|
-
it('is a Vue instance', () => {
|
|
8
|
-
const wrapper = mount(HelloWorld);
|
|
9
|
-
expect(wrapper.vm).toBeTruthy();
|
|
10
|
-
});
|
|
11
|
-
});
|