finished integrating component testing + cleanup

This commit is contained in:
Elvanos 2023-09-08 23:54:44 +02:00
parent 53040468db
commit ea6367bb0f
24 changed files with 407 additions and 423 deletions

View file

@ -10,7 +10,7 @@
"dev:electron": "quasar dev -m electron", "dev:electron": "quasar dev -m electron",
"build": "quasar build -m electron --publish never", "build": "quasar build -m electron --publish never",
"test:unit:ui": "vitest --ui", "test:unit:ui": "vitest --ui",
"test:unit:ci": "vitest run", "test:unit:ci": "vitest run --reporter verbose",
"test:component": "node \"node_modules/@playwright/test/cli.js\" test src/components/", "test:component": "node \"node_modules/@playwright/test/cli.js\" test src/components/",
"test:e2e": "node \"node_modules/@playwright/test/cli.js\" test test/playwright-e2e/" "test:e2e": "node \"node_modules/@playwright/test/cli.js\" test test/playwright-e2e/"
}, },

View file

@ -0,0 +1,9 @@
import { I_extraEnvVariablesAPI } from 'src/interfaces/I_extraEnvVariablesAPI'
import appRoot from 'app-root-path'
export const extraEnvVariablesAPI: I_extraEnvVariablesAPI = {
ELECTRON_MAIN_FILEPATH: appRoot + '/dist/electron/UnPackaged/electron-main.js',
FA_FRONTEND_RENDER_TIMER: 1000,
TEST_ENV: (process.env.TEST_ENV) ? process.env.TEST_ENV : false,
COMPONENT_NAME: (process.env.COMPONENT_NAME) ? process.env.COMPONENT_NAME : false
}

View file

@ -0,0 +1,40 @@
import { BrowserWindow } from '@electron/remote'
import { I_faWindowControlAPI } from 'src/interfaces/I_faWindowControlAPI'
export const faWindowControlAPI: I_faWindowControlAPI = {
checkWindowMaximized () {
const currentWindow = BrowserWindow.getFocusedWindow()
if (currentWindow !== null) {
return currentWindow.isMaximized()
}
return false
},
minimizeWindow () {
const currentWindow = BrowserWindow.getFocusedWindow()
if (currentWindow !== null) {
currentWindow.minimize()
}
},
resizeWindow () {
const currentWindow = BrowserWindow.getFocusedWindow()
if (currentWindow !== null) {
if (currentWindow.isMaximized()) {
currentWindow.unmaximize()
} else {
currentWindow.maximize()
}
}
},
closeWindow () {
const currentWindow = BrowserWindow.getFocusedWindow()
if (currentWindow !== null) {
currentWindow.close()
}
}
}

View file

@ -29,44 +29,9 @@
*/ */
import { contextBridge } from 'electron' import { contextBridge } from 'electron'
import { BrowserWindow } from '@electron/remote'
import { I_faWindowControlAPI } from 'src/interfaces/I_faWindowControlAPI'
const faWindowControlAPI: I_faWindowControlAPI = { import { faWindowControlAPI } from 'src-electron/customContentBridgeAPIs/faWindowControlAPI'
import { extraEnvVariablesAPI } from 'src-electron/customContentBridgeAPIs/extraEnvVariablesAPI'
checkWindowMaximized () {
const currentWindow = BrowserWindow.getFocusedWindow()
if (currentWindow !== null) {
return currentWindow.isMaximized()
}
return false
},
minimizeWindow () {
const currentWindow = BrowserWindow.getFocusedWindow()
if (currentWindow !== null) {
currentWindow.minimize()
}
},
resizeWindow () {
const currentWindow = BrowserWindow.getFocusedWindow()
if (currentWindow !== null) {
if (currentWindow.isMaximized()) {
currentWindow.unmaximize()
} else {
currentWindow.maximize()
}
}
},
closeWindow () {
const currentWindow = BrowserWindow.getFocusedWindow()
if (currentWindow !== null) {
currentWindow.close()
}
}
}
contextBridge.exposeInMainWorld('faWindowControlAPI', faWindowControlAPI) contextBridge.exposeInMainWorld('faWindowControlAPI', faWindowControlAPI)
contextBridge.exposeInMainWorld('extraEnvVariables', extraEnvVariablesAPI)

View file

@ -4,8 +4,39 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue' import { defineComponent } from 'vue'
import { useRouter } from 'vue-router'
export default defineComponent({ export default defineComponent({
name: 'App' name: 'App',
/**
* Setup is used to determine if the app is running testing of some kind or in normal mode
*/
setup () {
/**
* Local router variable
*/
const router = useRouter()
/**
* Testing type currently possibly happening
* */
const testingType = window.extraEnvVariables.TEST_ENV
/**
* Name of the component being possibly tested via component testing
* */
const testingComponentName = window.extraEnvVariables.COMPONENT_NAME
/**
* In case of some testing happening:
* Reroute to the proper component path route assuming all is properly set.
* Otherwise, make sure we are on homepage on load.
*/
if (testingType && testingType === 'components' && testingComponentName) {
router.push({ path: `/componentTesting/${testingComponentName}` })
} else {
router.push({ path: '/' })
}
}
}) })
</script> </script>

View file

@ -24,6 +24,7 @@ declare module 'vue-i18n' {
export default boot(({ app }) => { export default boot(({ app }) => {
const i18n = createI18n({ const i18n = createI18n({
locale: 'en-US', locale: 'en-US',
fallbackLocale: 'en-US',
legacy: false, legacy: false,
messages messages
}) })

View file

@ -1,51 +0,0 @@
<template>
<q-item
clickable
tag="a"
target="_blank"
:href="link"
>
<q-item-section
v-if="icon"
avatar
>
<q-icon :name="icon" />
</q-item-section>
<q-item-section>
<q-item-label>{{ title }}</q-item-label>
<q-item-label caption>
{{ caption }}
</q-item-label>
</q-item-section>
</q-item>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'EssentialLink',
props: {
title: {
type: String,
required: true
},
caption: {
type: String,
default: ''
},
link: {
type: String,
default: '#'
},
icon: {
type: String,
default: ''
}
}
})
</script>

View file

@ -1,68 +0,0 @@
<template>
<div>
<p>{{ title }}</p>
<ul>
<li
v-for="todo in todos"
:key="todo.id"
@click="increment"
>
{{ todo.id }} - {{ todo.content }}
</li>
</ul>
<p>Count: {{ todoCount }} / {{ meta.totalCount }}</p>
<p>Active: {{ active ? 'yes' : 'no' }}</p>
<p>Clicks on todos: {{ clickCount }}</p>
</div>
</template>
<script lang="ts">
import {
defineComponent,
PropType,
computed,
ref,
toRef,
Ref
} from 'vue'
import { Todo, Meta } from './models'
function useClickCount () {
const clickCount = ref(0)
function increment () {
clickCount.value += 1
return clickCount.value
}
return { clickCount, increment }
}
function useDisplayTodo (todos: Ref<Todo[]>) {
const todoCount = computed(() => todos.value.length)
return { todoCount }
}
export default defineComponent({
name: 'ExampleComponent',
props: {
title: {
type: String,
required: true
},
todos: {
type: Array as PropType<Todo[]>,
default: () => []
},
meta: {
type: Object as PropType<Meta>,
required: true
},
active: {
type: Boolean
}
},
setup (props) {
return { ...useClickCount(), ...useDisplayTodo(toRef(props, 'todos')) }
}
})
</script>

View file

@ -1,88 +1,155 @@
import appRoot from 'app-root-path'
import { _electron as electron } from 'playwright' import { _electron as electron } from 'playwright'
import { test, expect } from '@playwright/test' import { test, expect } from '@playwright/test'
import { extraEnvVariablesAPI } from 'app/src-electron/customContentBridgeAPIs/extraEnvVariablesAPI'
const electronMainFilePath = appRoot + '/dist/electron/UnPackaged/electron-main.js' /**
const faFrontendRenderTimer = 1000 * Extra env settings too trigger component testing via Playwright
*/
const extraEnvSettings = {
TEST_ENV: 'components',
COMPONENT_NAME: 'GlobalWindowButtons'
}
/**
* Electron main filepath
*/
const electronMainFilePath:string = extraEnvVariablesAPI.ELECTRON_MAIN_FILEPATH
/**
* Extra rended timer buffer for tests to start after loading the app
* - Change here in order manually adjust this component's wait times
*/
const faFrontendRenderTimer:number = extraEnvVariablesAPI.FA_FRONTEND_RENDER_TIMER
/**
* Object of string data selectors for the component
*/
const selectorList = {
buttonMinimize: 'globalWindowButtons-button-minimize',
buttonResize: 'globalWindowButtons-button-resize',
buttonClose: 'globalWindowButtons-button-close'
}
/**
* Test if the Electron launches to begin with.
*/
test('Should launch app', async () => {
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
test('launch app', async () => {
const electronApp = await electron.launch({ args: [electronMainFilePath] })
// close app
await electronApp.close() await electronApp.close()
}) })
test('click resize button - smallify', async () => { /**
const electronApp = await electron.launch({ args: [electronMainFilePath] }) * Attempt to click the resize button
*/
test('Click resize button - "smallify"', async () => {
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow() const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer) await appWindow.waitForTimeout(faFrontendRenderTimer)
const resizeButton = await appWindow.$('.globalWindowButtons__resize') const resizeButton = await appWindow.$(`[data-test="${selectorList.buttonResize}"]`)
if (resizeButton !== null) { if (resizeButton !== null) {
await resizeButton.click() await resizeButton.click()
const isMaximized = await appWindow.evaluate(() => window.faWindowControlAPI.checkWindowMaximized()) const isMaximized = await appWindow.evaluate(() => window.faWindowControlAPI.checkWindowMaximized())
expect(isMaximized).toBe(false) expect(isMaximized).toBe(false)
} else { } else {
test.fail() test.fail()
} }
// close app
await electronApp.close() await electronApp.close()
}) })
test('click resize button - maximize', async () => { /**
const electronApp = await electron.launch({ args: [electronMainFilePath] }) * Attempt to click the resize button, twice
*/
test('Click resize button - "maximize"', async () => {
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow() const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer) await appWindow.waitForTimeout(faFrontendRenderTimer)
const resizeButton = await appWindow.$('.globalWindowButtons__resize') const resizeButton = await appWindow.$(`[data-test="${selectorList.buttonResize}"]`)
if (resizeButton !== null) { if (resizeButton !== null) {
// Click twice
await resizeButton.click() await resizeButton.click()
await resizeButton.click() await resizeButton.click()
const isMaximized = await appWindow.evaluate(() => window.faWindowControlAPI.checkWindowMaximized()) const isMaximized = await appWindow.evaluate(() => window.faWindowControlAPI.checkWindowMaximized())
expect(isMaximized).toBe(true) expect(isMaximized).toBe(true)
} else { } else {
test.fail() test.fail()
} }
// close app
await electronApp.close() await electronApp.close()
}) })
test('click minimize button', async () => { /**
const electronApp = await electron.launch({ args: [electronMainFilePath] }) * Attempt to click the minimize button
*/
test('Click minimize button', async () => {
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow() const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer) await appWindow.waitForTimeout(faFrontendRenderTimer)
const minimizeButton = await appWindow.$('.globalWindowButtons__minimize') const minimizeButton = await appWindow.$(`[data-test="${selectorList.buttonMinimize}"]`)
if (minimizeButton !== null) { if (minimizeButton !== null) {
await minimizeButton.click() await minimizeButton.click()
const isMaximized = await appWindow.evaluate(() => window.faWindowControlAPI.checkWindowMaximized()) const isMaximized = await appWindow.evaluate(() => window.faWindowControlAPI.checkWindowMaximized())
expect(isMaximized).toBe(false) expect(isMaximized).toBe(false)
} else { } else {
test.fail() test.fail()
} }
// close app
await electronApp.close() await electronApp.close()
}) })
/* This test can VERY occasionally fail when the window takes too long to close on weaker PCs. Simply rerunning the tests generally fixes this. */ /**
test('click close button', async () => { * Attempt to click the close button
const electronApp = await electron.launch({ args: [electronMainFilePath] }) * - This test can VERY occasionally fail when the window takes too long to close on weaker PCs. Simply rerunning the tests generally fixes this.
*/
test('Click close button', async () => {
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow() const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer) await appWindow.waitForTimeout(faFrontendRenderTimer)
const closeButton = await appWindow.$('.globalWindowButtons__close') const closeButton = await appWindow.$(`[data-test="${selectorList.buttonClose}"]`)
if (closeButton !== null) { if (closeButton !== null) {
let windowIsClosed = false let windowIsClosed = false
// Listen to window close event
appWindow.on('close', () => { appWindow.on('close', () => {
windowIsClosed = true windowIsClosed = true
}) })
await closeButton.click() await closeButton.click()
expect(windowIsClosed).toBe(true) expect(windowIsClosed).toBe(true)
} else { } else {
test.fail() test.fail()

View file

@ -5,24 +5,61 @@ import GlobalWindowButtons from './GlobalWindowButtons.vue'
installQuasar() installQuasar()
describe('Unit test - GlobalWindowButtons component', () => { describe('Component - "GlobalWindowButtons"', () => {
it('should mount three buttons', () => { /**
* Object of string data selectors for the component
*/
const selectorList = {
buttonMinimize: 'globalWindowButtons-button-minimize',
buttonResize: 'globalWindowButtons-button-resize',
buttonClose: 'globalWindowButtons-button-close'
}
/**
* Test if the component has three specific HTML element buttons properly mounted in it:
* - Minimize button
* - Resize button
* - Close button
*/
it('Wrapper should contain three buttons', () => {
const wrapper = mount(GlobalWindowButtons) const wrapper = mount(GlobalWindowButtons)
expect(wrapper.findAll('.q-btn')).toHaveLength(3)
const buttonList = []
buttonList.push(wrapper.get(`[data-test="${selectorList.buttonMinimize}"]`))
buttonList.push(wrapper.get(`[data-test="${selectorList.buttonResize}"]`))
buttonList.push(wrapper.get(`[data-test="${selectorList.buttonClose}"]`))
expect(buttonList).toHaveLength(3)
}) })
it('should have `minimize` button', () => { /**
* Test if the component has a specific HTML element button properly mounted in it.
* - Minimize button
*/
it('Wrapper should contain "minimize" button', () => {
const wrapper = mount(GlobalWindowButtons) const wrapper = mount(GlobalWindowButtons)
expect(wrapper.findAll('.globalWindowButtons__minimize')).toHaveLength(1)
expect(wrapper.get(`[data-test="${selectorList.buttonMinimize}"]`))
}) })
it('should have `resize` button', () => { /**
* Test if the component has a specific HTML element button properly mounted in it.
* - Resize button
*/
it('Wrapper should contain "resize" button', () => {
const wrapper = mount(GlobalWindowButtons) const wrapper = mount(GlobalWindowButtons)
expect(wrapper.findAll('.globalWindowButtons__minimize')).toHaveLength(1)
expect(wrapper.get(`[data-test="${selectorList.buttonResize}"]`))
}) })
it('should have `close` button', () => { /**
* Test if the component has a specific HTML element button properly mounted in it.
* - Close button
*/
it('Wrapper should contain "close" button', () => {
const wrapper = mount(GlobalWindowButtons) const wrapper = mount(GlobalWindowButtons)
expect(wrapper.findAll('.globalWindowButtons__minimize')).toHaveLength(1)
expect(wrapper.get(`[data-test="${selectorList.buttonClose}"]`))
}) })
}) })

View file

@ -11,13 +11,14 @@
dark dark
size="xs" size="xs"
class="globalWindowButtons__minimize" class="globalWindowButtons__minimize"
data-test="globalWindowButtons-button-minimize"
@click="minimizeWindow()" @click="minimizeWindow()"
> >
<q-tooltip <q-tooltip
:delay="1000" :delay="1000"
:offset="[0, 5]" :offset="[0, 5]"
> >
{{ $t('globalWindowButtons_minimizeButton') }} {{ $t('GlobalWindowButtons.minimizeButton') }}
</q-tooltip> </q-tooltip>
<q-icon name="mdi-window-minimize" /> <q-icon name="mdi-window-minimize" />
</q-btn> </q-btn>
@ -29,13 +30,14 @@
dark dark
size="xs" size="xs"
class="globalWindowButtons__resize" class="globalWindowButtons__resize"
data-test="globalWindowButtons-button-resize"
@click="[resizeWindow(),checkIfWindowMaximized()]" @click="[resizeWindow(),checkIfWindowMaximized()]"
> >
<q-tooltip <q-tooltip
:delay="1000" :delay="1000"
:offset="[0, 5]" :offset="[0, 5]"
> >
{{ isMaximized ? $t('globalWindowButtons_resizeButton') : $t('globalWindowButtons_maximizeButton') }} {{ isMaximized ? $t('GlobalWindowButtons.resizeButton') : $t('GlobalWindowButtons.maximizeButton') }}
</q-tooltip> </q-tooltip>
<q-icon :name="(isMaximized)? 'mdi-window-restore' : 'mdi-window-maximize'" /> <q-icon :name="(isMaximized)? 'mdi-window-restore' : 'mdi-window-maximize'" />
</q-btn> </q-btn>
@ -47,13 +49,14 @@
dark dark
size="xs" size="xs"
class="globalWindowButtons__close" class="globalWindowButtons__close"
data-test="globalWindowButtons-button-close"
@click="tryCloseWindow()" @click="tryCloseWindow()"
> >
<q-tooltip <q-tooltip
:delay="1000" :delay="1000"
:offset="[0, 5]" :offset="[0, 5]"
> >
{{ $t('globalWindowButtons_close') }} {{ $t('GlobalWindowButtons.close') }}
</q-tooltip> </q-tooltip>
<q-icon name="mdi-window-close" /> <q-icon name="mdi-window-close" />
</q-btn> </q-btn>
@ -64,33 +67,34 @@
import { onMounted, ref } from 'vue' import { onMounted, ref } from 'vue'
import type { Ref } from 'vue' import type { Ref } from 'vue'
/* /**
Triggers minimize of the window by the minimize button click * Triggers minimize of the window by the minimize button click
*/ */
const minimizeWindow = () => { const minimizeWindow = () => {
console.log(process.env.MODE)
if (process.env.MODE === 'electron') { if (process.env.MODE === 'electron') {
window.faWindowControlAPI.minimizeWindow() window.faWindowControlAPI.minimizeWindow()
} }
} }
/* /**
Triggers resize of the window by the min/max button click * Triggers resize of the window by the min/max button click
*/ */
const resizeWindow = () => { const resizeWindow = () => {
if (process.env.MODE === 'electron') { if (process.env.MODE === 'electron') {
window.faWindowControlAPI.resizeWindow() window.faWindowControlAPI.resizeWindow()
} }
} }
/* /**
Triggers checking of the current app state by the close button click * Triggers checking of the current app state by the close button click.
This functionality checks the following: * This functionality checks the following:
1. If the app has any projects opened to begin with at the moment
2. If the project has any pending chnages to it * 1. If the app has any projects opened to begin with at the moment
If both is found to be true, then an appropriate dialog is opened * 2. If the project has any pending chnages to it
Otherwise, the app simply closes
*/ * If both is found to be true, then an appropriate dialog is opened.
* Otherwise, the app simply closes.
*/
const tryCloseWindow = () => { const tryCloseWindow = () => {
// TODO add project close checking // TODO add project close checking
if (process.env.MODE === 'electron') { if (process.env.MODE === 'electron') {
@ -98,8 +102,8 @@ const tryCloseWindow = () => {
} }
} }
/* /**
Checks if the window is maximized and sets local ref Checks if the window is maximized and sets local variable accordingly
*/ */
const checkIfWindowMaximized = () => { const checkIfWindowMaximized = () => {
if (process.env.MODE === 'electron') { if (process.env.MODE === 'electron') {
@ -107,14 +111,14 @@ const checkIfWindowMaximized = () => {
} }
} }
/* /**
Determines if the window is currently maximized or not * Determines if the window is currently maximized or not
*/ */
const isMaximized: Ref<boolean> = ref(false) const isMaximized: Ref<boolean> = ref(false)
/* /**
Check on component mount if the windows if maximized or not * Check on component mount if the windows if maximized or not
*/ */
onMounted(() => { onMounted(() => {
checkIfWindowMaximized() checkIfWindowMaximized()
}) })

View file

@ -1,8 +0,0 @@
export interface Todo {
id: number;
content: string;
}
export interface Meta {
totalCount: number;
}

4
src/globals.d.ts vendored
View file

@ -1,9 +1,11 @@
import { I_faWindowControlAPI } from './interfaces/I_faWindowControlAPI' import { I_faWindowControlAPI } from './interfaces/I_faWindowControlAPI'
import { I_extraEnvVariablesAPI } from './interfaces/I_extraEnvVariablesAPI'
export {} export {}
declare global{ declare global{
interface Window { interface Window {
faWindowControlAPI: I_faWindowControlAPI faWindowControlAPI: I_faWindowControlAPI,
extraEnvVariables: I_extraEnvVariablesAPI
} }
} }

View file

@ -1,6 +1,14 @@
// This is just an example,
// so you can safely delete all default props below
export default { export default {
appName: 'FA - but in german!' // GLOBAL - APP TEXTS
app: {
name: 'FA - but in german!'
},
// COMPONENT - GLOBAL WINDOW BUTTONS
GlobalWindowButtons: {
minimizeButton: 'Minimize',
resizeButton: 'Resize Down',
maximizeButton: 'Maximize',
close: 'Close'
}
} }

View file

@ -1,12 +1,14 @@
// This is just an example,
// so you can safely delete all default props below
export default { export default {
appName: 'FA - but in english!', // GLOBAL - APP TEXTS
app: {
name: 'FA - but in english!'
},
// COMPONENT - GLOBAL WINDOW BUTTONS // COMPONENT - GLOBAL WINDOW BUTTONS
globalWindowButtons_minimizeButton: 'Minimize', GlobalWindowButtons: {
globalWindowButtons_resizeButton: 'Resize Down', minimizeButton: 'Minimize',
globalWindowButtons_maximizeButton: 'Maximize', resizeButton: 'Resize Down',
globalWindowButtons_close: 'Close' maximizeButton: 'Maximize',
close: 'Close'
}
} }

View file

@ -0,0 +1,27 @@
export interface I_extraEnvVariablesAPI {
/**
* Full path to "electron-main.js" file in the dist, unpackaged form
*/
ELECTRON_MAIN_FILEPATH: string
/**
* Extra rended timer buffer for tests to start after loading the app.
* - Increase if your machine isn't keeping up with the render times and tests are randomly failing.
* - Lower if your machine is quick and the tests are waiting for no reason at all.
* - Can be set manually for each component/e2e test inside the test file.
*/
FA_FRONTEND_RENDER_TIMER: number
/**
* Type of test environment to load.
*/
TEST_ENV?: 'components'|'e2e'|false
/**
* Name of the component being tested.
* - MUST match the file name of the vue file being tested (including the capital letter at the start).
*/
COMPONENT_NAME?: string|false
}

View file

@ -1,6 +1,25 @@
export interface I_faWindowControlAPI { export interface I_faWindowControlAPI {
/**
* Check the current visual sizing of the current window
*/
checkWindowMaximized: () => boolean checkWindowMaximized: () => boolean
/**
* Minimizes the current window
*/
minimizeWindow: () => void minimizeWindow: () => void
/**
* Resizes the current window.
* - If the window is maximized, smallifies it
* - If the window is smallified, maximizes it
*/
resizeWindow: () => void resizeWindow: () => void
/**
* Closes the current window
*/
closeWindow: () => void closeWindow: () => void
} }

View file

@ -0,0 +1,15 @@
<template>
<q-layout>
<q-page-container>
<router-view :key="$route.path" />
</q-page-container>
</q-layout>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'ComponentTestingLayout'
})
</script>

View file

@ -13,7 +13,7 @@
/> />
<q-toolbar-title> <q-toolbar-title>
{{ $t('appName') }} {{ $t('app.name') }}
</q-toolbar-title> </q-toolbar-title>
<div>Quasar v{{ $q.version }}</div> <div>Quasar v{{ $q.version }}</div>
@ -31,12 +31,6 @@
> >
Essential Links Essential Links
</q-item-label> </q-item-label>
<EssentialLink
v-for="link in essentialLinks"
:key="link.title"
v-bind="link"
/>
</q-list> </q-list>
</q-drawer> </q-drawer>
@ -48,58 +42,12 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, ref } from 'vue' import { defineComponent, ref } from 'vue'
import EssentialLink from 'components/EssentialLink.vue'
import GlobalWindowButtons from 'components/GlobalWindowButtons/GlobalWindowButtons.vue' import GlobalWindowButtons from 'components/GlobalWindowButtons/GlobalWindowButtons.vue'
const linksList = [
{
title: 'Docs',
caption: 'quasar.dev',
icon: 'school',
link: 'https://quasar.dev'
},
{
title: 'Github',
caption: 'github.com/quasarframework',
icon: 'code',
link: 'https://github.com/quasarframework'
},
{
title: 'Discord Chat Channel',
caption: 'chat.quasar.dev',
icon: 'chat',
link: 'https://chat.quasar.dev'
},
{
title: 'Forum',
caption: 'forum.quasar.dev',
icon: 'record_voice_over',
link: 'https://forum.quasar.dev'
},
{
title: 'Twitter',
caption: '@quasarframework',
icon: 'rss_feed',
link: 'https://twitter.quasar.dev'
},
{
title: 'Facebook',
caption: '@QuasarFramework',
icon: 'public',
link: 'https://facebook.quasar.dev'
},
{
title: 'Quasar Awesome',
caption: 'Community Quasar projects',
icon: 'favorite',
link: 'https://awesome.quasar.dev'
}
]
export default defineComponent({ export default defineComponent({
name: 'MainLayout', name: 'MainLayout',
components: { components: {
EssentialLink,
GlobalWindowButtons GlobalWindowButtons
}, },
@ -107,7 +55,6 @@ export default defineComponent({
const leftDrawerOpen = ref(false) const leftDrawerOpen = ref(false)
return { return {
essentialLinks: linksList,
leftDrawerOpen, leftDrawerOpen,
toggleLeftDrawer () { toggleLeftDrawer () {
leftDrawerOpen.value = !leftDrawerOpen.value leftDrawerOpen.value = !leftDrawerOpen.value

View file

@ -0,0 +1,47 @@
<template>
<q-page class="row items-center justify-evenly">
<component :is="currentComponent" />
</q-page>
</template>
<script lang="ts" setup>
import { useRoute } from 'vue-router'
/**
* Current route
*/
const route = useRoute()
/**
* Currently tested component's name based on the last part of the route
*/
const componentName = route.params.componentName
/**
* Auto-import all components from the automatic matching via the route path
*/
const componentList = import.meta.globEager('components/**/*.vue')
/**
* Placeholder variable for the matched component
*/
let currentComponent = null as unknown
/**
* Loops through the component list
*/
for (const loopPath in componentList) {
/**
* Current component from the loop
*/
const loopComponent = componentList[loopPath].default
/**
* If the route-component-name matches the name of component in the loop, load it as the curently displayed one
*/
if (loopComponent.__name === componentName) {
currentComponent = loopComponent
}
}
</script>

View file

@ -1,49 +1,12 @@
<template> <template>
<q-page class="row items-center justify-evenly"> <q-page class="row items-center justify-evenly" />
<example-component
title="Example component"
active
:todos="todos"
:meta="meta"
/>
</q-page>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Todo, Meta } from 'components/models' import { defineComponent } from 'vue'
import ExampleComponent from 'components/ExampleComponent.vue'
import { defineComponent, ref } from 'vue'
export default defineComponent({ export default defineComponent({
name: 'IndexPage', name: 'IndexPage',
components: { ExampleComponent }, components: {}
setup () {
const todos = ref<Todo[]>([
{
id: 1,
content: 'ct1'
},
{
id: 2,
content: 'ct2'
},
{
id: 3,
content: 'ct3'
},
{
id: 4,
content: 'ct4'
},
{
id: 5,
content: 'ct5'
}
])
const meta = ref<Meta>({
totalCount: 1200
})
return { todos, meta }
}
}) })
</script> </script>

View file

@ -1,14 +1,30 @@
import { RouteRecordRaw } from 'vue-router' import { RouteRecordRaw } from 'vue-router'
const routes: RouteRecordRaw[] = [ const routes: RouteRecordRaw[] = [
/**
* Default pathing
*/
{ {
path: '/', path: '/',
component: () => import('layouts/MainLayout.vue'), component: () => import('layouts/MainLayout.vue'),
children: [{ path: '', component: () => import('pages/IndexPage.vue') }] children: [{ path: '', component: () => import('pages/IndexPage.vue') }]
}, },
// Always leave this as last one, /**
// but you can also remove it * Component testing pathing
*/
{
path: '/componentTesting/:componentName',
component: () => import('layouts/ComponentTestingLayout.vue'),
children: [
{ path: '', component: () => import('pages/ComponentTesting.vue') }
]
},
/**
* Always leave this as last one, but you can also remove it
*/
{ {
path: '/:catchAll(.*)*', path: '/:catchAll(.*)*',
component: () => import('pages/ErrorNotFound.vue') component: () => import('pages/ErrorNotFound.vue')

View file

@ -1,90 +0,0 @@
import appRoot from 'app-root-path'
import { _electron as electron } from 'playwright'
import { test, expect } from '@playwright/test'
const electronMainFilePath = appRoot + '/dist/electron/UnPackaged/electron-main.js'
const faFrontendRenderTimer = 1000
test('launch app', async () => {
const electronApp = await electron.launch({ args: [electronMainFilePath] })
// close app
await electronApp.close()
})
test('click resize button - smallify', async () => {
const electronApp = await electron.launch({ args: [electronMainFilePath] })
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const resizeButton = await appWindow.$('.globalWindowButtons__resize')
if (resizeButton !== null) {
await resizeButton.click()
const isMaximized = await appWindow.evaluate(() => window.faWindowControlAPI.checkWindowMaximized())
expect(isMaximized).toBe(false)
} else {
test.fail()
}
// close app
await electronApp.close()
})
test('click resize button - maximize', async () => {
const electronApp = await electron.launch({ args: [electronMainFilePath] })
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const resizeButton = await appWindow.$('.globalWindowButtons__resize')
if (resizeButton !== null) {
await resizeButton.click()
await resizeButton.click()
const isMaximized = await appWindow.evaluate(() => window.faWindowControlAPI.checkWindowMaximized())
expect(isMaximized).toBe(true)
} else {
test.fail()
}
// close app
await electronApp.close()
})
test('click minimize button', async () => {
const electronApp = await electron.launch({ args: [electronMainFilePath] })
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const minimizeButton = await appWindow.$('.globalWindowButtons__minimize')
if (minimizeButton !== null) {
await minimizeButton.click()
const isMaximized = await appWindow.evaluate(() => window.faWindowControlAPI.checkWindowMaximized())
expect(isMaximized).toBe(false)
} else {
test.fail()
}
// close app
await electronApp.close()
})
/* This test can VERY occasionally fail when the window takes too long to close on weaker PCs. Simply rerunning the tests generally fixes this. */
test('click close button', async () => {
const electronApp = await electron.launch({ args: [electronMainFilePath] })
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const closeButton = await appWindow.$('.globalWindowButtons__close')
if (closeButton !== null) {
let windowIsClosed = false
appWindow.on('close', () => {
windowIsClosed = true
})
await closeButton.click()
expect(windowIsClosed).toBe(true)
} else {
test.fail()
}
})

View file

@ -0,0 +1 @@
// TODO ADD SOME TESTS