test(vue): add test application (#22252)

This commit is contained in:
Liam DeBeasi
2020-10-05 15:01:46 -04:00
committed by GitHub
parent f11adabbc8
commit f5d657c6cd
39 changed files with 18859 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
> 1%
last 2 versions
not dead

View File

@@ -0,0 +1,31 @@
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/typescript/recommended'
],
parserOptions: {
ecmaVersion: 2020
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'vue/no-deprecated-slot-attribute': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
overrides: [
{
files: [
'**/__tests__/*.{j,t}s?(x)',
'**/tests/unit/**/*.spec.{j,t}s?(x)'
],
env: {
jest: true
}
}
]
}

31
packages/vue/test-app/.gitignore vendored Normal file
View File

@@ -0,0 +1,31 @@
# Specifies intentionally untracked files to ignore when using Git
# http://git-scm.com/docs/gitignore
*~
*.sw[mnpcod]
.tmp
*.tmp
*.tmp.*
*.sublime-project
*.sublime-workspace
.DS_Store
Thumbs.db
UserInterfaceState.xcuserstate
$RECYCLE.BIN/
*.log
log.txt
npm-debug.log*
/.idea
/.ionic
/.sass-cache
/.sourcemaps
/.versions
/.vscode
/coverage
/dist
/node_modules
/platforms
/plugins
/www

View File

@@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

View File

@@ -0,0 +1,5 @@
{
"pluginsFile": "tests/e2e/plugins/index.js",
"includeShadowDom": true,
"video": false
}

View File

@@ -0,0 +1,5 @@
{
"name": "test-app",
"integrations": {},
"type": "vue"
}

View File

@@ -0,0 +1,6 @@
module.exports = {
preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel',
transform: {
'^.+\\.vue$': 'vue-jest'
}
}

17007
packages/vue/test-app/package-lock.json generated Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,42 @@
{
"name": "test-app",
"version": "0.0.1",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "start-server-and-test serve http://localhost:8080 cypress",
"lint": "vue-cli-service lint",
"cypress": "node_modules/.bin/cypress run --headless --browser chrome"
},
"dependencies": {
"@ionic/vue": "^0.6.0-dev.202009301514.ea201ea",
"@ionic/vue-router": "^0.6.0-dev.202009301514.ea201ea",
"core-js": "^3.6.5",
"vue": "^3.0.0-0",
"vue-router": "^4.0.0-0"
},
"devDependencies": {
"@types/jest": "^24.0.19",
"@typescript-eslint/eslint-plugin": "^2.33.0",
"@typescript-eslint/parser": "^2.33.0",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-e2e-cypress": "^4.5.4",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-typescript": "~4.5.0",
"@vue/cli-plugin-unit-jest": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0-0",
"@vue/eslint-config-typescript": "^5.0.2",
"@vue/test-utils": "^2.0.0-0",
"cypress": "^5.3.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^7.0.0-0",
"typescript": "~3.9.3",
"vue-jest": "^5.0.0-0",
"wait-on": "^5.2.0"
},
"description": "An Ionic project"
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1 @@
<svg width="350" height="140" xmlns="http://www.w3.org/2000/svg" style="background:#f6f7f9"><g fill="none" fill-rule="evenodd"><path fill="#F04141" style="mix-blend-mode:multiply" d="M61.905-34.23l96.194 54.51-66.982 54.512L22 34.887z"/><circle fill="#10DC60" style="mix-blend-mode:multiply" cx="155.5" cy="135.5" r="57.5"/><path fill="#3880FF" style="mix-blend-mode:multiply" d="M208.538 9.513l84.417 15.392L223.93 93.93z"/><path fill="#FFCE00" style="mix-blend-mode:multiply" d="M268.625 106.557l46.332-26.75 46.332 26.75v53.5l-46.332 26.75-46.332-26.75z"/><circle fill="#7044FF" style="mix-blend-mode:multiply" cx="299.5" cy="9.5" r="38.5"/><rect fill="#11D3EA" style="mix-blend-mode:multiply" transform="rotate(-60 148.47 37.886)" x="143.372" y="-7.056" width="10.196" height="89.884" rx="5.098"/><path d="M-25.389 74.253l84.86 8.107c5.498.525 9.53 5.407 9.004 10.905a10 10 0 0 1-.057.477l-12.36 85.671a10.002 10.002 0 0 1-11.634 8.42l-86.351-15.226c-5.44-.959-9.07-6.145-8.112-11.584l13.851-78.551a10 10 0 0 1 10.799-8.219z" fill="#7044FF" style="mix-blend-mode:multiply"/><circle fill="#0CD1E8" style="mix-blend-mode:multiply" cx="273.5" cy="106.5" r="20.5"/></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Ionic App</title>
<base href="/" />
<meta name="color-scheme" content="light dark" />
<meta
name="viewport"
content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<link rel="shortcut icon" type="image/png" href="<%= BASE_URL %>assets/icon/favicon.png" />
<!-- add to homescreen for ios -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Ionic App" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
</head>
<body>
<div id="app"></div>
</body>
</html>

View File

@@ -0,0 +1,18 @@
<template>
<ion-app>
<ion-router-outlet />
</ion-app>
</template>
<script lang="ts">
import { IonApp, IonRouterOutlet } from '@ionic/vue';
import { defineComponent } from 'vue';
export default defineComponent({
name: 'App',
components: {
IonApp,
IonRouterOutlet
}
});
</script>

View File

@@ -0,0 +1,50 @@
<template>
<ion-header>
<ion-toolbar>
<ion-buttons>
<ion-button @click="dismiss">Dismiss</ion-button>
</ion-buttons>
<ion-title>Modal</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
{{ title }}
</ion-content>
</template>
<script lang="ts">
import {
IonButton,
IonButtons,
IonContent,
IonHeader,
IonTitle,
IonToolbar,
modalController
} from '@ionic/vue';
import { defineComponent } from 'vue';
export default defineComponent({
name: 'ModalContent',
props: {
title: { type: String, default: 'Default Title' }
},
components: {
IonButton,
IonButtons,
IonContent,
IonHeader,
IonTitle,
IonToolbar
},
setup() {
const dismiss = async () => {
await modalController.dismiss();
}
return {
dismiss
}
}
})
</script>

View File

@@ -0,0 +1,32 @@
<template>
<ion-content class="ion-padding">
{{ title }}
</ion-content>
</template>
<script lang="ts">
import {
IonContent,
popoverController
} from '@ionic/vue';
import { defineComponent } from 'vue';
export default defineComponent({
name: 'PopoverContent',
props: {
title: { type: String, default: 'Default Title' }
},
components: {
IonContent
},
setup() {
const dismiss = async () => {
await popoverController.dismiss();
}
return {
dismiss
}
}
})
</script>

View File

@@ -0,0 +1,32 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router';
import { IonicVue } from '@ionic/vue';
/* Core CSS required for Ionic components to work properly */
import '@ionic/vue/css/core.css';
/* Basic CSS for apps built with Ionic */
import '@ionic/vue/css/normalize.css';
import '@ionic/vue/css/structure.css';
import '@ionic/vue/css/typography.css';
/* Optional CSS utils that can be commented out */
import '@ionic/vue/css/padding.css';
import '@ionic/vue/css/float-elements.css';
import '@ionic/vue/css/text-alignment.css';
import '@ionic/vue/css/text-transformation.css';
import '@ionic/vue/css/flex-utils.css';
import '@ionic/vue/css/display.css';
/* Theme variables */
import './theme/variables.css';
const app = createApp(App)
.use(IonicVue)
.use(router);
router.isReady().then(() => {
app.mount('#app');
});

View File

@@ -0,0 +1,57 @@
import { createRouter, createWebHistory } from '@ionic/vue-router';
import { RouteRecordRaw } from 'vue-router';
import Home from '../views/Home.vue'
const routes: Array<RouteRecordRaw> = [
{
path: '/',
redirect: '/home'
},
{
path: '/home',
name: 'Home',
component: Home
},
{
path: '/overlays',
name: 'Overlays',
component: () => import('@/views/Overlays.vue')
},
{
path: '/inputs',
name: 'Inputs',
component: () => import('@/views/Inputs.vue')
},
{
path: '/slides',
name: 'Slides',
component: () => import('@/views/Slides.vue')
},
{
path: '/navigation',
name: 'Navigation',
component: () => import('@/views/Navigation.vue')
},
{
path: '/nested',
name: 'RouterOutlet',
component: () => import('@/views/RouterOutlet.vue'),
children: [
{
path: '',
component: () => import('@/views/NestedChild.vue')
},
{
path: 'two',
component: () => import('@/views/NestedChildTwo.vue')
}
]
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router

View File

@@ -0,0 +1,5 @@
declare module '*.vue' {
import { defineComponent } from 'vue'
const component: ReturnType<typeof defineComponent>
export default component
}

View File

@@ -0,0 +1,232 @@
/* Ionic Variables and Theming. For more info, please see:
http://ionicframework.com/docs/theming/ */
/** Ionic CSS Variables **/
:root {
/** primary **/
--ion-color-primary: #3880ff;
--ion-color-primary-rgb: 56, 128, 255;
--ion-color-primary-contrast: #ffffff;
--ion-color-primary-contrast-rgb: 255, 255, 255;
--ion-color-primary-shade: #3171e0;
--ion-color-primary-tint: #4c8dff;
/** secondary **/
--ion-color-secondary: #3dc2ff;
--ion-color-secondary-rgb: 61, 194, 255;
--ion-color-secondary-contrast: #ffffff;
--ion-color-secondary-contrast-rgb: 255, 255, 255;
--ion-color-secondary-shade: #36abe0;
--ion-color-secondary-tint: #50c8ff;
/** tertiary **/
--ion-color-tertiary: #5260ff;
--ion-color-tertiary-rgb: 82, 96, 255;
--ion-color-tertiary-contrast: #ffffff;
--ion-color-tertiary-contrast-rgb: 255, 255, 255;
--ion-color-tertiary-shade: #4854e0;
--ion-color-tertiary-tint: #6370ff;
/** success **/
--ion-color-success: #2dd36f;
--ion-color-success-rgb: 45, 211, 111;
--ion-color-success-contrast: #ffffff;
--ion-color-success-contrast-rgb: 255, 255, 255;
--ion-color-success-shade: #28ba62;
--ion-color-success-tint: #42d77d;
/** warning **/
--ion-color-warning: #ffc409;
--ion-color-warning-rgb: 255, 196, 9;
--ion-color-warning-contrast: #000000;
--ion-color-warning-contrast-rgb: 0, 0, 0;
--ion-color-warning-shade: #e0ac08;
--ion-color-warning-tint: #ffca22;
/** danger **/
--ion-color-danger: #eb445a;
--ion-color-danger-rgb: 235, 68, 90;
--ion-color-danger-contrast: #ffffff;
--ion-color-danger-contrast-rgb: 255, 255, 255;
--ion-color-danger-shade: #cf3c4f;
--ion-color-danger-tint: #ed576b;
/** dark **/
--ion-color-dark: #222428;
--ion-color-dark-rgb: 34, 36, 40;
--ion-color-dark-contrast: #ffffff;
--ion-color-dark-contrast-rgb: 255, 255, 255;
--ion-color-dark-shade: #1e2023;
--ion-color-dark-tint: #383a3e;
/** medium **/
--ion-color-medium: #92949c;
--ion-color-medium-rgb: 146, 148, 156;
--ion-color-medium-contrast: #ffffff;
--ion-color-medium-contrast-rgb: 255, 255, 255;
--ion-color-medium-shade: #808289;
--ion-color-medium-tint: #9d9fa6;
/** light **/
--ion-color-light: #f4f5f8;
--ion-color-light-rgb: 244, 245, 248;
--ion-color-light-contrast: #000000;
--ion-color-light-contrast-rgb: 0, 0, 0;
--ion-color-light-shade: #d7d8da;
--ion-color-light-tint: #f5f6f9;
}
@media (prefers-color-scheme: dark) {
/*
* Dark Colors
* -------------------------------------------
*/
body {
--ion-color-primary: #428cff;
--ion-color-primary-rgb: 66,140,255;
--ion-color-primary-contrast: #ffffff;
--ion-color-primary-contrast-rgb: 255,255,255;
--ion-color-primary-shade: #3a7be0;
--ion-color-primary-tint: #5598ff;
--ion-color-secondary: #50c8ff;
--ion-color-secondary-rgb: 80,200,255;
--ion-color-secondary-contrast: #ffffff;
--ion-color-secondary-contrast-rgb: 255,255,255;
--ion-color-secondary-shade: #46b0e0;
--ion-color-secondary-tint: #62ceff;
--ion-color-tertiary: #6a64ff;
--ion-color-tertiary-rgb: 106,100,255;
--ion-color-tertiary-contrast: #ffffff;
--ion-color-tertiary-contrast-rgb: 255,255,255;
--ion-color-tertiary-shade: #5d58e0;
--ion-color-tertiary-tint: #7974ff;
--ion-color-success: #2fdf75;
--ion-color-success-rgb: 47,223,117;
--ion-color-success-contrast: #000000;
--ion-color-success-contrast-rgb: 0,0,0;
--ion-color-success-shade: #29c467;
--ion-color-success-tint: #44e283;
--ion-color-warning: #ffd534;
--ion-color-warning-rgb: 255,213,52;
--ion-color-warning-contrast: #000000;
--ion-color-warning-contrast-rgb: 0,0,0;
--ion-color-warning-shade: #e0bb2e;
--ion-color-warning-tint: #ffd948;
--ion-color-danger: #ff4961;
--ion-color-danger-rgb: 255,73,97;
--ion-color-danger-contrast: #ffffff;
--ion-color-danger-contrast-rgb: 255,255,255;
--ion-color-danger-shade: #e04055;
--ion-color-danger-tint: #ff5b71;
--ion-color-dark: #f4f5f8;
--ion-color-dark-rgb: 244,245,248;
--ion-color-dark-contrast: #000000;
--ion-color-dark-contrast-rgb: 0,0,0;
--ion-color-dark-shade: #d7d8da;
--ion-color-dark-tint: #f5f6f9;
--ion-color-medium: #989aa2;
--ion-color-medium-rgb: 152,154,162;
--ion-color-medium-contrast: #000000;
--ion-color-medium-contrast-rgb: 0,0,0;
--ion-color-medium-shade: #86888f;
--ion-color-medium-tint: #a2a4ab;
--ion-color-light: #222428;
--ion-color-light-rgb: 34,36,40;
--ion-color-light-contrast: #ffffff;
--ion-color-light-contrast-rgb: 255,255,255;
--ion-color-light-shade: #1e2023;
--ion-color-light-tint: #383a3e;
}
/*
* iOS Dark Theme
* -------------------------------------------
*/
.ios body {
--ion-background-color: #000000;
--ion-background-color-rgb: 0,0,0;
--ion-text-color: #ffffff;
--ion-text-color-rgb: 255,255,255;
--ion-color-step-50: #0d0d0d;
--ion-color-step-100: #1a1a1a;
--ion-color-step-150: #262626;
--ion-color-step-200: #333333;
--ion-color-step-250: #404040;
--ion-color-step-300: #4d4d4d;
--ion-color-step-350: #595959;
--ion-color-step-400: #666666;
--ion-color-step-450: #737373;
--ion-color-step-500: #808080;
--ion-color-step-550: #8c8c8c;
--ion-color-step-600: #999999;
--ion-color-step-650: #a6a6a6;
--ion-color-step-700: #b3b3b3;
--ion-color-step-750: #bfbfbf;
--ion-color-step-800: #cccccc;
--ion-color-step-850: #d9d9d9;
--ion-color-step-900: #e6e6e6;
--ion-color-step-950: #f2f2f2;
--ion-toolbar-background: #0d0d0d;
--ion-item-background: #000000;
--ion-card-background: #1c1c1d;
}
/*
* Material Design Dark Theme
* -------------------------------------------
*/
.md body {
--ion-background-color: #121212;
--ion-background-color-rgb: 18,18,18;
--ion-text-color: #ffffff;
--ion-text-color-rgb: 255,255,255;
--ion-border-color: #222222;
--ion-color-step-50: #1e1e1e;
--ion-color-step-100: #2a2a2a;
--ion-color-step-150: #363636;
--ion-color-step-200: #414141;
--ion-color-step-250: #4d4d4d;
--ion-color-step-300: #595959;
--ion-color-step-350: #656565;
--ion-color-step-400: #717171;
--ion-color-step-450: #7d7d7d;
--ion-color-step-500: #898989;
--ion-color-step-550: #949494;
--ion-color-step-600: #a0a0a0;
--ion-color-step-650: #acacac;
--ion-color-step-700: #b8b8b8;
--ion-color-step-750: #c4c4c4;
--ion-color-step-800: #d0d0d0;
--ion-color-step-850: #dbdbdb;
--ion-color-step-900: #e7e7e7;
--ion-color-step-950: #f3f3f3;
--ion-item-background: #1e1e1e;
--ion-toolbar-background: #1f1f1f;
--ion-tab-bar-background: #1f1f1f;
--ion-card-background: #1e1e1e;
}
}

View File

@@ -0,0 +1,55 @@
<template>
<ion-page data-pageid="home">
<ion-header :translucent="true">
<ion-toolbar>
<ion-title>Test App</ion-title>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Test App</ion-title>
</ion-toolbar>
</ion-header>
<ion-list>
<ion-item router-link="/overlays">
<ion-label>Overlays</ion-label>
</ion-item>
<ion-item router-link="/inputs">
<ion-label>Inputs</ion-label>
</ion-item>
<ion-item router-link="/slides">
<ion-label>Slides</ion-label>
</ion-item>
<ion-item router-link="/navigation" id="navigation">
<ion-label>Navigation</ion-label>
</ion-item>
<ion-item router-link="/nested" id="nested">
<ion-label>Nested Router Outlet</ion-label>
</ion-item>
</ion-list>
</ion-content>
</ion-page>
</template>
<script lang="ts">
import { IonContent, IonHeader, IonItem, IonLabel, IonList, IonPage, IonTitle, IonToolbar } from '@ionic/vue';
import { defineComponent } from 'vue';
export default defineComponent({
name: 'Home',
components: {
IonContent,
IonHeader,
IonItem,
IonLabel,
IonList,
IonPage,
IonTitle,
IonToolbar
}
});
</script>

View File

@@ -0,0 +1,225 @@
<template>
<ion-page>
<ion-header :translucent="true">
<ion-toolbar>
<ion-buttons>
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Inputs</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-segment v-model="segment">
<ion-segment-button value="dogs">
<ion-label>Dogs</ion-label>
</ion-segment-button>
<ion-segment-button value="cats">
<ion-label>Cats</ion-label>
</ion-segment-button>
</ion-segment>
</ion-toolbar>
<ion-toolbar>
<ion-searchbar v-model="searchbar"></ion-searchbar>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Inputs</ion-title>
</ion-toolbar>
</ion-header>
<ion-item>
<ion-label>Checkbox</ion-label>
<ion-checkbox slot="start" v-model="checkbox"></ion-checkbox>
</ion-item>
<ion-item>
<ion-label>Toggle</ion-label>
<ion-toggle slot="end" v-model="toggle"></ion-toggle>
</ion-item>
<ion-item>
<ion-label>Input</ion-label>
<ion-input slot="end" v-model="input"></ion-input>
</ion-item>
<ion-item>
<ion-label>Range</ion-label>
<ion-range :dual-knobs="true" :min="0" :max="100" slot="end" v-model="range"></ion-range>
</ion-item>
<ion-item>
<ion-label>Textarea</ion-label>
<ion-textarea slot="end" v-model="textarea"></ion-textarea>
</ion-item>
<ion-item>
<ion-label>Datetime</ion-label>
<ion-datetime v-model="datetime"></ion-datetime>
</ion-item>
<ion-radio-group v-model="radio">
<ion-item>
<ion-label>Red</ion-label>
<ion-radio value="red"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Green</ion-label>
<ion-radio value="green"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Blue</ion-label>
<ion-radio value="blue"></ion-radio>
</ion-item>
</ion-radio-group>
<ion-item>
<ion-label>Select</ion-label>
<ion-select v-model="select">
<ion-select-option value="apples">Apples</ion-select-option>
<ion-select-option value="bananas">Bananas</ion-select-option>
</ion-select>
</ion-item>
<div class="ion-padding">
Checkbox: {{ checkbox }}<br>
Toggle: {{ toggle }}<br>
Input: {{ input }}<br>
Range: {{ range }}<br>
Textarea: {{ textarea }}<br>
Searchbar: {{ searchbar }}<br>
Datetime: {{ datetime }}<br>
Radio Group: {{ radio }}<br>
Segment: {{ segment }}<br>
Select: {{ select }}<br>
<br>
<ion-button expand="block" @click="reset" id="reset">Reset Values</ion-button>
<ion-button expand="block" @click="set" id="set">Set Values</ion-button>
</div>
</ion-content>
</ion-page>
</template>
<script lang="ts">
import {
IonBackButton,
IonButton,
IonButtons,
IonCheckbox,
IonContent,
IonDatetime,
IonHeader,
IonInput,
IonItem,
IonLabel,
IonPage,
IonRadio,
IonRadioGroup,
IonRange,
IonSearchbar,
IonSegment,
IonSegmentButton,
IonSelect,
IonSelectOption,
IonTextarea,
IonTitle,
IonToggle,
IonToolbar
} from '@ionic/vue';
import { defineComponent, ref } from 'vue';
export default defineComponent({
name: 'Home',
components: {
IonBackButton,
IonButton,
IonButtons,
IonCheckbox,
IonContent,
IonDatetime,
IonHeader,
IonInput,
IonItem,
IonLabel,
IonPage,
IonRadio,
IonRadioGroup,
IonRange,
IonSearchbar,
IonSegment,
IonSegmentButton,
IonSelect,
IonSelectOption,
IonTextarea,
IonTitle,
IonToggle,
IonToolbar
},
setup() {
const checkbox = ref(false);
const toggle = ref(false);
const input = ref('');
const range = ref({
lower: 30,
upper: 70
});
const textarea = ref('');
const searchbar = ref('');
const datetime = ref('');
const radio = ref('red');
const segment = ref('dogs');
const select = ref('apples');
const reset = () => {
checkbox.value = false;
toggle.value = false;
input.value = '';
range.value = {
lower: 30,
upper: 70
};
textarea.value = '';
searchbar.value = '';
datetime.value = '';
radio.value = 'red';
segment.value = 'dogs';
select.value = 'apples';
}
const set = () => {
checkbox.value = true;
toggle.value = true;
input.value = 'Hello World';
range.value = {
lower: 10,
upper: 90
}
textarea.value = 'Lorem Ipsum';
searchbar.value = 'Search Query';
datetime.value = '2019-01-31';
radio.value = 'blue';
segment.value = 'cats';
select.value = 'bananas';
}
return {
checkbox,
toggle,
input,
range,
textarea,
searchbar,
datetime,
radio,
segment,
select,
reset,
set
}
}
});
</script>

View File

@@ -0,0 +1,50 @@
<template>
<ion-page data-pageid="navigation">
<ion-header :translucent="true">
<ion-toolbar>
<ion-buttons>
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Navigation</ion-title>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Navigation</ion-title>
</ion-toolbar>
</ion-header>
<div class="ion-padding">
On iOS mode, swipe to go back.
</div>
</ion-content>
</ion-page>
</template>
<script lang="ts">
import {
IonBackButton,
IonButtons,
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar
} from '@ionic/vue';
import { defineComponent } from 'vue';
export default defineComponent({
name: 'Navigation',
components: {
IonBackButton,
IonButtons,
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar
}
});
</script>

View File

@@ -0,0 +1,52 @@
<template>
<ion-page data-pageid="nestedchild">
<ion-header :translucent="true">
<ion-toolbar>
<ion-buttons>
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Nested Child</ion-title>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Nested Child</ion-title>
</ion-toolbar>
</ion-header>
<div class="ion-padding">
<ion-button router-link="/nested/two" id="nested-child-two">Nested Child Two</ion-button>
</div>
</ion-content>
</ion-page>
</template>
<script lang="ts">
import {
IonBackButton,
IonButton,
IonButtons,
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar
} from '@ionic/vue';
import { defineComponent } from 'vue';
export default defineComponent({
name: 'NestedChild',
components: {
IonBackButton,
IonButton,
IonButtons,
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar
}
});
</script>

View File

@@ -0,0 +1,46 @@
<template>
<ion-page data-pageid="nestedchildtwo">
<ion-header :translucent="true">
<ion-toolbar>
<ion-buttons>
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Nested Child Two</ion-title>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Nested Child Two</ion-title>
</ion-toolbar>
</ion-header>
</ion-content>
</ion-page>
</template>
<script lang="ts">
import {
IonBackButton,
IonButtons,
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar
} from '@ionic/vue';
import { defineComponent } from 'vue';
export default defineComponent({
name: 'NestedChildTwo',
components: {
IonBackButton,
IonButtons,
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar
}
});
</script>

View File

@@ -0,0 +1,340 @@
<template>
<ion-page>
<ion-header :translucent="true">
<ion-toolbar>
<ion-buttons>
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Overlays</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding" :fullscreen="true">
<ion-radio-group v-model="componentType">
<ion-list-header>
<ion-label>
Component
</ion-label>
</ion-list-header>
<ion-item>
<ion-label>Alert</ion-label>
<ion-radio value="alert" id="ion-alert"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Action Sheet</ion-label>
<ion-radio value="action-sheet" id="ion-action-sheet"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Loading</ion-label>
<ion-radio value="loading" id="ion-loading"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Modal</ion-label>
<ion-radio value="modal" id="ion-modal"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Popover</ion-label>
<ion-radio value="popover" id="ion-popover"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Toast</ion-label>
<ion-radio value="toast" id="ion-toast"></ion-radio>
</ion-item>
</ion-radio-group>
<ion-radio-group v-model="presentationType">
<ion-list-header>
<ion-label>
Presentation Type
</ion-label>
</ion-list-header>
<ion-item>
<ion-label>Controller</ion-label>
<ion-radio value="controller" id="controller"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Component</ion-label>
<ion-radio value="component" id="component"></ion-radio>
</ion-item>
</ion-radio-group>
<br />
<ion-button expand="block" @click="present($event)" id="present-overlay">Present Overlay</ion-button>
<ion-action-sheet
:is-open="isActionSheetOpen"
:buttons="actionSheetButtons"
@onDidDismiss="setActionSheetRef(false)"
>
</ion-action-sheet>
<ion-alert
:is-open="isAlertOpen"
header="Alert!"
:buttons="alertButtons"
@onDidDismiss="setAlertRef(false)"
>
</ion-alert>
<ion-loading
:is-open="isLoadingOpen"
:duration="2000"
message="Loading"
:backdrop-dismiss="true"
@onDidDismiss="setLoadingRef(false)"
>
</ion-loading>
<ion-modal
:is-open="isModalOpen"
@onDidDismiss="setModalRef(false)"
>
<ModalContent></ModalContent>
</ion-modal>
<ion-popover
:is-open="isPopoverOpen"
:event="popoverEvent"
@onDidDismiss="setPopoverRef(false)"
>
<PopoverContent></PopoverContent>
</ion-popover>
<ion-toast
:is-open="isToastOpen"
:duration="2000"
message="Toast"
:buttons="toastButtons"
@onDidDismiss="setToastRef(false)"
>
</ion-toast>
</ion-content>
</ion-page>
</template>
<script lang="ts">
import {
IonBackButton,
IonButton,
IonButtons,
IonContent,
IonHeader,
IonItem,
IonLabel,
IonListHeader,
IonPage,
IonRadio,
IonRadioGroup,
IonTitle,
IonToolbar,
IonActionSheet,
IonAlert,
IonLoading,
IonModal,
IonPopover,
IonToast,
actionSheetController,
alertController,
loadingController,
modalController,
popoverController,
toastController
} from '@ionic/vue';
import { defineComponent, ref } from 'vue';
import { trash, share, caretForwardCircle, heart, close } from 'ionicons/icons';
import ModalContent from '@/components/ModalContent.vue';
import PopoverContent from '@/components/PopoverContent.vue';
export default defineComponent({
name: 'Overlays',
components: {
ModalContent,
PopoverContent,
IonBackButton,
IonButton,
IonButtons,
IonContent,
IonHeader,
IonItem,
IonLabel,
IonListHeader,
IonPage,
IonRadio,
IonRadioGroup,
IonTitle,
IonToolbar,
IonActionSheet,
IonAlert,
IonLoading,
IonModal,
IonPopover,
IonToast
},
setup() {
const alertButtons = [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary',
handler: () => {
console.log('Confirm Cancel: blah');
}
}, {
text: 'Okay',
handler: () => {
console.log('Confirm Okay');
}
}
]
const actionSheetButtons = [
{
text: 'Delete',
role: 'destructive',
icon: trash,
handler: () => {
console.log('Delete clicked');
}
}, {
text: 'Share',
icon: share,
handler: () => {
console.log('Share clicked');
}
}, {
text: 'Play (open modal)',
icon: caretForwardCircle,
handler: () => {
console.log('Play clicked');
}
}, {
text: 'Favorite',
icon: heart,
handler: () => {
console.log('Favorite clicked');
}
}, {
text: 'Cancel',
icon: close,
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
}
]
const toastButtons = [
{
text: 'Close', role: 'close'
}
]
const openActionSheet = async () => {
const actionSheet = await actionSheetController.create({ buttons: actionSheetButtons });
await actionSheet.present();
}
const openAlert = async () => {
const alert = await alertController.create({ buttons: alertButtons, header: 'Alert!' });
await alert.present();
}
const openLoading = async () => {
const loading = await loadingController.create({ message: "Loading", duration: 2000, backdropDismiss: true });
await loading.present();
}
const openToast = async () => {
const toast = await toastController.create({ header: "Toast!", buttons: toastButtons });
await toast.present();
}
const openModal = async () => {
const modal = await modalController.create({ component: ModalContent });
await modal.present();
}
const openPopover = async (event: Event) => {
const popover = await popoverController.create({ component: PopoverContent, event });
await popover.present();
}
const isActionSheetOpen = ref(false);
const isAlertOpen = ref(false);
const isLoadingOpen = ref(false);
const isToastOpen = ref(false);
const isModalOpen = ref(false);
const isPopoverOpen = ref(false);
const popoverEvent = ref();
const setActionSheetRef = (value: boolean) => isActionSheetOpen.value = value;
const setAlertRef = (value: boolean) => isAlertOpen.value = value;
const setLoadingRef = (value: boolean) => isLoadingOpen.value = value;
const setToastRef = (value: boolean) => isToastOpen.value = value;
const setModalRef = (value: boolean) => isModalOpen.value = value;
const setPopoverRef = (value: boolean, event: Event) => {
popoverEvent.value = event;
isPopoverOpen.value = value;
}
const componentType = ref('alert');
const presentationType = ref('controller');
const present = (ev: Event) => {
const controller = presentationType.value === 'controller';
switch(componentType.value) {
case "alert":
controller ? openAlert() : setAlertRef(true);
break;
case "action-sheet":
controller ? openActionSheet() : setActionSheetRef(true);
break;
case "loading":
controller ? openLoading() : setLoadingRef(true);
break;
case "toast":
controller ? openToast() : setToastRef(true);
break;
case "modal":
controller ? openModal() : setModalRef(true);
break;
case "popover":
controller ? openPopover(ev) : setPopoverRef(true, ev);
break;
default:
break;
}
}
return {
present,
componentType,
presentationType,
actionSheetButtons,
alertButtons,
toastButtons,
openActionSheet,
openAlert,
openLoading,
openToast,
openModal,
openPopover,
isActionSheetOpen,
isAlertOpen,
isLoadingOpen,
isToastOpen,
isModalOpen,
isPopoverOpen,
setActionSheetRef,
setAlertRef,
setLoadingRef,
setToastRef,
setModalRef,
setPopoverRef,
popoverEvent
}
}
});
</script>

View File

@@ -0,0 +1,25 @@
<template>
<ion-page>
<ion-content>
<ion-router-outlet></ion-router-outlet>
</ion-content>
</ion-page>
</template>
<script lang="ts">
import {
IonContent,
IonPage,
IonRouterOutlet,
} from '@ionic/vue';
import { defineComponent } from 'vue';
export default defineComponent({
name: 'RouterOutlet',
components: {
IonContent,
IonPage,
IonRouterOutlet
}
});
</script>

View File

@@ -0,0 +1,119 @@
<template>
<ion-page>
<ion-header :translucent="true">
<ion-toolbar>
<ion-buttons>
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Slides</ion-title>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Slides</ion-title>
</ion-toolbar>
</ion-header>
<ion-slides @ionSlideDidChange="checkIndex" ref="slidesRef">
<ion-slide v-for="slide in slides" :key="slide.id">
{{ slide.text }}
</ion-slide>
</ion-slides>
<div class="ion-padding">
<ion-button expand="block" @click="slidePrevious">Previous</ion-button>
<ion-button expand="block" @click="slideNext">Next</ion-button>
<br>
Slides Index: {{ slidesIndex }}
</div>
</ion-content>
</ion-page>
</template>
<script lang="ts">
import {
IonBackButton,
IonButton,
IonButtons,
IonContent,
IonHeader,
IonPage,
IonSlide,
IonSlides,
IonTitle,
IonToolbar
} from '@ionic/vue';
import { defineComponent, ref } from 'vue';
export default defineComponent({
name: 'Home',
components: {
IonBackButton,
IonButton,
IonButtons,
IonContent,
IonHeader,
IonPage,
IonSlide,
IonSlides,
IonTitle,
IonToolbar
},
data() {
return {
slides: [
{ text: 'Slide 0', id: 0 },
{ text: 'Slide 1', id: 1 },
{ text: 'Slide 2', id: 2 }
]
}
},
setup() {
const slidesRef = ref();
const slidesIndex = ref(0);
const checkIndex = async () => {
slidesIndex.value = await slidesRef.value.$el.getActiveIndex();
}
const slideNext = () => {
slidesRef.value.$el.slideNext();
}
const slidePrevious = () => {
slidesRef.value.$el.slidePrev();
}
return {
slidesRef,
slidesIndex,
checkIndex,
slideNext,
slidePrevious
}
}
});
</script>
<style scoped>
ion-slides {
height: 200px;
}
ion-slide:nth-of-type(1) {
background: #0088cc;
}
ion-slide:nth-of-type(2) {
background: #0021cc;
}
ion-slide:nth-of-type(3) {
background: #00ccaa;
}
</style>

View File

@@ -0,0 +1,46 @@
<template>
<ion-page>
<ion-header :translucent="true">
<ion-toolbar>
<ion-buttons>
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Template</ion-title>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Template</ion-title>
</ion-toolbar>
</ion-header>
</ion-content>
</ion-page>
</template>
<script lang="ts">
import {
IonBackButton,
IonButtons,
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar
} from '@ionic/vue';
import { defineComponent } from 'vue';
export default defineComponent({
name: 'Home',
components: {
IonBackButton,
IonButtons,
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar
}
});
</script>

View File

@@ -0,0 +1,12 @@
module.exports = {
plugins: [
'cypress'
],
env: {
mocha: true,
'cypress/globals': true
},
rules: {
strict: 'off'
}
}

View File

@@ -0,0 +1,25 @@
/* eslint-disable arrow-body-style */
// https://docs.cypress.io/guides/guides/plugins-guide.html
// if you need a custom webpack configuration you can uncomment the following import
// and then use the `file:preprocessor` event
// as explained in the cypress docs
// https://docs.cypress.io/api/plugins/preprocessors-api.html#Examples
// /* eslint-disable import/no-extraneous-dependencies, global-require */
// const webpack = require('@cypress/webpack-preprocessor')
module.exports = (on, config) => {
// on('file:preprocessor', webpack({
// webpackOptions: require('@vue/cli-service/webpack.config'),
// watchOptions: {}
// }))
return Object.assign({}, config, {
fixturesFolder: 'tests/e2e/fixtures',
integrationFolder: 'tests/e2e/specs',
screenshotsFolder: 'tests/e2e/screenshots',
videosFolder: 'tests/e2e/videos',
supportFile: 'tests/e2e/support/index.js'
})
}

View File

@@ -0,0 +1,45 @@
describe('Inputs', () => {
beforeEach(() => {
cy.visit('http://localhost:8080/inputs')
})
it('should have default value', () => {
cy.get('ion-checkbox').should('have.prop', 'checked').and('eq', false);
cy.get('ion-toggle').should('have.prop', 'checked').and('eq', false);
cy.get('ion-input').should('have.prop', 'value').and('eq', '');
cy.get('ion-range').should('have.prop', 'value').and('deep.eq', { lower: 30, upper: 70 });
cy.get('ion-textarea').should('have.prop', 'value').and('eq', '');
cy.get('ion-searchbar').should('have.prop', 'value').and('eq', '');
cy.get('ion-datetime').should('have.prop', 'value').and('eq', '');
cy.get('ion-radio-group').should('have.prop', 'value').and('eq', 'red');
cy.get('ion-segment').should('have.prop', 'value').and('eq', 'dogs');
cy.get('ion-select').should('have.prop', 'value').and('eq', 'apples');
});
it('should set/reset values', () => {
cy.get('ion-button#set').click();
cy.get('ion-checkbox').should('have.prop', 'checked').and('eq', true);
cy.get('ion-toggle').should('have.prop', 'checked').and('eq', true);
cy.get('ion-input').should('have.prop', 'value').and('eq', 'Hello World');
cy.get('ion-range').should('have.prop', 'value').and('deep.eq', { lower: 10, upper: 90 });
cy.get('ion-textarea').should('have.prop', 'value').and('eq', 'Lorem Ipsum');
cy.get('ion-searchbar').should('have.prop', 'value').and('eq', 'Search Query');
cy.get('ion-datetime').should('have.prop', 'value').and('eq', '2019-01-31');
cy.get('ion-radio-group').should('have.prop', 'value').and('eq', 'blue');
cy.get('ion-segment').should('have.prop', 'value').and('eq', 'cats');
cy.get('ion-select').should('have.prop', 'value').and('eq', 'bananas');
cy.get('ion-button#reset').click();
cy.get('ion-checkbox').should('have.prop', 'checked').and('eq', false);
cy.get('ion-toggle').should('have.prop', 'checked').and('eq', false);
cy.get('ion-input').should('have.prop', 'value').and('eq', '');
cy.get('ion-range').should('have.prop', 'value').and('deep.eq', { lower: 30, upper: 70 });
cy.get('ion-textarea').should('have.prop', 'value').and('eq', '');
cy.get('ion-searchbar').should('have.prop', 'value').and('eq', '');
cy.get('ion-datetime').should('have.prop', 'value').and('eq', '');
cy.get('ion-radio-group').should('have.prop', 'value').and('eq', 'red');
cy.get('ion-segment').should('have.prop', 'value').and('eq', 'dogs');
cy.get('ion-select').should('have.prop', 'value').and('eq', 'apples');
});
})

View File

@@ -0,0 +1,20 @@
describe('Inputs', () => {
beforeEach(() => {
cy.viewport(320, 568);
cy.visit('http://localhost:8080?ionic:mode=ios');
cy.get('#navigation').click();
cy.wait(500);
})
it.skip('should swipe and abort', () => {
cy.ionPageInvisible('home');
cy.ionSwipeToGoBack();
cy.ionPageInvisible('home');
cy.ionPageVisible('navigation');
});
it.skip('should swipe and complete', () => {
cy.ionSwipeToGoBack(true);
cy.ionPageVisible('home');
});
});

View File

@@ -0,0 +1,21 @@
describe('Inputs', () => {
beforeEach(() => {
cy.visit('http://localhost:8080/nested');
});
it('should show first page', () => {
cy.ionPageVisible('nestedchild');
});
it.skip('should go to second page', () => {
cy.get('#nested-child-two').click();
cy.ionPageVisible('nestedchildtwo');
cy.ionPageInvisible('nestedchild');
});
it.skip('should go back to first page', () => {
cy.get('#nested-child-two').click();
cy.ionBackClick('nestedchildtwo');
cy.ionPageVisible('nestedchild');
});
})

View File

@@ -0,0 +1,61 @@
describe('Inputs', () => {
beforeEach(() => {
cy.visit('http://localhost:8080/overlays')
})
const overlays = ['ion-alert', 'ion-action-sheet', 'ion-loading', 'ion-modal', 'ion-popover'];
for (let overlay of overlays) {
it(`should open and close ${overlay} via controller`, () => {
console.log(overlay)
cy.get(`ion-radio#${overlay}`).click();
cy.get('ion-radio#controller').click();
cy.get('ion-button#present-overlay').click();
cy.get(overlay).should('exist').should('be.visible');
cy.get(`${overlay} ion-backdrop`).click({ force: true });
cy.get(overlay).should('not.exist');
});
}
it(`should open and close ion-toast via controller`, () => {
cy.get(`ion-radio#ion-toast`).click();
cy.get('ion-radio#controller').click();
cy.get('ion-button#present-overlay').click();
cy.get('ion-toast').should('exist');
cy.get('ion-toast').find('button').click();
cy.get('ion-toast').should('not.exist');
});
for (let overlay of overlays) {
it(`should open and close ${overlay} via component`, () => {
console.log(overlay)
cy.get(`ion-radio#${overlay}`).click();
cy.get('ion-radio#component').click();
cy.get('ion-button#present-overlay').click();
cy.get(overlay).should('exist').should('be.visible');
cy.get(`${overlay} ion-backdrop`).click({ force: true });
cy.get(overlay).should('not.exist');
});
}
it(`should open and close ion-toast via component`, () => {
cy.get(`ion-radio#ion-toast`).click();
cy.get('ion-radio#component').click();
cy.get('ion-button#present-overlay').click();
cy.get('ion-toast').should('exist');
cy.get('ion-toast').find('button').click();
cy.get('ion-toast').should('not.exist');
});
})

View File

@@ -0,0 +1,53 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
Cypress.Commands.add('ionSwipeToGoBack', (complete = false) => {
cy.get('ion-router-outlet')
.trigger('mousedown', { position: "left" })
.trigger('mousemove', { clientX: (complete) ? 100 : 300, clientY: 275 })
.trigger('mouseup', { force: true })
cy.wait(150);
})
Cypress.Commands.add('ionPageVisible', (pageId) => {
cy.get(`.ion-page[data-pageid=${pageId}]`)
.should('not.have.class', 'ion-page-hidden')
.should('not.have.class', 'ion-page-invisible')
.should('have.length', 1)
})
Cypress.Commands.add('ionPageInvisible', (pageId) => {
cy.get(`div.ion-page[data-pageid=${pageId}]`)
.should('have.class', 'ion-page-invisible')
.should('have.length', 1)
})
Cypress.Commands.add('ionBackClick', (pageId) => {
cy.get(`div.ion-page[data-pageid=${pageId}]`)
.should('be.visible', true)
.find('ion-back-button')
.click()
});

View File

@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')

View File

@@ -0,0 +1,12 @@
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'
describe('HelloWorld.vue', () => {
it('renders props.msg when passed', () => {
const msg = 'new message'
const wrapper = shallowMount(HelloWorld, {
props: { msg }
})
expect(wrapper.text()).toMatch(msg)
})
})

View File

@@ -0,0 +1,40 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env",
"jest"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}