mirror of
https://github.com/Elvanos/fantasia-archive.git
synced 2024-05-04 12:23:18 +12:00
Cleaned up frontend testing & Readme file
This commit is contained in:
parent
5e7526882c
commit
8a0ef51133
28
README.md
28
README.md
|
@ -11,42 +11,44 @@ Make sure you are running this with Node v16.17.0 ("nvm" is great for these olde
|
|||
|
||||
##### Ensure that the Yarn global install location is in your PATH after install. (details in article linked above)
|
||||
|
||||
```bash
|
||||
```
|
||||
yarn global add @quasar/cli
|
||||
```
|
||||
|
||||
## Install the dependencies and set up the project
|
||||
```bash
|
||||
```
|
||||
yarn
|
||||
```
|
||||
|
||||
### Start the app in Quasar development mode (hot-code reloading, error reporting, etc.)
|
||||
```bash
|
||||
```
|
||||
quasar dev -m electron
|
||||
```
|
||||
|
||||
### Build the app for production
|
||||
```bash
|
||||
```
|
||||
quasar build
|
||||
```
|
||||
|
||||
### Testing:
|
||||
|
||||
> Keep in mind that Cypress tests are limited to front-end testing due to the nature of Electron's nodeJS-based backend. Anything in Electron's main and preload will NOT work.
|
||||
|
||||
#### Unit test - with pretty web-UI
|
||||
```bash
|
||||
```
|
||||
test:unit:ui
|
||||
```
|
||||
#### Unit test - without any UI, fully in a terminal
|
||||
```bash
|
||||
test:unit
|
||||
```
|
||||
#### Component test - via Cypress, pick Electron on the config screen (I suggest turning on the electron dev window first, the test is a bit buggy sometimes)
|
||||
```bash
|
||||
test:component
|
||||
test:unit:ci
|
||||
```
|
||||
#### e2e test - via Cypress, pick Electron on the config screen (I suggest turning on the electron dev window first, the test is a bit buggy sometimes)
|
||||
```bash
|
||||
test:e2e
|
||||
#### Component test, Frontend - via Cypress, pick Electron on the config screen (I suggest turning on the electron dev window first, the test is a bit buggy sometimes)
|
||||
```
|
||||
test:component:frontend
|
||||
```
|
||||
#### E2E test, Froentend - via Cypress, pick Electron on the config screen (I suggest turning on the electron dev window first, the test is a bit buggy sometimes)
|
||||
```
|
||||
test:e2e:frontend
|
||||
```
|
||||
|
||||
### Customize the configuration
|
||||
|
|
|
@ -22,7 +22,7 @@ export default defineConfig({
|
|||
return config
|
||||
},
|
||||
supportFile: 'test/cypress/support/component.ts',
|
||||
specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}',
|
||||
specPattern: 'src/**/*.cy.test.{js,jsx,ts,tsx}',
|
||||
indexHtmlFile: 'test/cypress/support/component-index.html',
|
||||
devServer: injectQuasarDevServerConfig()
|
||||
}
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
"test:unit:ui": "vitest --ui",
|
||||
"test:unit": "vitest",
|
||||
"test:unit:ci": "vitest run",
|
||||
"test:e2e": "cross-env NODE_ENV=test start-test \"quasar dev\" http-get://localhost:9000 \"cypress open --e2e\"",
|
||||
"test:e2e:ci": "cross-env NODE_ENV=test start-test \"quasar dev\" http-get://localhost:9000 \"cypress run --e2e\"",
|
||||
"test:component": "cross-env NODE_ENV=test cypress open --component",
|
||||
"test:component:ci": "cross-env NODE_ENV=test cypress run --component"
|
||||
"test:e2e:frontend": "cross-env NODE_ENV=test start-test \"quasar dev\" http-get://localhost:9000 \"cypress open --e2e\"",
|
||||
"test:e2e:frontend:ci": "cross-env NODE_ENV=test start-test \"quasar dev\" http-get://localhost:9000 \"cypress run --e2e\"",
|
||||
"test:component:frontend": "cross-env NODE_ENV=test cypress open --component",
|
||||
"test:component:frontend:ci": "cross-env NODE_ENV=test cypress run --component"
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron/remote": "^2.0.10",
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import GlobalWindowButtons from './GlobalWindowButtons.vue'
|
||||
|
||||
describe('Component test - GlobalWindowButtons', () => {
|
||||
it('should have a `accent` color & `dark` background-color', () => {
|
||||
cy.mount(GlobalWindowButtons)
|
||||
|
||||
cy.get('.q-btn-group')
|
||||
.should('have.backgroundColor', 'var(--q-dark)')
|
||||
.should('have.color', 'var(--q-accent)')
|
||||
})
|
||||
})
|
|
@ -0,0 +1,28 @@
|
|||
import { installQuasar } from '@quasar/quasar-app-extension-testing-unit-vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import GlobalWindowButtons from './GlobalWindowButtons.vue'
|
||||
|
||||
installQuasar()
|
||||
|
||||
describe('Unit test - GlobalWindowButtons component', () => {
|
||||
it('should mount three buttons', () => {
|
||||
const wrapper = mount(GlobalWindowButtons)
|
||||
expect(wrapper.findAll('.q-btn')).toHaveLength(3)
|
||||
})
|
||||
|
||||
it('should have `minimize` button', () => {
|
||||
const wrapper = mount(GlobalWindowButtons)
|
||||
expect(wrapper.findAll('.globalWindowButtons__minimize')).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('should have `resize` button', () => {
|
||||
const wrapper = mount(GlobalWindowButtons)
|
||||
expect(wrapper.findAll('.globalWindowButtons__minimize')).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('should have `close` button', () => {
|
||||
const wrapper = mount(GlobalWindowButtons)
|
||||
expect(wrapper.findAll('.globalWindowButtons__minimize')).toHaveLength(1)
|
||||
})
|
||||
})
|
|
@ -10,6 +10,7 @@
|
|||
:ripple="false"
|
||||
dark
|
||||
size="xs"
|
||||
class="globalWindowButtons__minimize"
|
||||
@click="minimizeWindow()"
|
||||
>
|
||||
<q-tooltip
|
||||
|
@ -27,6 +28,7 @@
|
|||
:ripple="false"
|
||||
dark
|
||||
size="xs"
|
||||
class="globalWindowButtons__resize"
|
||||
@click="[resizeWindow(),checkIfWindowMaximized()]"
|
||||
>
|
||||
<q-tooltip
|
||||
|
@ -44,6 +46,7 @@
|
|||
:ripple="false"
|
||||
dark
|
||||
size="xs"
|
||||
class="globalWindowButtons__close"
|
||||
@click="tryCloseWindow()"
|
||||
>
|
||||
<q-tooltip
|
||||
|
@ -61,20 +64,23 @@
|
|||
import { onMounted, ref } from 'vue'
|
||||
import type { Ref } from 'vue'
|
||||
|
||||
// TODO Add all tests!
|
||||
|
||||
/*
|
||||
Triggers minimize of the window by the minimize button click
|
||||
*/
|
||||
const minimizeWindow = () => {
|
||||
window.faWindowControlAPI.minimizeWindow()
|
||||
console.log(process.env.MODE)
|
||||
if (process.env.MODE === 'electron') {
|
||||
window.faWindowControlAPI.minimizeWindow()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Triggers resize of the window by the min/max button click
|
||||
*/
|
||||
const resizeWindow = () => {
|
||||
window.faWindowControlAPI.resizeWindow()
|
||||
if (process.env.MODE === 'electron') {
|
||||
window.faWindowControlAPI.resizeWindow()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -87,14 +93,18 @@ Otherwise, the app simply closes
|
|||
*/
|
||||
const tryCloseWindow = () => {
|
||||
// TODO add project close checking
|
||||
window.faWindowControlAPI.closeWindow()
|
||||
if (process.env.MODE === 'electron') {
|
||||
window.faWindowControlAPI.closeWindow()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Checks if the window is maximized and sets local ref
|
||||
*/
|
||||
const checkIfWindowMaximized = () => {
|
||||
isMaximized.value = window.faWindowControlAPI.checkWindowMaximized()
|
||||
if (process.env.MODE === 'electron') {
|
||||
isMaximized.value = window.faWindowControlAPI.checkWindowMaximized()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
<template>
|
||||
<q-btn
|
||||
data-cy="button"
|
||||
label="test emit"
|
||||
color="positive"
|
||||
rounded
|
||||
icon="edit"
|
||||
@click="$emit('test')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QuasarButton',
|
||||
emits: { test: () => true }
|
||||
})
|
||||
</script>
|
|
@ -1,44 +0,0 @@
|
|||
<template>
|
||||
<q-checkbox
|
||||
v-model="checked"
|
||||
data-cy="checkbox"
|
||||
/>
|
||||
<q-toggle
|
||||
v-model="toggled"
|
||||
data-cy="toggle"
|
||||
/>
|
||||
|
||||
<q-radio
|
||||
v-model="selected"
|
||||
val="Value1"
|
||||
data-cy="radio-1"
|
||||
>
|
||||
Value1
|
||||
</q-radio>
|
||||
<q-radio
|
||||
v-model="selected"
|
||||
val="Value2"
|
||||
data-cy="radio-2"
|
||||
>
|
||||
Value2
|
||||
</q-radio>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QuasarCheckboxAndToggle',
|
||||
setup () {
|
||||
const checked = ref()
|
||||
const toggled = ref()
|
||||
const selected = ref()
|
||||
|
||||
return {
|
||||
checked,
|
||||
toggled,
|
||||
selected
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,16 +0,0 @@
|
|||
<template>
|
||||
<q-card
|
||||
data-cy="dark-card"
|
||||
:dark="$q.dark.isActive"
|
||||
>
|
||||
{{ $q.dark.isActive ? 'Dark ' : 'Light' }} content
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QuasarDark'
|
||||
})
|
||||
</script>
|
|
@ -1,50 +0,0 @@
|
|||
<template>
|
||||
<q-date
|
||||
v-model="date"
|
||||
data-cy="date-picker"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<q-input
|
||||
v-model="date"
|
||||
label="Scegli data"
|
||||
>
|
||||
<template #append>
|
||||
<q-btn
|
||||
data-cy="open-date-picker-popup-button"
|
||||
icon="event"
|
||||
flat
|
||||
round
|
||||
@click="dateDialogRef.show()"
|
||||
/>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-dialog ref="dateDialogRef">
|
||||
<q-date
|
||||
v-model="date"
|
||||
@update:model-value="dateDialogRef.hide()"
|
||||
/>
|
||||
</q-dialog>
|
||||
</div>
|
||||
|
||||
<span data-cy="date-value">{{ date }}</span>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { QDialog } from 'quasar'
|
||||
import type { Ref } from 'vue'
|
||||
import { defineComponent, ref } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QuasarDate',
|
||||
setup () {
|
||||
const date = ref('')
|
||||
const dateDialogRef = ref() as Ref<QDialog>
|
||||
|
||||
return {
|
||||
date,
|
||||
dateDialogRef
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,78 +0,0 @@
|
|||
<template>
|
||||
<!-- notice dialogRef here -->
|
||||
<q-dialog
|
||||
ref="dialogRef"
|
||||
@hide="onDialogHide"
|
||||
>
|
||||
<q-card>
|
||||
<q-card-section>{{ message }}</q-card-section>
|
||||
|
||||
<!-- buttons example -->
|
||||
<q-card-actions align="right">
|
||||
<q-btn
|
||||
data-cy="ok-button"
|
||||
color="primary"
|
||||
label="OK"
|
||||
@click="onOKClick"
|
||||
/>
|
||||
<q-btn
|
||||
color="primary"
|
||||
label="Cancel"
|
||||
@click="onCancelClick"
|
||||
/>
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { useDialogPluginComponent } from 'quasar'
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QuasarDialog',
|
||||
props: {
|
||||
message: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
// REQUIRED; need to specify some events that your
|
||||
// component will emit through useDialogPluginComponent()
|
||||
emits: useDialogPluginComponent.emits,
|
||||
|
||||
setup () {
|
||||
// REQUIRED; must be called inside of setup()
|
||||
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
||||
useDialogPluginComponent()
|
||||
// dialogRef - Vue ref to be applied to QDialog
|
||||
// onDialogHide - Function to be used as handler for @hide on QDialog
|
||||
// onDialogOK - Function to call to settle dialog with "ok" outcome
|
||||
// example: onDialogOK() - no payload
|
||||
// example: onDialogOK({ /*.../* }) - with payload
|
||||
// onDialogCancel - Function to call to settle dialog with "cancel" outcome
|
||||
|
||||
return {
|
||||
// This is REQUIRED;
|
||||
// Need to inject these (from useDialogPluginComponent() call)
|
||||
// into the vue scope for the vue html template
|
||||
dialogRef,
|
||||
onDialogHide,
|
||||
|
||||
// other methods that we used in our vue html template;
|
||||
// these are part of our example (so not required)
|
||||
onOKClick () {
|
||||
// on OK, it is REQUIRED to
|
||||
// call onDialogOK (with optional payload)
|
||||
onDialogOK()
|
||||
// or with payload: onDialogOK({ ... })
|
||||
// ...and it will also hide the dialog automatically
|
||||
},
|
||||
|
||||
// we can passthrough onDialogCancel directly
|
||||
onCancelClick: onDialogCancel
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,40 +0,0 @@
|
|||
<template>
|
||||
<q-drawer
|
||||
v-model="showDrawer"
|
||||
show-if-above
|
||||
:width="200"
|
||||
:breakpoint="700"
|
||||
elevated
|
||||
data-cy="drawer"
|
||||
class="bg-primary text-white"
|
||||
>
|
||||
<q-scroll-area class="fit">
|
||||
<div class="q-pa-sm">
|
||||
<div
|
||||
v-for="n in 50"
|
||||
:key="n"
|
||||
>
|
||||
Drawer {{ n }} / 50
|
||||
</div>
|
||||
</div>
|
||||
<q-btn data-cy="button">
|
||||
Am I on screen?
|
||||
</q-btn>
|
||||
</q-scroll-area>
|
||||
</q-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QuasarDrawer',
|
||||
setup () {
|
||||
const showDrawer = ref(true)
|
||||
|
||||
return {
|
||||
showDrawer
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,31 +0,0 @@
|
|||
<template>
|
||||
<q-btn
|
||||
data-cy="open-menu-btn"
|
||||
label="Open menu"
|
||||
>
|
||||
<q-menu>
|
||||
<q-list>
|
||||
<q-item
|
||||
v-close-popup
|
||||
clickable
|
||||
>
|
||||
<q-item-section>Item 1</q-item-section>
|
||||
</q-item>
|
||||
<q-item
|
||||
v-close-popup
|
||||
clickable
|
||||
>
|
||||
<q-item-section>Item 2</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QuasarMenu'
|
||||
})
|
||||
</script>
|
|
@ -1,29 +0,0 @@
|
|||
<template>
|
||||
<q-page-sticky
|
||||
position="bottom-right"
|
||||
:offset="[18, 18]"
|
||||
>
|
||||
<q-btn
|
||||
data-cy="button"
|
||||
rounded
|
||||
color="accent"
|
||||
icon="arrow_forward"
|
||||
>
|
||||
{{ title }}
|
||||
</q-btn>
|
||||
</q-page-sticky>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QuasarPageSticky',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,54 +0,0 @@
|
|||
<template>
|
||||
<q-select
|
||||
v-model="selected"
|
||||
data-cy="select"
|
||||
label="test options selection"
|
||||
:options="options"
|
||||
:loading="loading"
|
||||
:disable="disable"
|
||||
/>
|
||||
|
||||
<span data-cy="select-value">{{ selected }}</span>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue'
|
||||
|
||||
const syncOptions = ['Option 1', 'Option 2', 'Option 3']
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QuasarSelect',
|
||||
props: {
|
||||
loadOptionsAsync: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
const selected = ref()
|
||||
const loading = ref(false)
|
||||
|
||||
const options = ref()
|
||||
|
||||
if (props.loadOptionsAsync) {
|
||||
loading.value = true
|
||||
setTimeout(() => {
|
||||
options.value = syncOptions
|
||||
loading.value = false
|
||||
}, 2000)
|
||||
} else {
|
||||
options.value = syncOptions
|
||||
}
|
||||
|
||||
return {
|
||||
loading,
|
||||
selected,
|
||||
options
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,31 +0,0 @@
|
|||
<template>
|
||||
<q-btn
|
||||
color="primary"
|
||||
data-cy="button"
|
||||
>
|
||||
Button
|
||||
<q-tooltip
|
||||
v-model="showTooltip"
|
||||
data-cy="tooltip"
|
||||
class="bg-red"
|
||||
:offset="[10, 10]"
|
||||
>
|
||||
Here I am!
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QuasarTooltip',
|
||||
setup () {
|
||||
const showTooltip = ref(true)
|
||||
|
||||
return {
|
||||
showTooltip
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,32 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<span data-cy="model-value">{{ modelValue }}</span>
|
||||
<button
|
||||
data-cy="button"
|
||||
@click="
|
||||
$emit(
|
||||
'update:modelValue',
|
||||
modelValue.length > 0 ? modelValue.substring(1) : ''
|
||||
)
|
||||
"
|
||||
>
|
||||
Remove first letter
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QuasarTooltip',
|
||||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
emits: { 'update:modelValue': (payload: string) => payload !== undefined }
|
||||
})
|
||||
</script>
|
|
@ -1,43 +0,0 @@
|
|||
import QuasarButton from '../QuasarButton.vue'
|
||||
|
||||
describe('QuasarButton', () => {
|
||||
it('renders a message', () => {
|
||||
const label = 'Hello there'
|
||||
cy.mount(QuasarButton, {
|
||||
props: {
|
||||
label
|
||||
}
|
||||
})
|
||||
|
||||
cy.dataCy('button').should('contain', label)
|
||||
})
|
||||
|
||||
it('renders another message', () => {
|
||||
const label = 'Will this work?'
|
||||
cy.mount(QuasarButton, {
|
||||
props: {
|
||||
label
|
||||
}
|
||||
})
|
||||
|
||||
cy.dataCy('button').should('contain', label)
|
||||
})
|
||||
|
||||
it('should have a `positive` color', () => {
|
||||
cy.mount(QuasarButton)
|
||||
|
||||
cy.dataCy('button')
|
||||
.should('have.backgroundColor', 'var(--q-positive)')
|
||||
.should('have.color', 'white')
|
||||
})
|
||||
|
||||
it('should emit `test` upon click', () => {
|
||||
cy.mount(QuasarButton)
|
||||
|
||||
cy.dataCy('button')
|
||||
cy.dataCy('button').click()
|
||||
cy.dataCy('button').should(() => {
|
||||
expect(Cypress.vueWrapper.emitted('test')).to.have.length(1)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,38 +0,0 @@
|
|||
import QuasarCheckComponents from '../QuasarCheckComponents.vue'
|
||||
|
||||
describe('QuasarCheckbox', () => {
|
||||
it('can be used with normal Cypress commands', () => {
|
||||
cy.mount(QuasarCheckComponents)
|
||||
|
||||
cy.dataCy('checkbox').check()
|
||||
cy.dataCy('checkbox').should('be.checked')
|
||||
|
||||
cy.dataCy('checkbox').uncheck()
|
||||
cy.dataCy('checkbox').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
|
||||
describe('QuasarToggle', () => {
|
||||
it('can be used with normal Cypress commands', () => {
|
||||
cy.mount(QuasarCheckComponents)
|
||||
|
||||
cy.dataCy('toggle').check()
|
||||
cy.dataCy('toggle').should('be.checked')
|
||||
|
||||
cy.dataCy('toggle').uncheck()
|
||||
cy.dataCy('toggle').should('not.be.checked')
|
||||
})
|
||||
})
|
||||
|
||||
describe('QuasarToggle', () => {
|
||||
it('can be used with normal Cypress commands', () => {
|
||||
cy.mount(QuasarCheckComponents)
|
||||
|
||||
cy.dataCy('radio-1').check()
|
||||
cy.dataCy('radio-1').should('be.checked')
|
||||
|
||||
cy.dataCy('radio-2').check()
|
||||
cy.dataCy('radio-2').should('be.checked')
|
||||
cy.dataCy('radio-1').should('not.be.checked')
|
||||
})
|
||||
})
|
|
@ -1,22 +0,0 @@
|
|||
import { Dark } from 'quasar'
|
||||
import QuasarDark from '../QuasarDark.vue'
|
||||
|
||||
describe('QuasarDark', () => {
|
||||
it('changes its color', () => {
|
||||
cy.mount(QuasarDark)
|
||||
|
||||
cy.dataCy('dark-card')
|
||||
.should('not.have.class', 'q-dark')
|
||||
.then(() => {
|
||||
Dark.set(true)
|
||||
})
|
||||
|
||||
cy.dataCy('dark-card')
|
||||
.should('have.class', 'q-dark')
|
||||
.then(() => {
|
||||
Cypress.vueWrapper.vm.$q.dark.set(false)
|
||||
})
|
||||
|
||||
cy.dataCy('dark-card').should('not.have.class', 'q-dark')
|
||||
})
|
||||
})
|
|
@ -1,33 +0,0 @@
|
|||
import QuasarDate from '../QuasarDate.vue'
|
||||
|
||||
const targetDate = '2023/02/23'
|
||||
|
||||
describe('QuasarDate', () => {
|
||||
it('selects a date by date string', () => {
|
||||
cy.mount(QuasarDate)
|
||||
|
||||
cy.dataCy('date-picker').selectDate(targetDate)
|
||||
cy.dataCy('date-value').should('have.text', targetDate)
|
||||
})
|
||||
|
||||
it('selects a date by date object', () => {
|
||||
cy.mount(QuasarDate)
|
||||
|
||||
cy.dataCy('date-picker').selectDate(new Date(targetDate))
|
||||
cy.dataCy('date-value').should('have.text', targetDate)
|
||||
})
|
||||
|
||||
it('selects a date displayed into a popup proxy', () => {
|
||||
cy.mount(QuasarDate)
|
||||
|
||||
cy.dataCy('open-date-picker-popup-button').click()
|
||||
cy.withinDialog(() => {
|
||||
cy.get('.q-date').selectDate(targetDate)
|
||||
})
|
||||
cy.dataCy('date-value').should('have.text', targetDate)
|
||||
|
||||
// When dealing with a nested dialog, or a popup proxy within a dialog,
|
||||
// add a data-cy on the dialog/popup-proxy containing the QDate and use the `withinDialog` extended signature:
|
||||
// Example: cy.withinDialog({ dataCy: 'date-picker-popup', fn: () => { cy.get('.q-date').selectDate(targetDate); } })
|
||||
})
|
||||
})
|
|
@ -1,42 +0,0 @@
|
|||
import DialogWrapper from 'app/test/cypress/wrappers/DialogWrapper.vue'
|
||||
import QuasarDialog from '../QuasarDialog.vue'
|
||||
|
||||
describe('QuasarDialog', () => {
|
||||
it('should show a dialog with a message', () => {
|
||||
const message = 'Hello, I am a dialog'
|
||||
cy.mount(DialogWrapper, {
|
||||
props: {
|
||||
component: QuasarDialog,
|
||||
componentProps: {
|
||||
message
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
cy.withinDialog((el) => {
|
||||
cy.wrap(el).should('contain', message)
|
||||
cy.dataCy('ok-button').click()
|
||||
})
|
||||
})
|
||||
|
||||
it('should keep the dialog open when not dismissed', () => {
|
||||
const message = 'Hello, I am a dialog'
|
||||
cy.mount(DialogWrapper, {
|
||||
props: {
|
||||
component: QuasarDialog,
|
||||
componentProps: {
|
||||
message
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// The helper won't check for the dialog to be closed
|
||||
// when the callback completes
|
||||
cy.withinDialog({
|
||||
persistent: true,
|
||||
fn: (el) => {
|
||||
cy.wrap(el).should('contain', message)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,20 +0,0 @@
|
|||
import LayoutContainer from 'app/test/cypress/wrappers/LayoutContainer.vue'
|
||||
import QuasarDrawer from '../QuasarDrawer.vue'
|
||||
|
||||
describe('QuasarDrawer', () => {
|
||||
it('should show a drawer', () => {
|
||||
cy.mount(LayoutContainer, {
|
||||
props: {
|
||||
component: QuasarDrawer
|
||||
}
|
||||
})
|
||||
cy.dataCy('drawer')
|
||||
.should('exist')
|
||||
.dataCy('button')
|
||||
.should('not.be.visible')
|
||||
cy.get('.q-scrollarea .scroll')
|
||||
cy.get('.q-scrollarea .scroll').scrollTo('bottom', { duration: 500 })
|
||||
cy.get('.q-scrollarea .scroll').dataCy('button')
|
||||
cy.get('.q-scrollarea .scroll').should('be.visible')
|
||||
})
|
||||
})
|
|
@ -1,21 +0,0 @@
|
|||
import QuasarMenu from '../QuasarMenu.vue'
|
||||
|
||||
describe('QuasarMenu', () => {
|
||||
it('click an item by content', () => {
|
||||
cy.mount(QuasarMenu)
|
||||
|
||||
cy.dataCy('open-menu-btn').click()
|
||||
cy.withinMenu(() => {
|
||||
cy.get('.q-item').contains('Item 1').click()
|
||||
})
|
||||
})
|
||||
|
||||
it('click an item by cardinality', () => {
|
||||
cy.mount(QuasarMenu)
|
||||
|
||||
cy.dataCy('open-menu-btn').click()
|
||||
cy.withinMenu(() => {
|
||||
cy.get('.q-item').eq(1).click()
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,21 +0,0 @@
|
|||
import LayoutContainer from 'app/test/cypress/wrappers/LayoutContainer.vue'
|
||||
import QuasarPageSticky from '../QuasarPageSticky.vue'
|
||||
|
||||
describe('QuasarPageSticky', () => {
|
||||
it('should show a sticky at the bottom-right of the page', () => {
|
||||
cy.mount(LayoutContainer, {
|
||||
props: {
|
||||
component: QuasarPageSticky,
|
||||
title: 'Test'
|
||||
}
|
||||
})
|
||||
|
||||
cy.dataCy('button')
|
||||
.should('be.visible')
|
||||
.should(($el) => {
|
||||
const rect = $el[0].getBoundingClientRect()
|
||||
expect(rect.bottom).to.equal(window.innerHeight - 18)
|
||||
expect(rect.right).to.equal(window.innerWidth - 18)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,44 +0,0 @@
|
|||
import QuasarSelect from '../QuasarSelect.vue'
|
||||
|
||||
function dataCySelect (dataCyId: string) {
|
||||
return cy.dataCy(dataCyId).closest('.q-select')
|
||||
}
|
||||
|
||||
describe('QuasarSelect', () => {
|
||||
it('makes sure the select is disabled', () => {
|
||||
cy.mount(QuasarSelect, {
|
||||
props: { disable: true }
|
||||
})
|
||||
|
||||
// `cy.dataCy('select')` won't work in this case, as it won't get the root q-select element
|
||||
dataCySelect('select').should('have.attr', 'aria-disabled', 'true')
|
||||
})
|
||||
|
||||
it('selects an option by content', () => {
|
||||
cy.mount(QuasarSelect)
|
||||
|
||||
cy.dataCy('select').select('Option 1')
|
||||
cy.dataCy('select-value').should('have.text', 'Option 1')
|
||||
})
|
||||
|
||||
it('selects an option by cardinality', () => {
|
||||
cy.mount(QuasarSelect)
|
||||
|
||||
cy.dataCy('select').select(1)
|
||||
cy.dataCy('select-value').should('have.text', 'Option 2')
|
||||
})
|
||||
|
||||
it('selects an option asynchronously', () => {
|
||||
cy.mount(QuasarSelect, {
|
||||
props: {
|
||||
loadOptionsAsync: true
|
||||
}
|
||||
})
|
||||
|
||||
// Wait for loading to complete
|
||||
cy.dataCy('select').get('.q-spinner').should('not.exist')
|
||||
|
||||
cy.dataCy('select').select('Option 3')
|
||||
cy.dataCy('select-value').should('have.text', 'Option 3')
|
||||
})
|
||||
})
|
|
@ -1,10 +0,0 @@
|
|||
import QuasarTooltip from '../QuasarTooltip.vue'
|
||||
|
||||
describe('QuasarTooltip', () => {
|
||||
it('should show a tooltip', () => {
|
||||
cy.mount(QuasarTooltip)
|
||||
|
||||
cy.dataCy('button').trigger('mouseover')
|
||||
cy.dataCy('tooltip').contains('Here I am!')
|
||||
})
|
||||
})
|
|
@ -1,72 +0,0 @@
|
|||
import { vModelAdapter } from '@quasar/quasar-app-extension-testing-e2e-cypress'
|
||||
import { ref } from 'vue'
|
||||
import VModelComponent from '../VModelComponent.vue'
|
||||
|
||||
describe('VModelComponent', () => {
|
||||
it('should show the value', () => {
|
||||
const text = 'Quasar'
|
||||
|
||||
cy.mount(VModelComponent, {
|
||||
props: {
|
||||
modelValue: text
|
||||
}
|
||||
})
|
||||
|
||||
cy.dataCy('model-value').should('contain', text)
|
||||
})
|
||||
|
||||
it('should call the listener when an update via inner button occurs', () => {
|
||||
const text = 'Quasar'
|
||||
const fn = cy.stub()
|
||||
|
||||
cy.mount(VModelComponent, {
|
||||
props: {
|
||||
modelValue: text,
|
||||
// This is how Vue internally codifies listeners,
|
||||
// defining a prop prepended with `on` and camelCased
|
||||
'onUpdate:modelValue': fn
|
||||
}
|
||||
})
|
||||
|
||||
cy.dataCy('button')
|
||||
cy.dataCy('button').click()
|
||||
cy.dataCy('button').then(() => {
|
||||
expect(fn).to.be.calledWith('uasar')
|
||||
})
|
||||
})
|
||||
|
||||
it('should update the value via inner button when not using the helper', () => {
|
||||
const text = 'Quasar'
|
||||
|
||||
cy.mount(VModelComponent, {
|
||||
props: {
|
||||
modelValue: text,
|
||||
'onUpdate:modelValue': (emittedValue: string) =>
|
||||
Cypress.vueWrapper.setProps({ modelValue: emittedValue })
|
||||
}
|
||||
})
|
||||
|
||||
cy.dataCy('button').click()
|
||||
cy.dataCy('model-value').should('contain', 'uasar')
|
||||
})
|
||||
|
||||
it('should update the value via inner button using the helper', () => {
|
||||
const model = ref('Quasar')
|
||||
|
||||
cy.mount(VModelComponent, {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
props: {
|
||||
...vModelAdapter(model)
|
||||
}
|
||||
})
|
||||
|
||||
cy.dataCy('button').click()
|
||||
cy.dataCy('model-value')
|
||||
.should('contain', 'uasar')
|
||||
.then(() => {
|
||||
// You cannot access `model.value` in a synchronous way,
|
||||
// you need to chain checks on it to a Cypress command or you'll be testing the initial value.
|
||||
expect(model.value).to.equal('uasar')
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,12 +0,0 @@
|
|||
import ColorAssertionsComponent from '../color-assertions.vue'
|
||||
|
||||
describe('color assertions', () => {
|
||||
it('works with names, hex codes and CSS variables', () => {
|
||||
cy.mount(ColorAssertionsComponent)
|
||||
|
||||
cy.get('.wrapper')
|
||||
.should('have.color', 'var(--q-primary)')
|
||||
.and('have.backgroundColor', 'black')
|
||||
.and('have.backgroundColor', '#000')
|
||||
})
|
||||
})
|
|
@ -1,16 +0,0 @@
|
|||
import DataCyComponent from '../data-cy.vue'
|
||||
|
||||
describe('dataCy command', () => {
|
||||
it('works as a parent command', () => {
|
||||
cy.mount(DataCyComponent)
|
||||
|
||||
cy.dataCy('wrapper').should('exist')
|
||||
cy.dataCy('paragraph').should('exist').and('contain', 'Test')
|
||||
})
|
||||
|
||||
it('works as a child command', () => {
|
||||
cy.mount(DataCyComponent)
|
||||
|
||||
cy.dataCy('wrapper').dataCy('paragraph').should('exist')
|
||||
})
|
||||
})
|
|
@ -1,5 +0,0 @@
|
|||
<template>
|
||||
<div class="wrapper text-primary bg-black">
|
||||
Text1
|
||||
</div>
|
||||
</template>
|
|
@ -1,7 +0,0 @@
|
|||
<template>
|
||||
<div data-cy="wrapper">
|
||||
<p data-cy="paragraph">
|
||||
Test
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
|
@ -1,38 +0,0 @@
|
|||
import { installQuasar } from '@quasar/quasar-app-extension-testing-unit-vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import ExampleComponent from './demo/ExampleComponent.vue'
|
||||
|
||||
installQuasar()
|
||||
|
||||
describe('example Component', () => {
|
||||
it('should mount component with todos', () => {
|
||||
const wrapper = mount(ExampleComponent, {
|
||||
props: {
|
||||
title: 'Hello',
|
||||
meta: {
|
||||
totalCount: 4
|
||||
},
|
||||
todos: [
|
||||
{ id: 1, content: 'Hallo' },
|
||||
{ id: 2, content: 'Hoi' }
|
||||
]
|
||||
}
|
||||
})
|
||||
expect(wrapper.vm.clickCount).toBe(0)
|
||||
wrapper.find('.q-item').trigger('click')
|
||||
expect(wrapper.vm.clickCount).toBe(1)
|
||||
})
|
||||
|
||||
it('should mount component without todos', () => {
|
||||
const wrapper = mount(ExampleComponent, {
|
||||
props: {
|
||||
title: 'Hello',
|
||||
meta: {
|
||||
totalCount: 4
|
||||
}
|
||||
}
|
||||
})
|
||||
expect(wrapper.findAll('.q-item')).toHaveLength(0)
|
||||
})
|
||||
})
|
|
@ -1,19 +0,0 @@
|
|||
import { installQuasar } from '@quasar/quasar-app-extension-testing-unit-vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { Notify } from 'quasar'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import NotifyComponent from './demo/NotifyComponent.vue'
|
||||
|
||||
installQuasar({ plugins: { Notify } })
|
||||
|
||||
describe('notify example', () => {
|
||||
it('should call notify on click', async () => {
|
||||
expect(NotifyComponent).toBeTruthy()
|
||||
|
||||
const wrapper = mount(NotifyComponent, {})
|
||||
const spy = vi.spyOn(Notify, 'create')
|
||||
expect(spy).not.toHaveBeenCalled()
|
||||
wrapper.trigger('click')
|
||||
expect(spy).toHaveBeenCalled()
|
||||
})
|
||||
})
|
|
@ -1,52 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<p>{{ title }}</p>
|
||||
<q-list>
|
||||
<q-item
|
||||
v-for="todo in todos"
|
||||
:key="todo.id"
|
||||
clickable
|
||||
@click="increment"
|
||||
>
|
||||
{{ todo.id }} - {{ todo.content }}
|
||||
</q-item>
|
||||
</q-list>
|
||||
|
||||
<p>Count: {{ todoCount }} / {{ meta.totalCount }}</p>
|
||||
<p>Active: {{ active ? 'yes' : 'no' }}</p>
|
||||
<p>Clicks on todos: {{ clickCount }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
interface Todo {
|
||||
id: number;
|
||||
content: string;
|
||||
}
|
||||
|
||||
interface Meta {
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
title: string;
|
||||
todos?: Todo[];
|
||||
meta: Meta;
|
||||
active?: boolean;
|
||||
}>(),
|
||||
{
|
||||
todos: () => []
|
||||
}
|
||||
)
|
||||
|
||||
const clickCount = ref(0)
|
||||
function increment () {
|
||||
clickCount.value += 1
|
||||
return clickCount.value
|
||||
}
|
||||
|
||||
const todoCount = computed(() => props.todos.length)
|
||||
</script>
|
|
@ -1,13 +0,0 @@
|
|||
<template>
|
||||
<q-btn @click="onClick">
|
||||
Click me!
|
||||
</q-btn>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Notify } from 'quasar'
|
||||
|
||||
function onClick () {
|
||||
Notify.create('Hello there!')
|
||||
}
|
||||
</script>
|
Loading…
Reference in a new issue