feature/fix-macos-cypress-and-align-with-create-vite #2898

Merged
konrad merged 3 commits from dpschen/frontend:feature/fix-macos-cypress-and-align-with-create-vite into main 2023-01-04 03:19:38 +00:00
46 changed files with 328 additions and 236 deletions

View File

@ -96,7 +96,7 @@ steps:
- dependencies - dependencies
- name: test-frontend - name: test-frontend
image: cypress/browsers:node18.12.0-chrome106-ff106 image: cypress/browsers:node18.12.0-chrome107
pull: always pull: always
environment: environment:
CYPRESS_API_URL: http://api:3456/api/v1 CYPRESS_API_URL: http://api:3456/api/v1
@ -110,8 +110,7 @@ steps:
- sed -i 's/localhost/api/g' dist/index.html - sed -i 's/localhost/api/g' dist/index.html
- corepack enable && pnpm config set store-dir .cache/pnpm - corepack enable && pnpm config set store-dir .cache/pnpm
- pnpm cypress install - pnpm cypress install
- pnpm run serve:dist & npx wait-on http://localhost:4173 - pnpm run test:e2e-record
- pnpm run test:frontend --browser chrome --record
depends_on: depends_on:
- build-prod - build-prod

34
.gitignore vendored
View File

@ -1,26 +1,31 @@
.DS_Store # Logs
node_modules
/dist*
*.zip
.direnv/
# local env files
.env.local
.env.*.local
# Log files
logs logs
*.log *.log
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
stats.html
pnpm-debug.log* pnpm-debug.log*
lerna-debug.log* lerna-debug.log*
stats.html
node_modules
.DS_Store
/dist*
coverage
*.zip
.direnv/
# Test files
cypress/screenshots
cypress/videos
# local env files
.env.local
.env.*.local
# Editor directories and files # Editor directories and files
.idea
.vscode .vscode
.idea
*.suo *.suo
*.ntvs* *.ntvs*
*.njsproj *.njsproj
@ -28,9 +33,6 @@ lerna-debug.log*
*.sw* *.sw*
!rollup.sw.js !rollup.sw.js
# Test files
cypress/screenshots
cypress/videos
# Local Netlify folder # Local Netlify folder
.netlify .netlify

View File

@ -11,8 +11,10 @@ export default defineConfig({
}, },
projectId: '181c7x', projectId: '181c7x',
e2e: { e2e: {
baseUrl: 'http://localhost:4173', specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}',
specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}', baseUrl: 'http://127.0.0.1:4173',
experimentalRunAllSpecs: true,
dpschen marked this conversation as resolved Outdated

What does this do?

What does this do?

Cyress removed the "run all" button in the UI in cypress 12 (i think). This readds it

Cyress removed the "run all" button in the UI in cypress 12 (i think). This readds it
// testIsolation: false,
}, },
component: { component: {
devServer: { devServer: {

View File

@ -36,7 +36,7 @@ to get a shell inside the cypress container.
In that shell you can then execute the tests with In that shell you can then execute the tests with
```shell ```shell
pnpm run test:frontend pnpm run test:e2e
``` ```
### Using The Cypress Dashboard ### Using The Cypress Dashboard
@ -44,5 +44,5 @@ pnpm run test:frontend
To open the Cypress Dashboard and run tests from there, run To open the Cypress Dashboard and run tests from there, run
```shell ```shell
pnpm run cypress:open pnpm run test:e2e:dev
``` ```

View File

@ -9,7 +9,7 @@ services:
ports: ports:
- 3456:3456 - 3456:3456
cypress: cypress:
image: cypress/browsers:node16.14.0-chrome99-ff97 image: cypress/browsers:node18.12.0-chrome107
volumes: volumes:
- ..:/project - ..:/project
- $HOME/.cache:/home/node/.cache/ - $HOME/.cache:/home/node/.cache/

View File

@ -1,9 +1,10 @@
import {ListFactory} from '../../factories/list' import {createFakeUserAndLogin} from '../../support/authenticateUser'
import '../../support/authenticateUser' import {ListFactory} from '../../factories/list'
import {prepareLists} from './prepareLists' import {prepareLists} from './prepareLists'
describe('List History', () => { describe('List History', () => {
createFakeUserAndLogin()
prepareLists() prepareLists()
it('should show a list history on the home page', () => { it('should show a list history on the home page', () => {

View File

@ -1,10 +1,12 @@
import {formatISO, format} from 'date-fns' import {formatISO, format} from 'date-fns'
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task' import {TaskFactory} from '../../factories/task'
import {prepareLists} from './prepareLists' import {prepareLists} from './prepareLists'
import '../../support/authenticateUser'
describe('List View Gantt', () => { describe('List View Gantt', () => {
createFakeUserAndLogin()
prepareLists() prepareLists()
it('Hides tasks with no dates', () => { it('Hides tasks with no dates', () => {
@ -33,8 +35,8 @@ describe('List View Gantt', () => {
it('Shows tasks with dates', () => { it('Shows tasks with dates', () => {
const now = new Date() const now = new Date()
const tasks = TaskFactory.create(1, { const tasks = TaskFactory.create(1, {
start_date: formatISO(now), start_date: now.toISOString(),
end_date: formatISO(now.setDate(now.getDate() + 4)), end_date: new Date(new Date(now).setDate(now.getDate() + 4)).toISOString(),
}) })
cy.visit('/lists/1/gantt') cy.visit('/lists/1/gantt')

View File

@ -1,14 +1,15 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {BucketFactory} from '../../factories/bucket' import {BucketFactory} from '../../factories/bucket'
import {ListFactory} from '../../factories/list' import {ListFactory} from '../../factories/list'
import {TaskFactory} from '../../factories/task' import {TaskFactory} from '../../factories/task'
import {prepareLists} from './prepareLists' import {prepareLists} from './prepareLists'
import '../../support/authenticateUser'
describe('List View Kanban', () => { describe('List View Kanban', () => {
let buckets createFakeUserAndLogin()
prepareLists() prepareLists()
let buckets
beforeEach(() => { beforeEach(() => {
buckets = BucketFactory.create(2) buckets = BucketFactory.create(2)
}) })
@ -38,7 +39,7 @@ describe('List View Kanban', () => {
}) })
cy.visit('/lists/1/kanban') cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket') cy.get('.kanban .bucket')
.contains(buckets[0].title) .contains(buckets[0].title)
.get('.bucket-footer .button') .get('.bucket-footer .button')
.contains('Add another task') .contains('Add another task')
@ -70,7 +71,7 @@ describe('List View Kanban', () => {
it('Can set a bucket limit', () => { it('Can set a bucket limit', () => {
cy.visit('/lists/1/kanban') cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger') cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger')
.first() .first()
.click() .click()
cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item') cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item')
@ -91,7 +92,7 @@ describe('List View Kanban', () => {
it('Can rename a bucket', () => { it('Can rename a bucket', () => {
cy.visit('/lists/1/kanban') cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket .bucket-header .title') cy.get('.kanban .bucket .bucket-header .title')
.first() .first()
.type('{selectall}New Bucket Title{enter}') .type('{selectall}New Bucket Title{enter}')
cy.get('.kanban .bucket .bucket-header .title') cy.get('.kanban .bucket .bucket-header .title')
@ -102,7 +103,7 @@ describe('List View Kanban', () => {
it('Can delete a bucket', () => { it('Can delete a bucket', () => {
cy.visit('/lists/1/kanban') cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger') cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger')
.first() .first()
.click() .click()
cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item') cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item')
@ -129,7 +130,7 @@ describe('List View Kanban', () => {
}) })
cy.visit('/lists/1/kanban') cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket .tasks .task') cy.get('.kanban .bucket .tasks .task')
.contains(tasks[0].title) .contains(tasks[0].title)
.first() .first()
.drag('.kanban .bucket:nth-child(2) .tasks') .drag('.kanban .bucket:nth-child(2) .tasks')
@ -148,7 +149,7 @@ describe('List View Kanban', () => {
}) })
cy.visit('/lists/1/kanban') cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket .tasks .task') cy.get('.kanban .bucket .tasks .task')
.contains(tasks[0].title) .contains(tasks[0].title)
.should('be.visible') .should('be.visible')
.click() .click()
@ -170,7 +171,7 @@ describe('List View Kanban', () => {
const task = tasks[0] const task = tasks[0]
cy.visit('/lists/1/kanban') cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket .tasks .task') cy.get('.kanban .bucket .tasks .task')
.contains(task.title) .contains(task.title)
.should('be.visible') .should('be.visible')
.click() .click()
@ -217,7 +218,7 @@ describe('List View Kanban', () => {
const task = tasks[0] const task = tasks[0]
cy.visit('/lists/1/kanban') cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket .tasks .task') cy.get('.kanban .bucket .tasks .task')
.contains(task.title) .contains(task.title)
.should('be.visible') .should('be.visible')
.click() .click()
@ -234,7 +235,7 @@ describe('List View Kanban', () => {
cy.get('.global-notification') cy.get('.global-notification')
.should('contain', 'Success') .should('contain', 'Success')
cy.getSettled('.kanban .bucket .tasks') cy.get('.kanban .bucket .tasks')
.should('not.contain', task.title) .should('not.contain', task.title)
}) })
}) })

View File

@ -1,12 +1,13 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {UserListFactory} from '../../factories/users_list' import {UserListFactory} from '../../factories/users_list'
import {TaskFactory} from '../../factories/task' import {TaskFactory} from '../../factories/task'
import {UserFactory} from '../../factories/user' import {UserFactory} from '../../factories/user'
import {ListFactory} from '../../factories/list' import {ListFactory} from '../../factories/list'
import {prepareLists} from './prepareLists' import {prepareLists} from './prepareLists'
import '../../support/authenticateUser'
describe('List View List', () => { describe('List View List', () => {
createFakeUserAndLogin()
prepareLists() prepareLists()
it('Should be an empty list', () => { it('Should be an empty list', () => {

View File

@ -1,8 +1,10 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task' import {TaskFactory} from '../../factories/task'
import '../../support/authenticateUser'
describe('List View Table', () => { describe('List View Table', () => {
createFakeUserAndLogin()
it('Should show a table with tasks', () => { it('Should show a table with tasks', () => {
const tasks = TaskFactory.create(1) const tasks = TaskFactory.create(1)
cy.visit('/lists/1/table') cy.visit('/lists/1/table')

View File

@ -1,9 +1,11 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task' import {TaskFactory} from '../../factories/task'
import {prepareLists} from './prepareLists' import {prepareLists} from './prepareLists'
import '../../support/authenticateUser'
describe('Lists', () => { describe('Lists', () => {
createFakeUserAndLogin()
let lists let lists
prepareLists((newLists) => (lists = newLists)) prepareLists((newLists) => (lists = newLists))

View File

@ -1,14 +1,14 @@
import {UserFactory} from '../../factories/user' import {createFakeUserAndLogin} from '../../support/authenticateUser'
import '../../support/authenticateUser'
import {ListFactory} from '../../factories/list' import {ListFactory} from '../../factories/list'
import {NamespaceFactory} from '../../factories/namespace' import {NamespaceFactory} from '../../factories/namespace'
describe('Namepaces', () => { describe('Namepaces', () => {
createFakeUserAndLogin()
let namespaces let namespaces
beforeEach(() => { beforeEach(() => {
UserFactory.create(1)
namespaces = NamespaceFactory.create(1) namespaces = NamespaceFactory.create(1)
ListFactory.create(1) ListFactory.create(1)
}) })

View File

@ -1,10 +1,8 @@
import {ListFactory} from '../../factories/list' import {ListFactory} from '../../factories/list'
import {UserFactory} from '../../factories/user'
import {NamespaceFactory} from '../../factories/namespace' import {NamespaceFactory} from '../../factories/namespace'
import {TaskFactory} from '../../factories/task' import {TaskFactory} from '../../factories/task'
export function createLists() { export function createLists() {
UserFactory.create(1)
NamespaceFactory.create(1) NamespaceFactory.create(1)
const lists = ListFactory.create(1, { const lists = ListFactory.create(1, {
title: 'First List' title: 'First List'

View File

@ -1,14 +1,16 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task' import {TaskFactory} from '../../factories/task'
import {ListFactory} from '../../factories/list' import {ListFactory} from '../../factories/list'
import {NamespaceFactory} from '../../factories/namespace' import {NamespaceFactory} from '../../factories/namespace'
import {UserListFactory} from '../../factories/users_list' import {UserListFactory} from '../../factories/users_list'
import '../../support/authenticateUser'
describe('Editor', () => { describe('Editor', () => {
createFakeUserAndLogin()
beforeEach(() => { beforeEach(() => {
NamespaceFactory.create(1) NamespaceFactory.create(1)
const lists = ListFactory.create(1) ListFactory.create(1)
TaskFactory.truncate() TaskFactory.truncate()
UserListFactory.truncate() UserListFactory.truncate()
}) })

View File

@ -1,6 +1,12 @@
import '../../support/authenticateUser' import {createFakeUserAndLogin} from '../../support/authenticateUser'
describe('The Menu', () => { describe('The Menu', () => {
createFakeUserAndLogin()
beforeEach(() => {
cy.visit('/')
})
it('Is visible by default on desktop', () => { it('Is visible by default on desktop', () => {
cy.get('.namespace-container') cy.get('.namespace-container')
.should('have.class', 'is-active') .should('have.class', 'is-active')

View File

@ -1,9 +1,12 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TeamFactory} from '../../factories/team' import {TeamFactory} from '../../factories/team'
import {TeamMemberFactory} from '../../factories/team_member' import {TeamMemberFactory} from '../../factories/team_member'
import {UserFactory} from '../../factories/user' import {UserFactory} from '../../factories/user'
import '../../support/authenticateUser'
describe('Team', () => { describe('Team', () => {
createFakeUserAndLogin()
it('Creates a new team', () => { it('Creates a new team', () => {
TeamFactory.truncate() TeamFactory.truncate()
cy.visit('/teams') cy.visit('/teams')

View File

@ -1,16 +1,13 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {ListFactory} from '../../factories/list' import {ListFactory} from '../../factories/list'
import {seed} from '../../support/seed' import {seed} from '../../support/seed'
import {TaskFactory} from '../../factories/task' import {TaskFactory} from '../../factories/task'
import {formatISO} from 'date-fns'
import {UserFactory} from '../../factories/user'
import {NamespaceFactory} from '../../factories/namespace' import {NamespaceFactory} from '../../factories/namespace'
import {BucketFactory} from '../../factories/bucket' import {BucketFactory} from '../../factories/bucket'
import {updateUserSettings} from '../../support/updateUserSettings' import {updateUserSettings} from '../../support/updateUserSettings'
import '../../support/authenticateUser' function seedTasks(numberOfTasks = 50, startDueDate = new Date()) {
dpschen marked this conversation as resolved Outdated

I think the changes to this function have broken the tests: https://cloud.cypress.io/projects/181c7x/runs/3562/overview

I think the changes to this function have broken the tests: https://cloud.cypress.io/projects/181c7x/runs/3562/overview

will check

will check
See https://kolaente.dev/vikunja/frontend/pulls/2898/files#issuecomment-41985
function seedTasks(numberOfTasks = 100, startDueDate = new Date()) {
UserFactory.create(1)
NamespaceFactory.create(1) NamespaceFactory.create(1)
const list = ListFactory.create()[0] const list = ListFactory.create()[0]
BucketFactory.create(1, { BucketFactory.create(1, {
@ -20,7 +17,7 @@ function seedTasks(numberOfTasks = 100, startDueDate = new Date()) {
let dueDate = startDueDate let dueDate = startDueDate
for (let i = 0; i < numberOfTasks; i++) { for (let i = 0; i < numberOfTasks; i++) {
const now = new Date() const now = new Date()
dueDate = (new Date(dueDate.valueOf())).setDate((new Date(dueDate.valueOf())).getDate() + 2) dueDate = new Date(new Date(dueDate).setDate(dueDate.getDate() + 2))
tasks.push({ tasks.push({
id: i + 1, id: i + 1,
list_id: list.id, list_id: list.id,
@ -28,9 +25,9 @@ function seedTasks(numberOfTasks = 100, startDueDate = new Date()) {
created_by_id: 1, created_by_id: 1,
title: 'Test Task ' + i, title: 'Test Task ' + i,
index: i + 1, index: i + 1,
due_date: formatISO(dueDate), due_date: dueDate.toISOString(),
created: formatISO(now), created: now.toISOString(),
updated: formatISO(now), updated: now.toISOString(),
}) })
} }
seed(TaskFactory.table, tasks) seed(TaskFactory.table, tasks)
@ -38,8 +35,11 @@ function seedTasks(numberOfTasks = 100, startDueDate = new Date()) {
} }
describe('Home Page Task Overview', () => { describe('Home Page Task Overview', () => {
createFakeUserAndLogin()
it('Should show tasks with a near due date first on the home page overview', () => { it('Should show tasks with a near due date first on the home page overview', () => {
const {tasks} = seedTasks() const taskCount = 50
const {tasks} = seedTasks(taskCount)
cy.visit('/') cy.visit('/')
cy.get('[data-cy="showTasks"] .card .task') cy.get('[data-cy="showTasks"] .card .task')
@ -49,8 +49,10 @@ describe('Home Page Task Overview', () => {
}) })
it('Should show overdue tasks first, then show other tasks', () => { it('Should show overdue tasks first, then show other tasks', () => {
const oldDate = (new Date()).setDate((new Date()).getDate() - 14) const now = new Date()
const {tasks} = seedTasks(100, oldDate) const oldDate = new Date(new Date(now).setDate(now.getDate() - 14))
const taskCount = 50
const {tasks} = seedTasks(taskCount, oldDate)
cy.visit('/') cy.visit('/')
cy.get('[data-cy="showTasks"] .card .task') cy.get('[data-cy="showTasks"] .card .task')
@ -68,7 +70,7 @@ describe('Home Page Task Overview', () => {
TaskFactory.create(1, { TaskFactory.create(1, {
id: 999, id: 999,
title: newTaskTitle, title: newTaskTitle,
due_date: formatISO(new Date()), due_date: new Date().toISOString(),
}, false) }, false)
cy.visit(`/lists/${tasks[0].list_id}/list`) cy.visit(`/lists/${tasks[0].list_id}/list`)
@ -83,7 +85,7 @@ describe('Home Page Task Overview', () => {
it('Should not show a new task without a date at the bottom when there are > 50 tasks', () => { it('Should not show a new task without a date at the bottom when there are > 50 tasks', () => {
// We're not using the api here to create the task in order to verify the flow // We're not using the api here to create the task in order to verify the flow
const {tasks} = seedTasks() const {tasks} = seedTasks(100)
const newTaskTitle = 'New Task' const newTaskTitle = 'New Task'
cy.visit('/') cy.visit('/')

View File

@ -1,4 +1,4 @@
import {formatISO} from 'date-fns' import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task' import {TaskFactory} from '../../factories/task'
import {ListFactory} from '../../factories/list' import {ListFactory} from '../../factories/list'
@ -11,7 +11,6 @@ import {LabelFactory} from '../../factories/labels'
import {LabelTaskFactory} from '../../factories/label_task' import {LabelTaskFactory} from '../../factories/label_task'
import {BucketFactory} from '../../factories/bucket' import {BucketFactory} from '../../factories/bucket'
import '../../support/authenticateUser'
import {TaskAttachmentFactory} from '../../factories/task_attachments' import {TaskAttachmentFactory} from '../../factories/task_attachments'
function addLabelToTaskAndVerify(labelTitle: string) { function addLabelToTaskAndVerify(labelTitle: string) {
@ -46,12 +45,14 @@ function uploadAttachmentAndVerify(taskId: number) {
} }
describe('Task', () => { describe('Task', () => {
createFakeUserAndLogin()
let namespaces let namespaces
let lists let lists
let buckets let buckets
beforeEach(() => { beforeEach(() => {
UserFactory.create(1) // UserFactory.create(1)
namespaces = NamespaceFactory.create(1) namespaces = NamespaceFactory.create(1)
lists = ListFactory.create(1) lists = ListFactory.create(1)
buckets = BucketFactory.create(1, { buckets = BucketFactory.create(1, {
@ -145,7 +146,7 @@ describe('Task', () => {
id: 1, id: 1,
index: 1, index: 1,
done: true, done: true,
done_at: formatISO(new Date()) done_at: new Date().toISOString()
}) })
cy.visit(`/tasks/${tasks[0].id}`) cy.visit(`/tasks/${tasks[0].id}`)
@ -421,10 +422,10 @@ describe('Task', () => {
cy.visit(`/tasks/${tasks[0].id}`) cy.visit(`/tasks/${tasks[0].id}`)
cy.getSettled('.task-view .details.labels-list .multiselect .input-wrapper') cy.get('.task-view .details.labels-list .multiselect .input-wrapper')
.should('be.visible') .should('be.visible')
.should('contain', labels[0].title) .should('contain', labels[0].title)
cy.getSettled('.task-view .details.labels-list .multiselect .input-wrapper') cy.get('.task-view .details.labels-list .multiselect .input-wrapper')
.children() .children()
.first() .first()
.get('[data-cy="taskDetail.removeLabel"]') .get('[data-cy="taskDetail.removeLabel"]')

11
cypress/e2e/tsconfig.json Normal file
View File

@ -0,0 +1,11 @@
{
"extends": "@vue/tsconfig/tsconfig.web.json",
"include": ["./**/*", "../support/**/*", "../factories/**/*"],
"compilerOptions": {
"baseUrl": ".",
"isolatedModules": false,
"target": "ES2015",
"lib": ["ESNext", "dom"],
"types": ["cypress"]
}
}

View File

@ -11,16 +11,11 @@ const testAndAssertFailed = fixture => {
cy.get('div.message.danger').contains('Wrong username or password.') cy.get('div.message.danger').contains('Wrong username or password.')
} }
const username = 'test'
context('Login', () => { context('Login', () => {
beforeEach(() => { beforeEach(() => {
UserFactory.create(1, { UserFactory.create(1, {username})
username: 'test',
})
cy.visit('/', {
onBeforeLoad(win) {
win.localStorage.removeItem('token')
},
})
}) })
it('Should log in with the right credentials', () => { it('Should log in with the right credentials', () => {

View File

@ -1,4 +1,4 @@
import '../../support/authenticateUser' import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {createLists} from '../list/prepareLists' import {createLists} from '../list/prepareLists'
function logout() { function logout() {
@ -10,6 +10,8 @@ function logout() {
} }
describe('Log out', () => { describe('Log out', () => {
createFakeUserAndLogin()
it('Logs the user out', () => { it('Logs the user out', () => {
cy.visit('/') cy.visit('/')

View File

@ -1,11 +1,7 @@
import {UserFactory} from '../../factories/user' import {createFakeUserAndLogin} from '../../support/authenticateUser'
import '../../support/authenticateUser'
describe('User Settings', () => { describe('User Settings', () => {
beforeEach(() => { createFakeUserAndLogin()
UserFactory.create(1)
})
it('Changes the user avatar', () => { it('Changes the user avatar', () => {
cy.intercept(`${Cypress.env('API_URL')}/user/settings/avatar/upload`).as('uploadAvatar') cy.intercept(`${Cypress.env('API_URL')}/user/settings/avatar/upload`).as('uploadAvatar')

View File

@ -1,6 +1,5 @@
import {faker} from '@faker-js/faker' import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class BucketFactory extends Factory { export class BucketFactory extends Factory {
static table = 'buckets' static table = 'buckets'
@ -13,8 +12,8 @@ export class BucketFactory extends Factory {
title: faker.lorem.words(3), title: faker.lorem.words(3),
list_id: 1, list_id: 1,
created_by_id: 1, created_by_id: 1,
created: formatISO(now), created: now.toISOString(),
updated: formatISO(now) updated: now.toISOString(),
} }
} }
} }

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class LabelTaskFactory extends Factory { export class LabelTaskFactory extends Factory {
static table = 'label_tasks' static table = 'label_tasks'
@ -11,7 +10,7 @@ export class LabelTaskFactory extends Factory {
id: '{increment}', id: '{increment}',
task_id: 1, task_id: 1,
label_id: 1, label_id: 1,
created: formatISO(now), created: now.toISOString(),
} }
} }
} }

View File

@ -1,7 +1,6 @@
import {faker} from '@faker-js/faker' import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class LabelFactory extends Factory { export class LabelFactory extends Factory {
static table = 'labels' static table = 'labels'
@ -15,8 +14,8 @@ export class LabelFactory extends Factory {
description: faker.lorem.text(10), description: faker.lorem.text(10),
hex_color: (Math.random()*0xFFFFFF<<0).toString(16), // random 6-digit hex number hex_color: (Math.random()*0xFFFFFF<<0).toString(16), // random 6-digit hex number
created_by_id: 1, created_by_id: 1,
created: formatISO(now), created: now.toISOString(),
updated: formatISO(now), updated: now.toISOString(),
} }
} }
} }

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from "date-fns"
import {faker} from '@faker-js/faker' import {faker} from '@faker-js/faker'
export class LinkShareFactory extends Factory { export class LinkShareFactory extends Factory {
@ -15,8 +14,8 @@ export class LinkShareFactory extends Factory {
right: 0, right: 0,
sharing_type: 0, sharing_type: 0,
shared_by_id: 1, shared_by_id: 1,
created: formatISO(now), created: now.toISOString(),
updated: formatISO(now) updated: now.toISOString(),
} }
} }
} }

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from "date-fns"
import {faker} from '@faker-js/faker' import {faker} from '@faker-js/faker'
export class ListFactory extends Factory { export class ListFactory extends Factory {
@ -13,8 +12,8 @@ export class ListFactory extends Factory {
title: faker.lorem.words(3), title: faker.lorem.words(3),
owner_id: 1, owner_id: 1,
namespace_id: 1, namespace_id: 1,
created: formatISO(now), created: now.toISOString(),
updated: formatISO(now) updated: now.toISOString(),
} }
} }
} }

View File

@ -1,6 +1,5 @@
import {faker} from '@faker-js/faker' import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class NamespaceFactory extends Factory { export class NamespaceFactory extends Factory {
static table = 'namespaces' static table = 'namespaces'
@ -12,8 +11,8 @@ export class NamespaceFactory extends Factory {
id: '{increment}', id: '{increment}',
title: faker.lorem.words(3), title: faker.lorem.words(3),
owner_id: 1, owner_id: 1,
created: formatISO(now), created: now.toISOString(),
updated: formatISO(now) updated: now.toISOString(),
} }
} }
} }

View File

@ -1,6 +1,5 @@
import {faker} from '@faker-js/faker' import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class TaskFactory extends Factory { export class TaskFactory extends Factory {
static table = 'tasks' static table = 'tasks'
@ -16,8 +15,8 @@ export class TaskFactory extends Factory {
created_by_id: 1, created_by_id: 1,
index: '{increment}', index: '{increment}',
position: '{increment}', position: '{increment}',
created: formatISO(now), created: now.toISOString(),
updated: formatISO(now) updated: now.toISOString()
} }
} }
} }

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class TaskAssigneeFactory extends Factory { export class TaskAssigneeFactory extends Factory {
static table = 'task_assignees' static table = 'task_assignees'
@ -11,7 +10,7 @@ export class TaskAssigneeFactory extends Factory {
id: '{increment}', id: '{increment}',
task_id: 1, task_id: 1,
user_id: 1, user_id: 1,
created: formatISO(now), created: now.toISOString(),
} }
} }
} }

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class TaskAttachmentFactory extends Factory { export class TaskAttachmentFactory extends Factory {
static table = 'task_attachments' static table = 'task_attachments'
@ -11,7 +10,7 @@ export class TaskAttachmentFactory extends Factory {
id: '{increment}', id: '{increment}',
task_id: 1, task_id: 1,
file_id: 1, file_id: 1,
created: formatISO(now), created: now.toISOString(),
} }
} }
} }

View File

@ -1,7 +1,6 @@
import {faker} from '@faker-js/faker' import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from "date-fns"
export class TaskCommentFactory extends Factory { export class TaskCommentFactory extends Factory {
static table = 'task_comments' static table = 'task_comments'
@ -14,8 +13,8 @@ export class TaskCommentFactory extends Factory {
comment: faker.lorem.text(3), comment: faker.lorem.text(3),
author_id: 1, author_id: 1,
task_id: 1, task_id: 1,
created: formatISO(now), created: now.toISOString(),
updated: formatISO(now) updated: now.toISOString()
} }
} }
} }

View File

@ -1,6 +1,5 @@
import {faker} from '@faker-js/faker' import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class TeamFactory extends Factory { export class TeamFactory extends Factory {
static table = 'teams' static table = 'teams'
@ -11,8 +10,8 @@ export class TeamFactory extends Factory {
return { return {
name: faker.lorem.words(3), name: faker.lorem.words(3),
created_by_id: 1, created_by_id: 1,
created: formatISO(now), created: now.toISOString(),
updated: formatISO(now) updated: now.toISOString(),
} }
} }
} }

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class TeamMemberFactory extends Factory { export class TeamMemberFactory extends Factory {
static table = 'team_members' static table = 'team_members'
@ -9,7 +8,7 @@ export class TeamMemberFactory extends Factory {
team_id: 1, team_id: 1,
user_id: 1, user_id: 1,
admin: false, admin: false,
created: formatISO(new Date()), created: new Date().toISOString(),
} }
} }
} }

View File

@ -1,7 +1,6 @@
import {faker} from '@faker-js/faker' import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from "date-fns"
export class UserFactory extends Factory { export class UserFactory extends Factory {
static table = 'users' static table = 'users'
@ -15,8 +14,8 @@ export class UserFactory extends Factory {
password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.', // 1234 password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.', // 1234
status: 0, status: 0,
issuer: 'local', issuer: 'local',
created: formatISO(now), created: now.toISOString(),
updated: formatISO(now) updated: now.toISOString(),
} }
} }
} }

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory' import {Factory} from '../support/factory'
import {formatISO} from "date-fns"
export class UserListFactory extends Factory { export class UserListFactory extends Factory {
static table = 'users_lists' static table = 'users_lists'
@ -12,8 +11,8 @@ export class UserListFactory extends Factory {
list_id: 1, list_id: 1,
user_id: 1, user_id: 1,
right: 0, right: 0,
created: formatISO(now), created: now.toISOString(),
updated: formatISO(now) updated: now.toISOString(),
} }
} }
} }

View File

@ -4,26 +4,32 @@
import {UserFactory} from '../factories/user' import {UserFactory} from '../factories/user'
let token export function login(user, cacheAcrossSpecs = false) {
if (!user) {
before(() => { throw new Error('Needs user')
const users = UserFactory.create(1) }
// Caching session when logging in via page visit
cy.session(`user__${user.username}`, () => {
cy.request('POST', `${Cypress.env('API_URL')}/login`, { cy.request('POST', `${Cypress.env('API_URL')}/login`, {
username: users[0].username, username: user.username,
password: '1234', password: '1234',
}).then(({ body }) => {
window.localStorage.setItem('token', body.token)
}) })
.its('body') }, {
.then(r => { cacheAcrossSpecs,
token = r.token
}) })
}
export function createFakeUserAndLogin() {
let user
before(() => {
user = UserFactory.create(1)[0]
}) })
beforeEach(() => { beforeEach(() => {
cy.log(`Using token ${token} to make authenticated requests`) login(user, true)
cy.visit('/', {
onBeforeLoad(win) {
win.localStorage.setItem('token', token)
},
})
}) })
return user
}

View File

@ -35,37 +35,3 @@
// } // }
// } // }
// } // }
/**
* Recursively gets an element, returning only after it's determined to be attached to the DOM for good.
*
* Source: https://github.com/cypress-io/cypress/issues/7306#issuecomment-850621378
*/
Cypress.Commands.add('getSettled', (selector, opts = {}) => {
const retries = opts.retries || 3
const delay = opts.delay || 100
const isAttached = (resolve, count = 0) => {
const el = Cypress.$(selector)
// is element attached to the DOM?
count = Cypress.dom.isAttached(el) ? count + 1 : 0
// hit our base case, return the element
if (count >= retries) {
return resolve(el)
}
// retry after a bit of a delay
setTimeout(() => isAttached(resolve, count), delay)
}
// wrap, so we can chain cypress commands off the result
return cy.wrap(null).then(() => {
return new Cypress.Promise((resolve) => {
return isAttached(resolve, 0)
}).then((el) => {
return cy.wrap(el)
})
})
})

View File

@ -1,10 +0,0 @@
{
"extends": "@vue/tsconfig/tsconfig.web.json",
"include": ["./integration/**/*", "./support/**/*"],
"compilerOptions": {
"isolatedModules": false,
"target": "es5",
"lib": ["es5", "dom"],
"types": ["cypress"]
}
}

View File

@ -4,16 +4,17 @@
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vite", "serve": "vite",
"serve:dist": "vite preview --port 4173", "preview": "vite preview --port 4173",
"serve:dist:dev": "vite preview --mode development --port 4173", "preview:dev": "vite preview --outDir dist-dev --mode development --port 4173",
"build": "vite build && workbox copyLibraries dist/", "build": "vite build && workbox copyLibraries dist/",
"build:modern-only": "BUILD_MODERN_ONLY=true vite build && workbox copyLibraries dist/", "build:modern-only": "BUILD_MODERN_ONLY=true vite build && workbox copyLibraries dist/",
"build:dev": "vite build --mode development --outDir dist-dev/", "build:dev": "vite build --mode development --outDir dist-dev/",
"lint": "eslint --ignore-pattern '*.test.*' ./src --ext .vue,.js,.ts", "lint": "eslint --ignore-pattern '*.test.*' ./src --ext .vue,.js,.ts",
"cypress:open": "cypress open", "test:e2e": "start-server-and-test preview http://127.0.0.1:4173 'cypress run --e2e --browser chrome'",
"test:unit": "vitest --run", "test:e2e-record": "start-server-and-test preview http://127.0.0.1:4173 'cypress run --e2e --browser chrome --record'",
"test:unit-watch": "vitest watch", "test:e2e-dev-dev": "start-server-and-test preview:dev http://127.0.0.1:4173 'cypress open --e2e'",
"test:frontend": "cypress run", "test:e2e-dev": "start-server-and-test preview http://127.0.0.1:4173 'cypress open --e2e'",
"test:unit": "vitest",
"typecheck": "vue-tsc --noEmit && vue-tsc --noEmit -p tsconfig.vitest.json --composite false", "typecheck": "vue-tsc --noEmit && vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
"browserslist:update": "npx browserslist@latest --update-db", "browserslist:update": "npx browserslist@latest --update-db",
"fonts:update": "pnpm run fonts:download && pnpm run fonts:subset", "fonts:update": "pnpm run fonts:download && pnpm run fonts:subset",
@ -102,6 +103,7 @@
"rollup": "3.9.0", "rollup": "3.9.0",
"rollup-plugin-visualizer": "5.9.0", "rollup-plugin-visualizer": "5.9.0",
"sass": "1.57.1", "sass": "1.57.1",
"start-server-and-test": "1.15.2",
"typescript": "4.9.4", "typescript": "4.9.4",
"vite": "4.0.3", "vite": "4.0.3",
"vite-plugin-pwa": "0.14.0", "vite-plugin-pwa": "0.14.0",

View File

@ -72,6 +72,7 @@ specifiers:
sass: 1.57.1 sass: 1.57.1
snake-case: 3.0.4 snake-case: 3.0.4
sortablejs: 1.15.0 sortablejs: 1.15.0
start-server-and-test: 1.15.2
typescript: 4.9.4 typescript: 4.9.4
ufo: 1.0.1 ufo: 1.0.1
vite: 4.0.3 vite: 4.0.3
@ -171,6 +172,7 @@ devDependencies:
rollup: 3.9.0 rollup: 3.9.0
rollup-plugin-visualizer: 5.9.0_rollup@3.9.0 rollup-plugin-visualizer: 5.9.0_rollup@3.9.0
sass: 1.57.1 sass: 1.57.1
start-server-and-test: 1.15.2
typescript: 4.9.4 typescript: 4.9.4
vite: 4.0.3_4ljv3kzetn75ixk7nciffo2yk4 vite: 4.0.3_4ljv3kzetn75ixk7nciffo2yk4
vite-plugin-pwa: 0.14.0_d6hwg7klbxt3x5xmvc2y355a7m vite-plugin-pwa: 0.14.0_d6hwg7klbxt3x5xmvc2y355a7m
@ -2159,7 +2161,7 @@ packages:
'@netlify/edge-bundler': 8.0.0 '@netlify/edge-bundler': 8.0.0
'@netlify/functions-utils': 5.1.1_supports-color@9.2.1 '@netlify/functions-utils': 5.1.1_supports-color@9.2.1
'@netlify/git-utils': 5.1.0 '@netlify/git-utils': 5.1.0
'@netlify/plugins-list': 6.59.0 '@netlify/plugins-list': 6.61.0
'@netlify/run-utils': 5.1.0 '@netlify/run-utils': 5.1.0
'@netlify/zip-it-and-ship-it': 8.2.0_supports-color@9.2.1 '@netlify/zip-it-and-ship-it': 8.2.0_supports-color@9.2.1
'@sindresorhus/slugify': 2.1.0 '@sindresorhus/slugify': 2.1.0
@ -2665,8 +2667,8 @@ packages:
resolution: {integrity: sha512-1n9VvO/9qM7cRB5f7NgSNqeUrovM7j9WVAY7ZQ4LtQuXSquFmO9Fku7WrV3zAUC6v2Y62fxGyJ0fRllYz5uXLw==} resolution: {integrity: sha512-1n9VvO/9qM7cRB5f7NgSNqeUrovM7j9WVAY7ZQ4LtQuXSquFmO9Fku7WrV3zAUC6v2Y62fxGyJ0fRllYz5uXLw==}
dev: true dev: true
/@netlify/plugins-list/6.59.0: /@netlify/plugins-list/6.61.0:
resolution: {integrity: sha512-QLS3j9jf/5Jmu9x6OY+qp8i1mSCftBgq9SmE797mHP/TRD6+00C93pIdZN9KZJRUdyy8gts9K3XSXiS23LJJWA==} resolution: {integrity: sha512-76pkuMxDdRQcAKu5WXBl24fFCzjV8rQyBS2xh/xphAntPn57uLBtQYasncTzsgGjckWwDPjwoIkmxOzi3OeqFQ==}
engines: {node: ^14.14.0 || >=16.0.0} engines: {node: ^14.14.0 || >=16.0.0}
dev: true dev: true
@ -2701,7 +2703,7 @@ packages:
junk: 4.0.0 junk: 4.0.0
locate-path: 7.1.0 locate-path: 7.1.0
merge-options: 3.0.4 merge-options: 3.0.4
minimatch: 5.1.1 minimatch: 5.1.2
normalize-path: 3.0.0 normalize-path: 3.0.0
p-map: 5.5.0 p-map: 5.5.0
path-exists: 5.0.0 path-exists: 5.0.0
@ -2742,7 +2744,7 @@ packages:
junk: 4.0.0 junk: 4.0.0
locate-path: 7.1.0 locate-path: 7.1.0
merge-options: 3.0.4 merge-options: 3.0.4
minimatch: 5.1.1 minimatch: 5.1.2
normalize-path: 3.0.0 normalize-path: 3.0.0
p-map: 5.5.0 p-map: 5.5.0
path-exists: 5.0.0 path-exists: 5.0.0
@ -3682,7 +3684,7 @@ packages:
'@vue/compiler-sfc': 3.2.45 '@vue/compiler-sfc': 3.2.45
'@vue/reactivity': 3.2.45 '@vue/reactivity': 3.2.45
'@vue/shared': 3.2.45 '@vue/shared': 3.2.45
minimatch: 5.1.1 minimatch: 5.1.2
vue-template-compiler: 2.7.14 vue-template-compiler: 2.7.14
dev: true dev: true
@ -4136,6 +4138,10 @@ packages:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
dev: true dev: true
/arg/5.0.2:
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
dev: true
/argparse/2.0.1: /argparse/2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
@ -4191,7 +4197,7 @@ packages:
dev: true dev: true
/ascii-table/0.0.9: /ascii-table/0.0.9:
resolution: {integrity: sha512-xpkr6sCDIYTPqzvjG8M3ncw1YOTaloWZOyrUmicoEifBEKzQzt+ooUpRpQ/AbOoJfO/p2ZKiyp79qHThzJDulQ==} resolution: {integrity: sha1-BqZgTWpV1L9BqaR9mHLXp42jHnM=}
dev: true dev: true
/asn1/0.2.6: /asn1/0.2.6:
@ -4278,6 +4284,14 @@ packages:
resolution: {integrity: sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==} resolution: {integrity: sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==}
dev: true dev: true
/axios/0.25.0_debug@4.3.4:
resolution: {integrity: sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==}
dependencies:
follow-redirects: 1.15.1_debug@4.3.4
transitivePeerDependencies:
- debug
dev: true
/axios/0.27.2: /axios/0.27.2:
resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==}
dependencies: dependencies:
@ -4576,7 +4590,7 @@ packages:
dev: true dev: true
/buffer-equal-constant-time/1.0.1: /buffer-equal-constant-time/1.0.1:
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} resolution: {integrity: sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=}
dev: true dev: true
/buffer-fill/1.0.0: /buffer-fill/1.0.0:
@ -5143,7 +5157,7 @@ packages:
dev: true dev: true
/concat-map/0.0.1: /concat-map/0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
dev: true dev: true
/concordance/5.0.4: /concordance/5.0.4:
@ -5213,7 +5227,7 @@ packages:
dev: true dev: true
/cookie-signature/1.0.6: /cookie-signature/1.0.6:
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} resolution: {integrity: sha1-4wOogrNCzD7oylE6eZmXNNqzriw=}
dev: true dev: true
/cookie/0.5.0: /cookie/0.5.0:
@ -5978,7 +5992,7 @@ packages:
/dom-serializer/1.3.2: /dom-serializer/1.3.2:
resolution: {integrity: sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==} resolution: {integrity: sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==}
dependencies: dependencies:
domelementtype: 2.3.0 domelementtype: 2.2.0
domhandler: 4.3.0 domhandler: 4.3.0
entities: 2.2.0 entities: 2.2.0
dev: true dev: true
@ -5991,6 +6005,10 @@ packages:
entities: 4.4.0 entities: 4.4.0
dev: true dev: true
/domelementtype/2.2.0:
resolution: {integrity: sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==}
dev: true
/domelementtype/2.3.0: /domelementtype/2.3.0:
resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
dev: true dev: true
@ -5999,7 +6017,7 @@ packages:
resolution: {integrity: sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==} resolution: {integrity: sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==}
engines: {node: '>= 4'} engines: {node: '>= 4'}
dependencies: dependencies:
domelementtype: 2.3.0 domelementtype: 2.2.0
dev: true dev: true
/domhandler/5.0.3: /domhandler/5.0.3:
@ -6017,7 +6035,7 @@ packages:
resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
dependencies: dependencies:
dom-serializer: 1.3.2 dom-serializer: 1.3.2
domelementtype: 2.3.0 domelementtype: 2.2.0
domhandler: 4.3.0 domhandler: 4.3.0
dev: true dev: true
@ -6084,6 +6102,10 @@ packages:
pify: 4.0.1 pify: 4.0.1
dev: true dev: true
/duplexer/0.1.2:
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
dev: true
/duplexer3/0.1.4: /duplexer3/0.1.4:
resolution: {integrity: sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==} resolution: {integrity: sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==}
dev: true dev: true
@ -6120,7 +6142,7 @@ packages:
dev: true dev: true
/ee-first/1.1.1: /ee-first/1.1.1:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} resolution: {integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=}
dev: true dev: true
/ejs/3.1.6: /ejs/3.1.6:
@ -6510,6 +6532,18 @@ packages:
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
dev: true dev: true
/event-stream/3.3.4:
resolution: {integrity: sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=}
dependencies:
duplexer: 0.1.2
from: 0.1.7
map-stream: 0.1.0
pause-stream: 0.0.11
split: 0.3.3
stream-combiner: 0.0.4
through: 2.3.8
dev: true
/eventemitter2/6.4.7: /eventemitter2/6.4.7:
resolution: {integrity: sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==} resolution: {integrity: sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==}
dev: true dev: true
@ -6877,7 +6911,7 @@ packages:
dev: true dev: true
/file-size/0.0.5: /file-size/0.0.5:
resolution: {integrity: sha512-ZW056dw8Ta1RWHVOQue3LMZe+mSOnHkcM7AN9is8JoHSIHRiLD5szwPAHM3fM7P5SGJ1bkAmCv3PvUTGoluDqA==} resolution: {integrity: sha1-BX1Dw6Ptc12j+Q1gUqs4Dx5tXjs=}
dev: true dev: true
/file-type/11.1.0: /file-type/11.1.0:
@ -7131,10 +7165,14 @@ packages:
dev: true dev: true
/fresh/0.5.2: /fresh/0.5.2:
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} resolution: {integrity: sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
dev: true dev: true
/from/0.1.7:
resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==}
dev: true
/from2-array/0.0.4: /from2-array/0.0.4:
resolution: {integrity: sha512-0G0cAp7sYLobH7ALsr835x98PU/YeVF7wlwxdWbCUaea7wsa7lJfKZUAo6p2YZGZ8F94luCuqHZS3JtFER6uPg==} resolution: {integrity: sha512-0G0cAp7sYLobH7ALsr835x98PU/YeVF7wlwxdWbCUaea7wsa7lJfKZUAo6p2YZGZ8F94luCuqHZS3JtFER6uPg==}
dependencies: dependencies:
@ -7385,7 +7423,7 @@ packages:
fs.realpath: 1.0.0 fs.realpath: 1.0.0
inflight: 1.0.6 inflight: 1.0.6
inherits: 2.0.4 inherits: 2.0.4
minimatch: 5.1.1 minimatch: 5.1.2
once: 1.4.0 once: 1.4.0
dev: true dev: true
@ -8531,6 +8569,16 @@ packages:
supports-color: 7.2.0 supports-color: 7.2.0
dev: true dev: true
/joi/17.6.0:
resolution: {integrity: sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==}
dependencies:
'@hapi/hoek': 9.2.1
'@hapi/topo': 5.1.0
'@sideway/address': 4.1.3
'@sideway/formula': 3.0.0
'@sideway/pinpoint': 2.0.0
dev: true
/joi/17.7.0: /joi/17.7.0:
resolution: {integrity: sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg==} resolution: {integrity: sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg==}
dependencies: dependencies:
@ -8576,7 +8624,7 @@ packages:
dev: true dev: true
/json-buffer/3.0.0: /json-buffer/3.0.0:
resolution: {integrity: sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==} resolution: {integrity: sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=}
dev: true dev: true
/json-buffer/3.0.1: /json-buffer/3.0.1:
@ -9165,6 +9213,10 @@ packages:
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dev: true dev: true
/map-stream/0.1.0:
resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==}
dev: true
/map-visit/1.0.0: /map-visit/1.0.0:
resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -9207,7 +9259,7 @@ packages:
dev: true dev: true
/media-typer/0.3.0: /media-typer/0.3.0:
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} resolution: {integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
dev: true dev: true
@ -9233,7 +9285,7 @@ packages:
dev: true dev: true
/merge-descriptors/1.0.1: /merge-descriptors/1.0.1:
resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} resolution: {integrity: sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=}
dev: true dev: true
/merge-options/3.0.4: /merge-options/3.0.4:
@ -9375,8 +9427,8 @@ packages:
brace-expansion: 1.1.11 brace-expansion: 1.1.11
dev: true dev: true
/minimatch/5.1.1: /minimatch/5.1.2:
resolution: {integrity: sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==} resolution: {integrity: sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==}
engines: {node: '>=10'} engines: {node: '>=10'}
dependencies: dependencies:
brace-expansion: 2.0.1 brace-expansion: 2.0.1
@ -9487,7 +9539,7 @@ packages:
dev: true dev: true
/mute-stream/0.0.7: /mute-stream/0.0.7:
resolution: {integrity: sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==} resolution: {integrity: sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=}
dev: true dev: true
/mute-stream/0.0.8: /mute-stream/0.0.8:
@ -10397,7 +10449,7 @@ packages:
dev: true dev: true
/path-to-regexp/0.1.7: /path-to-regexp/0.1.7:
resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} resolution: {integrity: sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=}
dev: true dev: true
/path-type/3.0.0: /path-type/3.0.0:
@ -10428,6 +10480,12 @@ packages:
resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
dev: true dev: true
/pause-stream/0.0.11:
resolution: {integrity: sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=}
dependencies:
through: 2.3.8
dev: true
/pend/1.2.0: /pend/1.2.0:
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
dev: true dev: true
@ -11007,6 +11065,14 @@ packages:
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dev: true dev: true
/ps-tree/1.2.0:
resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==}
engines: {node: '>= 0.10'}
hasBin: true
dependencies:
event-stream: 3.3.4
dev: true
/psl/1.8.0: /psl/1.8.0:
resolution: {integrity: sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==} resolution: {integrity: sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==}
dev: true dev: true
@ -11070,7 +11136,7 @@ packages:
dev: true dev: true
/querystring/0.2.0: /querystring/0.2.0:
resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==} resolution: {integrity: sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=}
engines: {node: '>=0.4.x'} engines: {node: '>=0.4.x'}
deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
dev: true dev: true
@ -11538,6 +11604,12 @@ packages:
tslib: 1.14.1 tslib: 1.14.1
dev: true dev: true
/rxjs/7.5.4:
resolution: {integrity: sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==}
dependencies:
tslib: 2.3.1
dev: true
/rxjs/7.8.0: /rxjs/7.8.0:
resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==} resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==}
dependencies: dependencies:
@ -11922,6 +11994,12 @@ packages:
extend-shallow: 3.0.2 extend-shallow: 3.0.2
dev: true dev: true
/split/0.3.3:
resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==}
dependencies:
through: 2.3.8
dev: true
/split2/1.1.1: /split2/1.1.1:
resolution: {integrity: sha512-cfurE2q8LamExY+lJ9Ex3ZfBwqAPduzOKVscPDXNCLLMvyaeD3DTz1yk7fVIs6Chco+12XeD0BB6HEoYzPYbXA==} resolution: {integrity: sha512-cfurE2q8LamExY+lJ9Ex3ZfBwqAPduzOKVscPDXNCLLMvyaeD3DTz1yk7fVIs6Chco+12XeD0BB6HEoYzPYbXA==}
dependencies: dependencies:
@ -11958,6 +12036,23 @@ packages:
resolution: {integrity: sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg==} resolution: {integrity: sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg==}
dev: true dev: true
/start-server-and-test/1.15.2:
resolution: {integrity: sha512-t5xJX04Hg7hqxiKHMJBz/n4zIMsE6G7hpAcerFAH+4Vh9le/LeyFcJERJM7WLiPygWF9TOg33oroJF1XOzJtYQ==}
engines: {node: '>=6'}
hasBin: true
dependencies:
arg: 5.0.2
bluebird: 3.7.2
check-more-types: 2.24.0
debug: 4.3.4
execa: 5.1.1
lazy-ass: 1.6.0
ps-tree: 1.2.0
wait-on: 6.0.1_debug@4.3.4
transitivePeerDependencies:
- supports-color
dev: true
/static-extend/0.1.2: /static-extend/0.1.2:
resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -11993,6 +12088,12 @@ packages:
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
dev: true dev: true
/stream-combiner/0.0.4:
resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==}
dependencies:
duplexer: 0.1.2
dev: true
/strict-uri-encode/1.1.0: /strict-uri-encode/1.1.0:
resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -12924,7 +13025,7 @@ packages:
dev: true dev: true
/utils-merge/1.0.1: /utils-merge/1.0.1:
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} resolution: {integrity: sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=}
engines: {node: '>= 0.4.0'} engines: {node: '>= 0.4.0'}
dev: true dev: true
@ -12962,7 +13063,7 @@ packages:
dev: true dev: true
/verror/1.10.0: /verror/1.10.0:
resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} resolution: {integrity: sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=}
engines: {'0': node >=0.6.0} engines: {'0': node >=0.6.0}
dependencies: dependencies:
assert-plus: 1.0.0 assert-plus: 1.0.0
@ -13212,6 +13313,20 @@ packages:
'@vue/server-renderer': 3.2.45_vue@3.2.45 '@vue/server-renderer': 3.2.45_vue@3.2.45
'@vue/shared': 3.2.45 '@vue/shared': 3.2.45
/wait-on/6.0.1_debug@4.3.4:
resolution: {integrity: sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==}
engines: {node: '>=10.0.0'}
hasBin: true
dependencies:
axios: 0.25.0_debug@4.3.4
joi: 17.6.0
lodash: 4.17.21
minimist: 1.2.7
rxjs: 7.5.4
transitivePeerDependencies:
- debug
dev: true
/wait-on/7.0.1: /wait-on/7.0.1:
resolution: {integrity: sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog==} resolution: {integrity: sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}

View File

@ -10,8 +10,6 @@
"importHelpers": true, "importHelpers": true,
"sourceMap": true, "sourceMap": true,
"strictNullChecks": true, "strictNullChecks": true,
// "allowJs": true,
// "allowSyntheticDefaultImports": true,
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]

View File

@ -1,8 +1,8 @@
{ {
"extends": "@vue/tsconfig/tsconfig.node.json", "extends": "@vue/tsconfig/tsconfig.node.json",
"include": ["vite.config.*"], "include": ["vite.config.*", "vitest.config.*", "cypress.config.*"],
"compilerOptions": { "compilerOptions": {
"composite": true, "composite": true,
"types": ["node", "vitest"] "types": ["node"]
} }
} }

View File

@ -2,7 +2,7 @@
"files": [], "files": [],
"references": [ "references": [
{ {
"path": "./tsconfig.vite-config.json" "path": "./tsconfig.config.json"
}, },
{ {
"path": "./tsconfig.app.json" "path": "./tsconfig.app.json"

View File

@ -137,6 +137,7 @@ export default defineConfig({
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'], extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
}, },
server: { server: {
host: '127.0.0.1', // see: https://github.com/vitejs/vite/pull/8543
port: 4173, port: 4173,
strictPort: true, strictPort: true,
}, },