revorked vitest to playwright tests, multiple fixes

This commit is contained in:
Elvanos 2023-10-30 00:40:55 +01:00
parent 5297953ac0
commit 0f952a6dce
21 changed files with 689 additions and 731 deletions

View file

@ -34,15 +34,6 @@ quasar build
### Testing:
#### Unit test - with pretty web-UI
```
test:unit:ui
```
#### Unit test - Without any UI, fully in a terminal
```
test:unit:ci
```
#### Component test - via Playwright
```
test:component

View file

@ -9,8 +9,6 @@
"lint": "eslint --ext .js,.ts,.vue ./",
"dev:electron": "quasar dev -m electron",
"build": "quasar build -m electron --publish never",
"test:unit:ui": "vitest --ui",
"test:unit:ci": "vitest run --reporter verbose",
"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/"
},
@ -30,19 +28,14 @@
},
"devDependencies": {
"@intlify/vite-plugin-vue-i18n": "^3.3.1",
"@pinia/testing": "^0.1.3",
"@playwright/test": "^1.37.1",
"@quasar/app-vite": "^1.3.0",
"@quasar/quasar-app-extension-qmarkdown": "^2.0.0-beta.10",
"@quasar/quasar-app-extension-testing": "^2.1.0",
"@quasar/quasar-app-extension-testing-unit-vitest": "^0.4.0",
"@types/lodash-es": "^4.17.10",
"@types/node": "^16.18.0",
"@types/uuid": "^9.0.5",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"@vitest/ui": "^0.15.0",
"@vue/test-utils": "^2.0.0",
"autoprefixer": "^10.4.2",
"electron": "^25.5.0",
"electron-builder": "^24.3.0",
@ -55,13 +48,12 @@
"jsdom": "^22.1.0",
"playwright": "^1.37.1",
"postcss-html": "^1.5.0",
"sass": "^1.69.0",
"sass": "1.29.0",
"stylelint": "^15.10.3",
"stylelint-config-standard": "^34.0.0",
"stylelint-config-standard-scss": "^11.0.0",
"stylelint-config-standard-vue": "^1.0.0",
"typescript": "^4.5.4",
"vitest": "^0.15.0"
"typescript": "^4.5.4"
},
"engines": {
"node": "^18 || ^16 || ^14.19",

View file

@ -1,6 +1,8 @@
import { defineConfig } from '@playwright/test'
export default defineConfig({
workers: 3,
fullyParallel: false,
testMatch: '**/*playwright.@(spec|test).?(c|m)[jt]s?(x)',
reporter: [
['list'],

View file

@ -1,17 +1,5 @@
{
"@quasar/testing": {
"harnesses": [
"unit-vitest@alpha"
]
},
"@quasar/testing-unit-vitest": {
"options": [
"scripts",
"typescript",
"ui"
]
},
"@quasar/qmarkdown": {
"import_md": true
}
}
}

View file

@ -1,5 +0,0 @@
{
"unit-vitest": {
"runnerCommand": "vitest run"
}
}

View file

@ -0,0 +1,79 @@
import { _electron as electron } from 'playwright'
import { test, expect } from '@playwright/test'
import { extraEnvVariablesAPI } from 'app/src-electron/customContentBridgeAPIs/extraEnvVariablesAPI'
/**
* Extra env settings to trigger component testing via Playwright
*/
const extraEnvSettings = {
TEST_ENV: 'components',
COMPONENT_NAME: 'AppControlMenus',
COMPONENT_PROPS: JSON.stringify({})
}
/**
* 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 = extraEnvVariablesAPI.FA_FRONTEND_RENDER_TIMER
/**
* Object of string data selectors for the component
*/
const selectorList = {
testMenu: 'appControlMenus-testMenu',
anyMenu: 'appControlMenus-anyMenu'
}
/**
* Load a custom "Test Title" menu button in the menu and check if it loaded
*/
test('Load "Test Title" menu button sub-component', async () => {
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const testMenu = await appWindow.$(`[data-test-test-menu="${selectorList.testMenu}"]`)
// Check if the tested element exists
if (testMenu !== null) {
await expect(true).toBe(true)
await electronApp.close()
} else {
// Element doesn't exist
test.fail()
}
})
/**
* Check if we have exactly one testing menu loaded
*/
test('Check if we have exactly one testing menu loaded', async () => {
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const anyMenus = await appWindow.$$(`[data-test-any-menu="${selectorList.anyMenu}"]`)
// Check for example one testing menu
if (anyMenus.length === 1) {
await expect(true).toBe(true)
await electronApp.close()
} else {
// No menus/too many menus
test.fail()
}
})

View file

@ -6,29 +6,57 @@
flat
class="appControlMenus__inner"
>
<!-- Project menu-->
<AppControlSingleMenu :data-input="project" />
<!-- Test data menu - FOR COMPOENT TEST PURPOSES ONLY -->
<AppControlSingleMenu
v-if="testingType === 'components'"
:data-input="testData"
data-test-test-menu="appControlMenus-testMenu"
data-test-any-menu="appControlMenus-anyMenu"
/>
<!-- Tools menu-->
<AppControlSingleMenu :data-input="tools" />
<!-- Project menu -->
<AppControlSingleMenu
v-if="testingType !== 'components'"
:data-input="project"
data-test-any-menu="appControlMenus-anyMenu"
/>
<!-- Help & Info Menu-->
<AppControlSingleMenu :data-input="helpInfo" />
<!-- Tools menu -->
<AppControlSingleMenu
v-if="testingType !== 'components'"
:data-input="tools"
data-test-any-menu="appControlMenus-anyMenu"
/>
<!-- Help & Info Menu -->
<AppControlSingleMenu
v-if="testingType !== 'components'"
:data-input="helpInfo"
data-test-any-menu="appControlMenus-anyMenu"
/>
</q-btn-group>
<!-- Dialog Popups -->
<DialogMarkdownDocument />
</div>
</template>
<script setup lang="ts">
import AppControlSingleMenu from 'src/components/AppControlMenus/AppControlSingleMenu/AppControlSingleMenu.vue'
import { testData } from 'app/src/components/AppControlMenus/_testData/test.raw.component'
import { project } from 'app/src/components/AppControlMenus/_data/project'
import { tools } from 'app/src/components/AppControlMenus/_data/tools'
import { helpInfo } from 'app/src/components/AppControlMenus/_data/helpInfo'
import AppControlSingleMenu from 'app/src/components/AppControlMenus/AppControlSingleMenu/AppControlSingleMenu.vue'
import DialogMarkdownDocument from 'app/src/components/DialogMarkdownDocument/DialogMarkdownDocument.vue'
/**
* Testing type currently possibly happening
*/
const testingType = window.extraEnvVariables.TEST_ENV
</script>
<style lang="scss" scoped>

View file

@ -0,0 +1,173 @@
import { _electron as electron } from 'playwright'
import { test, expect } from '@playwright/test'
import { extraEnvVariablesAPI } from 'app/src-electron/customContentBridgeAPIs/extraEnvVariablesAPI'
import { testData } from '../_testData/test.fixed.component'
/**
* Extra env settings to trigger component testing via Playwright
*/
const extraEnvSettings = {
TEST_ENV: 'components',
COMPONENT_NAME: 'AppControlSingleMenu',
COMPONENT_PROPS: JSON.stringify({})
}
/**
* 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 = extraEnvVariablesAPI.FA_FRONTEND_RENDER_TIMER
/**
* Object of string data selectors for the component
*/
const selectorList = {
menuWrapper: 'AppControlSingleMenu-wrapper',
menuTitle: 'AppControlSingleMenu-title',
menuItem: 'AppControlSingleMenu-menuItem',
menuItemText: 'AppControlSingleMenu-menuItem-text',
menuItemIcon: 'AppControlSingleMenu-menuItem-icon',
menuItemSubMenu: 'AppControlSingleMenu-menuItem-subMenu',
menuItemSubMenuItem: 'AppControlSingleMenu-menuItem-subMenu-item',
menuItemSubMenuItemText: 'AppControlSingleMenu-menuItem-subMenu-item-text',
menuItemSubMenuItemIcon: 'AppControlSingleMenu-menuItem-subMenu-item-icon'
}
/**
* Test if the component managed to load the test data
*/
test('Test if the component managed to load the test data', async () => {
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const menuWrapperElement = await appWindow.$(`[data-test="${selectorList.menuWrapper}"]`)
// Check if the tested element exists
if (menuWrapperElement !== null) {
const hasProperInput = await menuWrapperElement.evaluate(el => !!el.dataset.testHasProperDataInput)
await expect(hasProperInput).toBe(true)
await electronApp.close()
} else {
// Element doesn't exist
test.fail()
}
})
/**
* Load a custom "Test Title" menu button in the menu and check if it loaded
*/
test('Check if the "Menu title" element is properly loaded and has proper content in it', async () => {
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const menuTitleElement = await appWindow.$(`[data-test="${selectorList.menuTitle}"]`)
const menuTitleElementText = (menuTitleElement !== null) ? await menuTitleElement.textContent() : ''
// Check if the tested element exists and has proper title content
if (menuTitleElement !== null && menuTitleElementText === testData.title) {
await expect(true).toBe(true)
await electronApp.close()
} else {
// Element doesn't exist OR lacks proper title in it
test.fail()
}
})
/**
* Check if the menu opens properly on click and all parts are loaded properly
*/
test('Check if the menu has a wrapper, click if all menu elements loaded properly', async () => {
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const menuWrapper = await appWindow.$(`[data-test="${selectorList.menuWrapper}"]`)
// Check if wrapper exists for clicking and if so, click it
if (menuWrapper !== null) {
await menuWrapper.click()
const menuItems = await appWindow.$$(`[data-test="${selectorList.menuItem}"]`)
const dataItems = testData.data.filter(item => item.mode === 'item')
// Check if element feed matched the data feed
await expect(menuItems.length === dataItems.length).toBe(true)
await electronApp.close()
} else {
// Wrapper for opening the menu doesn't exist
test.fail()
}
})
// TODO add checking text color class!
/**
* Check if the first menu item has proper text and icon
*/
test('Check if the first menu item has proper text and icon', async () => {
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const menuWrapper = await appWindow.$(`[data-test="${selectorList.menuWrapper}"]`)
// Check if wrapper exists for clicking and if so, click it
if (menuWrapper !== null) {
await menuWrapper.click()
const firstMenuItem = await appWindow.$(`[data-test="${selectorList.menuItem}"]`)
const firstDataItem = testData.data.filter(item => item.mode === 'item')[0]
// Check if the item wrapper exists
if (firstMenuItem !== null) {
const firstMenuItemTextElement = await firstMenuItem.$(`[data-test="${selectorList.menuItemText}"]`)
const firstMenuItemIconElement = await firstMenuItem.$(`[data-test="${selectorList.menuItemIcon}"]`)
// Check if the icon and text wrappers exist
if (firstMenuItemTextElement !== null && firstMenuItemIconElement !== null) {
const firstMenuItemText = await firstMenuItemTextElement.textContent()
const firstDataItemText = firstDataItem.text
const firstMenuItemIconClassObject = await firstMenuItemIconElement.evaluate(el => el.classList)
const firstMenuItemIconClassList = Object.values(firstMenuItemIconClassObject).concat()
const firstDataItemIcon = firstDataItem.icon as string
await expect(firstMenuItemText === firstDataItemText && firstMenuItemIconClassList.includes(firstDataItemIcon)).toBe(true)
await electronApp.close()
} else {
// Item text or icon wrappers don't exist
test.fail()
}
} else {
// Item wrapper doesn't exist
test.fail()
}
} else {
// Wrapper for opening the menu doesn't exist
test.fail()
}
})

View file

@ -1,4 +1,5 @@
<template>
<!-- Main menu - Wrapper -->
<q-btn
v-if="hasProperDataInput"
flat
@ -6,10 +7,18 @@
dark
size="md"
no-caps
data-test="AppControlSingleMenu-wrapper"
:data-test-has-proper-data-input="hasProperDataInput"
>
{{ menuTitle }}
<!-- Main menu - Title -->
<span
v-if="menuTitle"
data-test="AppControlSingleMenu-title"
>
{{ menuTitle }}
</span>
<!-- Button menu-->
<!-- Main menu - Content -->
<q-menu
anchor="bottom left"
square
@ -35,6 +44,7 @@
v-if="menuItem.mode === 'item'"
v-close-popup="menuItem.submenu === undefined ? true : false"
clickable
data-test="AppControlSingleMenu-menuItem"
:class="['appControlSingleMenu__item', `text-${menuItem.specialColor}`, 'non-selectable']"
:disable="(!menuItem.conditions)"
@click="(menuItem.trigger)
@ -43,15 +53,18 @@
: menuItem.trigger()
: false"
>
<q-item-section>{{ menuItem.text }}</q-item-section>
<q-item-section data-test="AppControlSingleMenu-menuItem-text">
{{ menuItem.text }}
</q-item-section>
<q-item-section avatar>
<q-icon
class="appControlSingleMenu__icon"
:name="menuItem.icon"
data-test="AppControlSingleMenu-menuItem-icon"
/>
</q-item-section>
<!-- Sub-menu-->
<!-- Sub-menu -->
<q-menu
v-if="menuItem.submenu !== undefined"
anchor="top end"
@ -61,6 +74,7 @@
transition-show="jump-right"
transition-hide="jump-left"
class="-subMenu"
data-test="AppControlSingleMenu-menuItem-subMenu"
>
<q-list
class="appControlSingleMenu__list"
@ -81,12 +95,18 @@
clickable
:class="['appControlSingleMenu__item', `text-${submenuItem.specialColor}`, 'non-selectable']"
:disable="(!submenuItem.conditions)"
data-test="AppControlSingleMenu-menuItem-subMenu-item"
@click="(submenuItem.trigger) ? submenuItem.trigger() : false"
>
<q-item-section>{{ submenuItem.text }}</q-item-section>
<q-item-section
data-test="AppControlSingleMenu-menuItem-subMenu-item-text"
>
{{ submenuItem.text }}
</q-item-section>
<q-item-section avatar>
<q-icon
class="appControlSingleMenu__icon"
data-test="AppControlSingleMenu-menuItem-subMenu-item-icon"
:name="submenuItem.icon"
/>
</q-item-section>
@ -99,12 +119,17 @@
</template>
</q-list>
</q-menu>
<!-- Main menu end -->
<!-- Main menu end - Content -->
</q-btn>
<!-- Main menu end - Wrappper -->
</template>
<script setup lang="ts">
// TODO - ADD TESTS
import { I_appMenusDataList } from 'app/interfaces/I_appMenusDataList'
import { testData } from '../_testData/test.raw.component'
import { computed } from 'vue'
/**
* All component props
@ -116,23 +141,36 @@ const props = defineProps<{
dataInput: I_appMenusDataList
}>()
/**
* Testing type currently possibly happening
*/
const testingType = window.extraEnvVariables.TEST_ENV
const componentData = computed(() => {
if (testingType === 'components') {
return testData
} else {
return props.dataInput
}
})
/**
* Determines if the input has "proper" data in it
* Checks for:
* - Title
* - Overall data feed
*/
const hasProperDataInput = !!(props.dataInput.title && props.dataInput.data)
const hasProperDataInput = !!(componentData.value.title && componentData.value.data)
/**
* Menu title from the prop
*/
const menuTitle = props.dataInput.title
const menuTitle = componentData.value.title
/**
* Menu data content from the prop
*/
const menuData = props.dataInput.data
const menuData = componentData.value.data
</script>

View file

@ -110,7 +110,6 @@ export const project: I_appMenusDataList = {
specialColor: undefined
}
]
}
]
}

View file

@ -0,0 +1,93 @@
import { I_appMenusDataList } from 'app/interfaces/I_appMenusDataList'
export const testData:I_appMenusDataList = {
title: 'Test Title',
data: [
{
mode: 'item',
text: 'Test Button 1 - Open Dialog with Markdown document',
icon: 'mdi-text-box-plus-outline',
submenu: undefined,
trigger: undefined,
triggerArguments: ['changeLog'],
conditions: true,
specialColor: undefined
},
{
mode: 'item',
text: 'Test Button 2',
icon: 'mdi-database-search',
submenu: undefined,
trigger: undefined,
conditions: true,
specialColor: undefined
},
{
mode: 'separator'
},
{
mode: 'item',
text: 'Test Button 3 - Secondary',
icon: 'mdi-text-box-remove-outline',
submenu: undefined,
trigger: undefined,
conditions: true,
specialColor: 'secondary'
},
{
mode: 'separator'
},
{
mode: 'item',
text: 'Test Button 4',
icon: 'mdi-page-layout-sidebar-left',
submenu: undefined,
trigger: undefined,
conditions: true,
specialColor: undefined
},
{
mode: 'item',
text: 'Test Button 5',
icon: 'mdi-clipboard-text-outline',
submenu: undefined,
trigger: undefined,
conditions: true,
specialColor: undefined
},
{
mode: 'separator'
},
{
mode: 'item',
text: 'Test Button 6 - Grey, Submenu',
icon: 'keyboard_arrow_right',
trigger: undefined,
conditions: true,
specialColor: 'grey',
submenu: [
{
mode: 'item',
text: 'Submenu-Test Button 1',
icon: 'mdi-folder-plus-outline',
trigger: undefined,
conditions: true,
specialColor: undefined
},
{
mode: 'separator'
},
{
mode: 'item',
text: 'Submenu-Test Button 2 - Secondary',
icon: 'mdi-wrench',
trigger: undefined,
conditions: true,
specialColor: 'secondary'
}
]
}
]
}

View file

@ -0,0 +1,94 @@
import { I_appMenusDataList } from 'app/interfaces/I_appMenusDataList'
import { openDialogMarkdownDocument } from 'src/scripts/appInfo/openDialogMarkdownDocument'
export const testData:I_appMenusDataList = {
title: 'Test Title',
data: [
{
mode: 'item',
text: 'Test Button 1 - Open Dialog with Markdown document',
icon: 'mdi-text-box-plus-outline',
submenu: undefined,
trigger: openDialogMarkdownDocument,
triggerArguments: ['changeLog'],
conditions: true,
specialColor: undefined
},
{
mode: 'item',
text: 'Test Button 2',
icon: 'mdi-database-search',
submenu: undefined,
trigger: undefined,
conditions: true,
specialColor: undefined
},
{
mode: 'separator'
},
{
mode: 'item',
text: 'Test Button 3 - Secondary',
icon: 'mdi-text-box-remove-outline',
submenu: undefined,
trigger: undefined,
conditions: true,
specialColor: 'secondary'
},
{
mode: 'separator'
},
{
mode: 'item',
text: 'Test Button 4',
icon: 'mdi-page-layout-sidebar-left',
submenu: undefined,
trigger: undefined,
conditions: true,
specialColor: undefined
},
{
mode: 'item',
text: 'Test Button 5',
icon: 'mdi-clipboard-text-outline',
submenu: undefined,
trigger: undefined,
conditions: true,
specialColor: undefined
},
{
mode: 'separator'
},
{
mode: 'item',
text: 'Test Button 6 - Grey, Submenu',
icon: 'keyboard_arrow_right',
trigger: undefined,
conditions: true,
specialColor: 'grey',
submenu: [
{
mode: 'item',
text: 'Submenu-Test Button 1',
icon: 'mdi-folder-plus-outline',
trigger: undefined,
conditions: true,
specialColor: undefined
},
{
mode: 'separator'
},
{
mode: 'item',
text: 'Submenu-Test Button 2 - Secondary',
icon: 'mdi-wrench',
trigger: undefined,
conditions: true,
specialColor: 'secondary'
}
]
}
]
}

View file

@ -86,7 +86,8 @@ test('Open test "license" dialog and try closing it', async () => {
await appWindow.waitForTimeout(1500)
// Check if the content is properly hidden after closing the popup
expect(await markdownContent.isHidden()).toBe(true)
await expect(await markdownContent.isHidden()).toBe(true)
await electronApp.close()
} else {
// Close button doesn't exist
test.fail()

View file

@ -1,19 +0,0 @@
import { describe, it } from 'vitest'
describe('Component - "DialogMarkdownDocument"', () => {
/**
* Object of string data selectors for the component
*/
/*
const selectorList = {
markdown: 'dialogMarkdownDocument-markdown',
markdownWrapper: 'dialogMarkdownDocument-markdown-wrappers',
closeButton: 'dialogMarkdownDocument-button-close'
} */
/**
* Placeholder test due to incompatibility of unit vitest incompatibility with something in this component
* Actual testing moved to component tests
*/
it('Placeholder - Test runs! :o')
})

View file

@ -29,6 +29,36 @@ const selectorList = {
image: 'fantasiaMascotImage-image'
}
/**
* Check if the wrapper contains 'IMG' element
*/
test('Check if the wrapper contains "IMG" element', async () => {
const testString = 'IMG'
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const imageElement = await appWindow.$(`[data-test="${selectorList.image}"]`)
// Check if the tested element exists
if (imageElement !== null) {
const elementType = await imageElement.evaluate(el => el.tagName)
await expect(elementType).toBe(testString)
await electronApp.close()
} else {
// Element doesn't exist
test.fail()
}
await electronApp.close()
})
/**
* Attempt to pass "width" prop to the component and check the result
*/
@ -56,7 +86,8 @@ test('Visually check "width" prop', async () => {
const roundedFirstValue = Math.round(imageBoxData.width)
const roundedSecondValue = Math.round(parseInt(testString))
expect(roundedFirstValue).toBe(roundedSecondValue)
await expect(roundedFirstValue).toBe(roundedSecondValue)
await electronApp.close()
} else {
// Element is invisible
test.fail()
@ -96,7 +127,8 @@ test('Visually check "height" prop', async () => {
const roundedFirstValue = Math.round(imageBoxData.height)
const roundedSecondValue = Math.round(parseInt(testString))
expect(roundedFirstValue).toBe(roundedSecondValue)
await expect(roundedFirstValue).toBe(roundedSecondValue)
await electronApp.close()
} else {
// Element is invisible
test.fail()
@ -108,3 +140,65 @@ test('Visually check "height" prop', async () => {
await electronApp.close()
})
/**
* Test if the component properly determines if the image will be random - YES
*/
test('Check if the image is random: YES', async () => {
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const imageElement = await appWindow.$(`[data-test="${selectorList.image}"]`)
// Check if the tested element exists
if (imageElement !== null) {
const isRandom = await imageElement.evaluate(el => el.dataset.testIsRandom)
await expect(isRandom).toBe('true')
await electronApp.close()
} else {
// Element doesn't exist
test.fail()
}
await electronApp.close()
})
/**
* Test if the component properly determines if the image will be random - NO
*/
test('Check if the image is random: NO', async () => {
const testString = 'flop'
extraEnvSettings.COMPONENT_PROPS = JSON.stringify({ fantasiaImage: testString })
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const imageElement = await appWindow.$(`[data-test="${selectorList.image}"]`)
// Check if the tested element exists
if (imageElement !== null) {
const isRandom = await imageElement.evaluate(el => el.dataset.testIsRandom)
const imageString = await imageElement.evaluate(el => el.dataset.testImage)
await expect.soft(imageString).toBe(testString)
await expect(isRandom).toBe('false')
await electronApp.close()
} else {
// Element doesn't exist
test.fail()
}
await electronApp.close()
})

View file

@ -1,90 +0,0 @@
import { installQuasarPlugin } from '@quasar/quasar-app-extension-testing-unit-vitest'
import { mount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import FantasiaMascotImage from './FantasiaMascotImage.vue'
installQuasarPlugin()
describe('Component - "FantasiaMascotImage"', () => {
/**
* Object of string data selectors for the component
*/
const selectorList = {
image: 'fantasiaMascotImage-image'
}
/**
* Test if the component has an "img" HTML element properly mounted in it.
*/
it('Wrapper should contain an image', () => {
const wrapper = mount(FantasiaMascotImage)
const imageElement = wrapper.get(`[data-test="${selectorList.image}"]`).element
expect(imageElement.tagName).toBe('IMG')
})
/**
* Test if the "img" HTML element has received the "width" prop properly.
* - Testing via "dataset" instead of actual width due to Vitest limitations.
*/
it('Image inside wrapper should have 300px "width"', () => {
const testString = '300px'
const wrapper = mount(FantasiaMascotImage, {
props: {
width: testString
}
})
const imageElement = wrapper.get(`[data-test="${selectorList.image}"]`).element as HTMLImageElement
expect(imageElement.dataset.testWidth).toBe(testString)
})
/**
* Test if the "img" HTML element has received the "height" prop properly.
* - Testing via "dataset" instead of actual height due to Vitest limitations.
*/
it('Image inside wrapper should have 300px "height"', () => {
const testString = '300px'
const wrapper = mount(FantasiaMascotImage, {
props: {
height: testString
}
})
const imageElement = wrapper.get(`[data-test="${selectorList.image}"]`).element as HTMLImageElement
expect(imageElement.dataset.testHeight).toBe(testString)
})
/**
* Test if the component properly determines if the image will be random.
*/
it('Should generate random image URL', () => {
const wrapper = mount(FantasiaMascotImage)
const imageElement = wrapper.get(`[data-test="${selectorList.image}"]`).element as HTMLImageElement
expect(imageElement.dataset.testIsRandom).toBe('true')
})
/**
* Test if the component properly determines if the image will NOT be random.
*/
it('Should generate non-random image URL', () => {
const testString = 'flop'
const wrapper = mount(FantasiaMascotImage, {
props: {
fantasiaImage: testString
}
})
const imageElement = wrapper.get(`[data-test="${selectorList.image}"]`).element as HTMLImageElement
expect(imageElement.dataset.testIsRandom).toBe('false')
})
})

View file

@ -8,8 +8,7 @@
:src="currentMascotImage"
class="fantasiaMascotImage__inner"
data-test="fantasiaMascotImage-image"
:data-test-width="props.width"
:data-test-height="props.height"
:data-test-image="fantasiaImage"
:data-test-is-random="isRandom"
>
</div>

View file

@ -31,6 +31,37 @@ const selectorList = {
buttonClose: 'globalWindowButtons-button-close'
}
/**
* Test if the component has three specific HTML element buttons properly mounted in it:
* - Minimize button
* - Resize button
* - Close button
*/
test('Wrapper should contain three specific buttons', async () => {
const electronApp = await electron.launch({
env: extraEnvSettings,
args: [electronMainFilePath]
})
const appWindow = await electronApp.firstWindow()
await appWindow.waitForTimeout(faFrontendRenderTimer)
const resizeButton = await appWindow.$(`[data-test="${selectorList.buttonResize}"]`)
const minimizeButton = await appWindow.$(`[data-test="${selectorList.buttonMinimize}"]`)
const closeButton = await appWindow.$(`[data-test="${selectorList.buttonClose}"]`)
// Check if the tested elements exists
if (resizeButton !== null && minimizeButton !== null && closeButton !== null) {
await expect(true).toBe(true)
await electronApp.close()
} else {
// At least one of the tested elements doesn't exist
test.fail()
}
await electronApp.close()
})
/**
* Attempt to click the resize button
*/
@ -51,7 +82,8 @@ test('Click resize button - "smallify"', async () => {
const isMaximized = await appWindow.evaluate(() => window.faWindowControlAPI.checkWindowMaximized())
expect(isMaximized).toBe(false)
await expect(isMaximized).toBe(false)
await electronApp.close()
} else {
// Element doesn't exist
test.fail()
@ -82,14 +114,19 @@ test('Click resize button - "maximize"', async () => {
if (isMaximized) {
// Click twice
await resizeButton.click()
await appWindow.waitForTimeout(500)
await resizeButton.click()
} else {
await resizeButton.click()
}
await appWindow.waitForTimeout(500)
isMaximized = await appWindow.evaluate(() => window.faWindowControlAPI.checkWindowMaximized())
expect(isMaximized).toBe(true)
await expect(isMaximized).toBe(true)
await electronApp.close()
} else {
// Element doesn't exist
test.fail()
@ -118,7 +155,8 @@ test('Click minimize button', async () => {
const isMaximized = await appWindow.evaluate(() => window.faWindowControlAPI.checkWindowMaximized())
expect(isMaximized).toBe(false)
await expect(isMaximized).toBe(false)
await electronApp.close()
} else {
// Element doesn't exist
test.fail()
@ -153,7 +191,8 @@ test('Click close button', async () => {
await closeButton.click()
expect(windowIsClosed).toBe(true)
await expect(windowIsClosed).toBe(true)
await electronApp.close()
} else {
// Element doesn't exist
test.fail()

View file

@ -1,65 +0,0 @@
import { installQuasarPlugin } 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'
installQuasarPlugin()
describe('Component - "GlobalWindowButtons"', () => {
/**
* 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 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)
})
/**
* 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)
expect(wrapper.get(`[data-test="${selectorList.buttonMinimize}"]`))
})
/**
* 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)
expect(wrapper.get(`[data-test="${selectorList.buttonResize}"]`))
})
/**
* 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)
expect(wrapper.get(`[data-test="${selectorList.buttonClose}"]`))
})
})

View file

@ -1,25 +0,0 @@
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
import { quasar, transformAssetUrls } from '@quasar/vite-plugin'
import tsconfigPaths from 'vite-tsconfig-paths'
// https://vitejs.dev/config/
export default defineConfig({
test: {
environment: 'jsdom',
include: [
// Matches vitest tests in any subfolder of 'src' or into 'test/vitest/__tests__'
// Matches all files with extension 'js', 'jsx', 'ts' and 'tsx'
'src/**/*.vitest.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'
]
},
plugins: [
vue({
template: { transformAssetUrls }
}),
quasar({
sassVariables: 'src/quasar-variables.scss'
}),
tsconfigPaths()
]
})

490
yarn.lock
View file

@ -59,11 +59,6 @@
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-3.0.0.tgz#798622546b63847e82389e473fd67f2707d82247"
integrity sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==
"@cush/relative@^1.0.0":
version "1.0.0"
resolved "https://registry.npmjs.org/@cush/relative/-/relative-1.0.0.tgz"
integrity sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==
"@develar/schema-utils@~2.6.5":
version "2.6.5"
resolved "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz"
@ -257,38 +252,11 @@
"@intlify/core-base" "9.2.2"
"@intlify/shared" "9.2.2"
"@jridgewell/gen-mapping@^0.3.2":
version "0.3.3"
resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz"
integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==
dependencies:
"@jridgewell/set-array" "^1.0.1"
"@jridgewell/sourcemap-codec" "^1.4.10"
"@jridgewell/trace-mapping" "^0.3.9"
"@jridgewell/resolve-uri@^3.1.0":
version "3.1.1"
resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz"
integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
"@jridgewell/set-array@^1.0.1":
version "1.1.2"
resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz"
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15":
"@jridgewell/sourcemap-codec@^1.4.15":
version "1.4.15"
resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz"
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
"@jridgewell/trace-mapping@^0.3.9":
version "0.3.19"
resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz"
integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==
dependencies:
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"
"@malept/cross-spawn-promise@^1.1.0":
version "1.1.1"
resolved "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz"
@ -358,18 +326,6 @@
mkdirp "^1.0.4"
rimraf "^3.0.2"
"@one-ini/wasm@0.1.1":
version "0.1.1"
resolved "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz"
integrity sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==
"@pinia/testing@^0.1.3":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@pinia/testing/-/testing-0.1.3.tgz#ee46a5a51d437f845ddc9c7b048c98b6a435e68b"
integrity sha512-D2Ds2s69kKFaRf2KCcP1NhNZEg5+we59aRyQalwRm7ygWfLM25nDH66267U3hNvRUOTx8ofL24GzodZkOmB5xw==
dependencies:
vue-demi ">=0.14.5"
"@playwright/test@^1.37.1":
version "1.37.1"
resolved "https://registry.npmjs.org/@playwright/test/-/test-1.37.1.tgz"
@ -380,11 +336,6 @@
optionalDependencies:
fsevents "2.3.2"
"@polka/url@^1.0.0-next.20":
version "1.0.0-next.21"
resolved "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz"
integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==
"@quasar/app-vite@^1.3.0":
version "1.4.7"
resolved "https://registry.npmjs.org/@quasar/app-vite/-/app-vite-1.4.7.tgz"
@ -449,25 +400,6 @@
raw-loader "^4.0.2"
webpack-merge "^5.8.0"
"@quasar/quasar-app-extension-testing-unit-vitest@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@quasar/quasar-app-extension-testing-unit-vitest/-/quasar-app-extension-testing-unit-vitest-0.4.0.tgz#d5cb651ac2f17154de6f9499f5205c9632490ad2"
integrity sha512-eyzdUdmZiCueNS+5nedjMmzdbpCetSrtdGIwW6KplW1dTzRbLiNvYUjpBOxQGmJCgEhWy9zuswJ7MZ/bTql24Q==
dependencies:
happy-dom "^11.0.6"
lodash-es "^4.17.21"
vite-jsconfig-paths "^2.0.1"
vite-tsconfig-paths "^4.2.1"
"@quasar/quasar-app-extension-testing@^2.1.0":
version "2.1.1"
resolved "https://registry.npmjs.org/@quasar/quasar-app-extension-testing/-/quasar-app-extension-testing-2.1.1.tgz"
integrity sha512-OyvbOI5fA7D3gQoNJCmKC960YWz763nqVs4lz/QJfABRLUP/Ce7Du+dOdyKbWE8gJN1gAtRF7Z3untIWryy6Mw==
dependencies:
chalk "^4.1.1"
execa "^5.1.1"
strip-ansi "^6.0.0"
"@quasar/quasar-ui-qmarkdown@^2.0.0-beta.10":
version "2.0.0-beta.10"
resolved "https://registry.yarnpkg.com/@quasar/quasar-ui-qmarkdown/-/quasar-ui-qmarkdown-2.0.0-beta.10.tgz#c4ee74f7f69fb0465a1a73ffa60bfe59a3976894"
@ -540,18 +472,6 @@
"@types/node" "*"
"@types/responselike" "^1.0.0"
"@types/chai-subset@^1.3.3":
version "1.3.3"
resolved "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz"
integrity sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==
dependencies:
"@types/chai" "*"
"@types/chai@*", "@types/chai@^4.3.1":
version "4.3.5"
resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz"
integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==
"@types/chrome@^0.0.208":
version "0.0.208"
resolved "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.208.tgz"
@ -885,13 +805,6 @@
resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.4.tgz"
integrity sha512-IfFNbtkbIm36O9KB8QodlwwYvTEsJb4Lll4c2IwB3VHc2gie2mSPtSzL0eYay7X2jd/2WX02FjSGTWR6OPr/zg==
"@vitest/ui@^0.15.0":
version "0.15.2"
resolved "https://registry.npmjs.org/@vitest/ui/-/ui-0.15.2.tgz"
integrity sha512-0L5Hhk7j6MPkMK3WONpbCLRFlbOZC8w/C5/LAU66iSBhahg3nJOXNuSxnr+l0KFNKYf10SNlZZ/E2H1vb2s7WQ==
dependencies:
sirv "^2.0.2"
"@vue/compiler-core@3.3.4":
version "3.3.4"
resolved "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz"
@ -987,14 +900,6 @@
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz"
integrity sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==
"@vue/test-utils@^2.0.0":
version "2.4.1"
resolved "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.1.tgz"
integrity sha512-VO8nragneNzUZUah6kOjiFmD/gwRjUauG9DROh6oaOeFwX1cZRUNHhdeogE8635cISigXFTtGLUQWx5KCb0xeg==
dependencies:
js-beautify "1.14.9"
vue-component-type-helpers "1.8.4"
"@xmldom/xmldom@^0.8.8":
version "0.8.10"
resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz"
@ -1005,7 +910,7 @@ abab@^2.0.6:
resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz"
integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==
abbrev@1, abbrev@^1.0.0:
abbrev@1:
version "1.1.1"
resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz"
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
@ -1106,11 +1011,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
any-promise@^1.0.0:
version "1.3.0"
resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz"
integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==
anymatch@~3.1.2:
version "3.1.3"
resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz"
@ -1307,11 +1207,6 @@ assert-plus@^1.0.0:
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==
assertion-error@^1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz"
integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
astral-regex@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz"
@ -1622,19 +1517,6 @@ caniuse-lite@^1.0.30001517, caniuse-lite@^1.0.30001520:
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001525.tgz"
integrity sha512-/3z+wB4icFt3r0USMwxujAqRvaD/B7rvGTsKhbhSQErVrJvkZCLhgNLJxU8MevahQVH6hCU9FsHdNUFbiwmE7Q==
chai@^4.3.6:
version "4.3.8"
resolved "https://registry.npmjs.org/chai/-/chai-4.3.8.tgz"
integrity sha512-vX4YvVVtxlfSZ2VecZgFUTU5qPCYsobVI2O9FmwEXBhDigYGQA6jRXCycIs1yJnnWbZ6/+a2zNIF5DfVCcJBFQ==
dependencies:
assertion-error "^1.1.0"
check-error "^1.0.2"
deep-eql "^4.1.2"
get-func-name "^2.0.0"
loupe "^2.3.1"
pathval "^1.1.1"
type-detect "^4.0.5"
chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
@ -1657,12 +1539,7 @@ chardet@^0.7.0:
resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz"
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
check-error@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz"
integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==
"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3:
"chokidar@>=2.0.0 <4.0.0", "chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3:
version "3.5.3"
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz"
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
@ -1805,21 +1682,11 @@ combined-stream@^1.0.8:
dependencies:
delayed-stream "~1.0.0"
commander@^10.0.0:
version "10.0.1"
resolved "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz"
integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
commander@^2.19.0:
version "2.20.3"
resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
commander@^4.0.0:
version "4.1.1"
resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz"
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
commander@^5.0.0:
version "5.1.0"
resolved "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz"
@ -1865,14 +1732,6 @@ concat-map@0.0.1:
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
config-chain@^1.1.13:
version "1.1.13"
resolved "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz"
integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==
dependencies:
ini "^1.3.4"
proto-list "~1.2.1"
config-file-ts@^0.2.4:
version "0.2.4"
resolved "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.4.tgz"
@ -1970,11 +1829,6 @@ css-tree@^2.3.1:
mdn-data "2.0.30"
source-map-js "^1.0.1"
css.escape@^1.5.1:
version "1.5.1"
resolved "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz"
integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==
cssesc@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz"
@ -2052,13 +1906,6 @@ decompress-response@^6.0.0:
dependencies:
mimic-response "^3.1.0"
deep-eql@^4.1.2:
version "4.1.3"
resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz"
integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==
dependencies:
type-detect "^4.0.0"
deep-is@^0.1.3:
version "0.1.4"
resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz"
@ -2230,16 +2077,6 @@ dotenv@^9.0.2:
resolved "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz"
integrity sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==
editorconfig@^1.0.3:
version "1.0.4"
resolved "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz"
integrity sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==
dependencies:
"@one-ini/wasm" "0.1.1"
commander "^10.0.0"
minimatch "9.0.1"
semver "^7.5.3"
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz"
@ -2332,7 +2169,7 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1:
dependencies:
once "^1.4.0"
entities@^4.2.0, entities@^4.4.0, entities@^4.5.0:
entities@^4.2.0, entities@^4.4.0:
version "4.5.0"
resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
@ -2941,21 +2778,6 @@ etag@~1.8.1:
resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz"
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
execa@^5.1.1:
version "5.1.1"
resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz"
integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
dependencies:
cross-spawn "^7.0.3"
get-stream "^6.0.0"
human-signals "^2.1.0"
is-stream "^2.0.0"
merge-stream "^2.0.0"
npm-run-path "^4.0.1"
onetime "^5.1.2"
signal-exit "^3.0.3"
strip-final-newline "^2.0.0"
express@^4.17.3:
version "4.18.2"
resolved "https://registry.npmjs.org/express/-/express-4.18.2.tgz"
@ -3298,11 +3120,6 @@ get-caller-file@^2.0.5:
resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
get-func-name@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz"
integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==
get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1:
version "1.2.1"
resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz"
@ -3320,11 +3137,6 @@ get-stream@^5.1.0:
dependencies:
pump "^3.0.0"
get-stream@^6.0.0:
version "6.0.1"
resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz"
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
get-symbol-description@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz"
@ -3347,23 +3159,6 @@ glob-parent@^6.0.2:
dependencies:
is-glob "^4.0.3"
glob-regex@^0.3.0:
version "0.3.2"
resolved "https://registry.npmjs.org/glob-regex/-/glob-regex-0.3.2.tgz"
integrity sha512-m5blUd3/OqDTWwzBBtWBPrGlAzatRywHameHeekAZyZrskYouOGdNB8T/q6JucucvJXtOuyHIn0/Yia7iDasDw==
glob@7.1.6:
version "7.1.6"
resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
version "7.2.3"
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
@ -3376,17 +3171,6 @@ glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^8.1.0:
version "8.1.0"
resolved "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz"
integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^5.0.1"
once "^1.3.0"
global-agent@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz"
@ -3446,11 +3230,6 @@ globjoin@^0.1.4:
resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43"
integrity sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==
globrex@^0.1.2:
version "0.1.2"
resolved "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz"
integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==
gopd@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz"
@ -3485,18 +3264,6 @@ graphemer@^1.4.0:
resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz"
integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
happy-dom@^11.0.6:
version "11.2.0"
resolved "https://registry.yarnpkg.com/happy-dom/-/happy-dom-11.2.0.tgz#4b476deb71707bc7c231e6545cd62a81ef2cf689"
integrity sha512-z4PshcYIIH6SkymSNRcDFwYUJOENe+FOQDx5BbHgg/wQUgxF5p9I9/BN45Jff34bbhXV8yJgkC5N99eyOzXK3w==
dependencies:
css.escape "^1.5.1"
entities "^4.5.0"
iconv-lite "^0.6.3"
webidl-conversions "^7.0.0"
whatwg-encoding "^2.0.0"
whatwg-mimetype "^3.0.0"
hard-rejection@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
@ -3650,11 +3417,6 @@ https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1:
agent-base "6"
debug "4"
human-signals@^2.1.0:
version "2.1.0"
resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
humanize-ms@^1.2.1:
version "1.2.1"
resolved "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz"
@ -3677,7 +3439,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24:
dependencies:
safer-buffer ">= 2.1.2 < 3"
iconv-lite@0.6.3, iconv-lite@^0.6.2, iconv-lite@^0.6.3:
iconv-lite@0.6.3, iconv-lite@^0.6.2:
version "0.6.3"
resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz"
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
@ -3694,11 +3456,6 @@ ignore@^5.1.1, ignore@^5.2.0, ignore@^5.2.4:
resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz"
integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
immutable@^4.0.0:
version "4.3.4"
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.4.tgz#2e07b33837b4bb7662f288c244d1ced1ef65a78f"
integrity sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==
import-fresh@^3.2.1, import-fresh@^3.3.0:
version "3.3.0"
resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz"
@ -3745,7 +3502,7 @@ inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
ini@^1.3.4, ini@^1.3.5:
ini@^1.3.5:
version "1.3.8"
resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
@ -3948,11 +3705,6 @@ is-shared-array-buffer@^1.0.2:
dependencies:
call-bind "^1.0.2"
is-stream@^2.0.0:
version "2.0.1"
resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz"
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
is-string@^1.0.5, is-string@^1.0.7:
version "1.0.7"
resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz"
@ -4033,16 +3785,6 @@ jake@^10.8.5:
filelist "^1.0.4"
minimatch "^3.1.2"
js-beautify@1.14.9:
version "1.14.9"
resolved "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.9.tgz"
integrity sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==
dependencies:
config-chain "^1.1.13"
editorconfig "^1.0.3"
glob "^8.1.0"
nopt "^6.0.0"
js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@ -4229,11 +3971,6 @@ loader-utils@^2.0.0:
emojis-list "^3.0.0"
json5 "^2.1.2"
local-pkg@^0.4.1:
version "0.4.3"
resolved "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz"
integrity sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==
locate-path@^6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz"
@ -4294,13 +4031,6 @@ log-symbols@^4.1.0:
chalk "^4.1.0"
is-unicode-supported "^0.1.0"
loupe@^2.3.1:
version "2.3.6"
resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz"
integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==
dependencies:
get-func-name "^2.0.0"
lower-case@^1.1.1:
version "1.1.4"
resolved "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz"
@ -4488,11 +4218,6 @@ merge-descriptors@1.0.1:
resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz"
integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
merge-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz"
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
merge2@^1.3.0, merge2@^1.4.1:
version "1.4.1"
resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz"
@ -4553,13 +4278,6 @@ min-indent@^1.0.1:
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
minimatch@9.0.1:
version "9.0.1"
resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz"
integrity sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==
dependencies:
brace-expansion "^2.0.1"
minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
@ -4652,11 +4370,6 @@ mkdirp@^1.0.3, mkdirp@^1.0.4:
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
mrmime@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz"
integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==
ms@2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
@ -4677,15 +4390,6 @@ mute-stream@0.0.8:
resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz"
integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
mz@^2.7.0:
version "2.7.0"
resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz"
integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
dependencies:
any-promise "^1.0.0"
object-assign "^4.0.1"
thenify-all "^1.0.0"
nanoid@^3.3.6:
version "3.3.6"
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz"
@ -4758,13 +4462,6 @@ nopt@^5.0.0:
dependencies:
abbrev "1"
nopt@^6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz"
integrity sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==
dependencies:
abbrev "^1.0.0"
normalize-package-data@^3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e"
@ -4790,13 +4487,6 @@ normalize-url@^6.0.1:
resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz"
integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
npm-run-path@^4.0.1:
version "4.0.1"
resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz"
integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
dependencies:
path-key "^3.0.0"
npmlog@^5.0.1:
version "5.0.1"
resolved "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz"
@ -4829,7 +4519,7 @@ nwsapi@^2.2.4:
resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz"
integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==
object-assign@^4.0.1, object-assign@^4.1.1:
object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
@ -4901,7 +4591,7 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies:
wrappy "1"
onetime@^5.1.0, onetime@^5.1.2:
onetime@^5.1.0:
version "5.1.2"
resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz"
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
@ -5021,7 +4711,7 @@ path-is-absolute@^1.0.0:
resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz"
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
path-key@^3.0.0, path-key@^3.1.0:
path-key@^3.1.0:
version "3.1.1"
resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
@ -5041,11 +4731,6 @@ path-type@^4.0.0:
resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
pathval@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz"
integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==
pend@~1.2.0:
version "1.2.0"
resolved "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz"
@ -5069,11 +4754,6 @@ pinia@^2.0.11:
"@vue/devtools-api" "^6.5.0"
vue-demi ">=0.14.5"
pirates@^4.0.1:
version "4.0.6"
resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz"
integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==
playwright-core@1.37.1:
version "1.37.1"
resolved "https://registry.npmjs.org/playwright-core/-/playwright-core-1.37.1.tgz"
@ -5189,11 +4869,6 @@ promise-retry@^2.0.1:
err-code "^2.0.2"
retry "^0.12.0"
proto-list@~1.2.1:
version "1.2.4"
resolved "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz"
integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==
proxy-addr@~2.0.7:
version "2.0.7"
resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz"
@ -5349,17 +5024,6 @@ readdirp@~3.6.0:
dependencies:
picomatch "^2.2.1"
recrawl-sync@^2.0.3:
version "2.2.3"
resolved "https://registry.npmjs.org/recrawl-sync/-/recrawl-sync-2.2.3.tgz"
integrity sha512-vSaTR9t+cpxlskkdUFrsEpnf67kSmPk66yAGT1fZPrDudxQjoMzPgQhSMImQ0pAw5k0NPirefQfhopSjhdUtpQ==
dependencies:
"@cush/relative" "^1.0.0"
glob-regex "^0.3.0"
slash "^3.0.0"
sucrase "^3.20.3"
tslib "^1.9.3"
redent@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/redent/-/redent-4.0.0.tgz#0c0ba7caabb24257ab3bb7a4fd95dd1d5c5681f9"
@ -5557,6 +5221,13 @@ sanitize-filename@^1.6.3:
dependencies:
truncate-utf8-bytes "^1.0.0"
sass@1.29.0:
version "1.29.0"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.29.0.tgz#ec4e1842c146d8ea9258c28c141b8c2b7c6ab7f1"
integrity sha512-ZpwAUFgnvAUCdkjwPREny+17BpUj8nh5Yr6zKPGtLNTLrmtoRYIjm7njP24COhjJldjwW1dcv52Lpf4tNZVVRA==
dependencies:
chokidar ">=2.0.0 <4.0.0"
sass@1.32.12:
version "1.32.12"
resolved "https://registry.npmjs.org/sass/-/sass-1.32.12.tgz"
@ -5564,15 +5235,6 @@ sass@1.32.12:
dependencies:
chokidar ">=3.0.0 <4.0.0"
sass@^1.69.0:
version "1.69.0"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.69.0.tgz#5195075371c239ed556280cf2f5944d234f42679"
integrity sha512-l3bbFpfTOGgQZCLU/gvm1lbsQ5mC/WnLz3djL2v4WCJBDrWm58PO+jgngcGRNnKUh6wSsdm50YaovTqskZ0xDQ==
dependencies:
chokidar ">=3.0.0 <4.0.0"
immutable "^4.0.0"
source-map-js ">=0.6.2 <2.0.0"
sax@1.1.4:
version "1.1.4"
resolved "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz"
@ -5697,7 +5359,7 @@ side-channel@^1.0.4:
get-intrinsic "^1.0.2"
object-inspect "^1.9.0"
signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.7:
version "3.0.7"
resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
@ -5714,15 +5376,6 @@ simple-update-notifier@2.0.0:
dependencies:
semver "^7.5.3"
sirv@^2.0.2:
version "2.0.3"
resolved "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz"
integrity sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==
dependencies:
"@polka/url" "^1.0.0-next.20"
mrmime "^1.0.0"
totalist "^3.0.0"
slash@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
@ -5768,7 +5421,7 @@ socks@^2.6.2:
ip "^2.0.0"
smart-buffer "^4.2.0"
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2:
source-map-js@^1.0.1, source-map-js@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
@ -5922,11 +5575,6 @@ strip-bom@^3.0.0:
resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz"
integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
strip-final-newline@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
strip-indent@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-4.0.0.tgz#b41379433dd06f5eae805e21d631e07ee670d853"
@ -6053,19 +5701,6 @@ stylelint@^15.10.3:
table "^6.8.1"
write-file-atomic "^5.0.1"
sucrase@^3.20.3:
version "3.34.0"
resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz"
integrity sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==
dependencies:
"@jridgewell/gen-mapping" "^0.3.2"
commander "^4.0.0"
glob "7.1.6"
lines-and-columns "^1.1.6"
mz "^2.7.0"
pirates "^4.0.1"
ts-interface-checker "^0.1.9"
sumchecker@^3.0.1:
version "3.0.1"
resolved "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz"
@ -6157,35 +5792,11 @@ text-table@^0.2.0:
resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz"
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
thenify-all@^1.0.0:
version "1.6.0"
resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz"
integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==
dependencies:
thenify ">= 3.1.0 < 4"
"thenify@>= 3.1.0 < 4":
version "3.3.1"
resolved "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz"
integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
dependencies:
any-promise "^1.0.0"
through@^2.3.6:
version "2.3.8"
resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz"
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
tinypool@^0.1.3:
version "0.1.3"
resolved "https://registry.npmjs.org/tinypool/-/tinypool-0.1.3.tgz"
integrity sha512-2IfcQh7CP46XGWGGbdyO4pjcKqsmVqFAPcXfPxcPXmOWt9cYkTP9HcDmGgsfijYoAEc4z9qcpM/BaBz46Y9/CQ==
tinyspy@^0.3.3:
version "0.3.3"
resolved "https://registry.npmjs.org/tinyspy/-/tinyspy-0.3.3.tgz"
integrity sha512-gRiUR8fuhUf0W9lzojPf1N1euJYA30ISebSfgca8z76FOvXtVXqd5ojEIaKLWbDQhAaC3ibxZIjqbyi4ybjcTw==
tmp-promise@^3.0.2:
version "3.0.3"
resolved "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz"
@ -6219,11 +5830,6 @@ toidentifier@1.0.1:
resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz"
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
totalist@^3.0.0:
version "3.0.1"
resolved "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz"
integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==
tough-cookie@^4.1.2:
version "4.1.3"
resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz"
@ -6258,17 +5864,7 @@ truncate-utf8-bytes@^1.0.0:
dependencies:
utf8-byte-length "^1.0.1"
ts-interface-checker@^0.1.9:
version "0.1.13"
resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz"
integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
tsconfck@^2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/tsconfck/-/tsconfck-2.1.2.tgz#f667035874fa41d908c1fe4d765345fcb1df6e35"
integrity sha512-ghqN1b0puy3MhhviwO2kGF8SeMDNhEbnKxjK7h6+fvY9JAxqvXi8y5NAHSQv687OVboS2uZIByzGd45/YxrRHg==
tsconfig-paths@^3.14.2, tsconfig-paths@^3.9.0:
tsconfig-paths@^3.14.2:
version "3.14.2"
resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz"
integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==
@ -6278,7 +5874,7 @@ tsconfig-paths@^3.14.2, tsconfig-paths@^3.9.0:
minimist "^1.2.6"
strip-bom "^3.0.0"
tslib@^1.8.1, tslib@^1.9.3:
tslib@^1.8.1:
version "1.14.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
@ -6302,11 +5898,6 @@ type-check@^0.4.0, type-check@~0.4.0:
dependencies:
prelude-ls "^1.2.1"
type-detect@^4.0.0, type-detect@^4.0.5:
version "4.0.8"
resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
type-fest@^0.13.1:
version "0.13.1"
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz"
@ -6515,26 +6106,7 @@ verror@^1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
vite-jsconfig-paths@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/vite-jsconfig-paths/-/vite-jsconfig-paths-2.0.1.tgz"
integrity sha512-rabcTTfKs0MdAsQWcZjbIMo5fcp6jthZce7uFEPgVPgpSY+RNOwjzIJOPES6cB/GJZLSoLGfHM9kt5HNmJvp7A==
dependencies:
debug "^4.1.1"
globrex "^0.1.2"
recrawl-sync "^2.0.3"
tsconfig-paths "^3.9.0"
vite-tsconfig-paths@^4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-4.2.1.tgz#e53b89096b91d31a6d1e26f75999ea8c336a89ed"
integrity sha512-GNUI6ZgPqT3oervkvzU+qtys83+75N/OuDaQl7HmOqFTb0pjZsuARrRipsyJhJ3enqV8beI1xhGbToR4o78nSQ==
dependencies:
debug "^4.1.1"
globrex "^0.1.2"
tsconfck "^2.1.0"
vite@^2.9.12, vite@^2.9.13:
vite@^2.9.13:
version "2.9.16"
resolved "https://registry.npmjs.org/vite/-/vite-2.9.16.tgz"
integrity sha512-X+6q8KPyeuBvTQV8AVSnKDvXoBMnTx8zxh54sOwmmuOdxkjMmEJXH2UEchA+vTMps1xw9vL64uwJOWryULg7nA==
@ -6546,26 +6118,6 @@ vite@^2.9.12, vite@^2.9.13:
optionalDependencies:
fsevents "~2.3.2"
vitest@^0.15.0:
version "0.15.2"
resolved "https://registry.npmjs.org/vitest/-/vitest-0.15.2.tgz"
integrity sha512-cMabuUqu+nNHafkdN7H8Z20+UZTrrUfqjGwAoLwUwrqFGWBz3gXwxndjbLf6mgSFs9lF/JWjKeNM1CXKwtk26w==
dependencies:
"@types/chai" "^4.3.1"
"@types/chai-subset" "^1.3.3"
"@types/node" "*"
chai "^4.3.6"
debug "^4.3.4"
local-pkg "^0.4.1"
tinypool "^0.1.3"
tinyspy "^0.3.3"
vite "^2.9.12"
vue-component-type-helpers@1.8.4:
version "1.8.4"
resolved "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-1.8.4.tgz"
integrity sha512-6bnLkn8O0JJyiFSIF0EfCogzeqNXpnjJ0vW/SZzNHfe6sPx30lTtTXlE5TFs2qhJlAtDFybStVNpL73cPe3OMQ==
vue-demi@>=0.14.5:
version "0.14.6"
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz"