Merge pull request #93 from mcataford/build/explore-vite-instead-of-parcel
build: explore vite instead of parcel
This commit is contained in:
commit
b243e309d7
17 changed files with 2253 additions and 3836 deletions
|
@ -4,9 +4,6 @@
|
||||||
# This is expected to run before any step logic is executed.
|
# This is expected to run before any step logic is executed.
|
||||||
#
|
#
|
||||||
|
|
||||||
env:
|
|
||||||
NODE_VERSION: lts/iron
|
|
||||||
|
|
||||||
name: 'Setup Frontend Environment'
|
name: 'Setup Frontend Environment'
|
||||||
inputs:
|
inputs:
|
||||||
task-version:
|
task-version:
|
||||||
|
@ -24,7 +21,7 @@ runs:
|
||||||
version: ${{ inputs.task-version }}
|
version: ${{ inputs.task-version }}
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: lts/iron
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
id: cache-restore
|
id: cache-restore
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
|
||||||
module.exports = {
|
|
||||||
preset: "ts-jest",
|
|
||||||
testEnvironment: "jsdom",
|
|
||||||
setupFilesAfterEnv: ["./src/tests/testSetup.ts"],
|
|
||||||
transform: {
|
|
||||||
"^.+\\.(ts|tsx)$": "ts-jest",
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -11,32 +11,30 @@
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "parcel serve src/index.html --no-cache",
|
"start": "vite ./src --config ./vite.config.js",
|
||||||
"build": "parcel build src/index.html",
|
"build": "vite build ./src",
|
||||||
"lint": "biome check src *.js --verbose && biome format src *.js --verbose",
|
"lint": "biome check src *.js --verbose && biome format src *.js --verbose",
|
||||||
"lint:fix": "biome check src ./*.js --apply --verbose && biome format src ./*.js --write --verbose",
|
"lint:fix": "biome check src ./*.js --apply --verbose && biome format src ./*.js --write --verbose",
|
||||||
"test": "yarn jest",
|
"test": "yarn vitest run src",
|
||||||
"typecheck": "yarn tsc --noEmit"
|
"typecheck": "yarn tsc --noEmit"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^1.4.1",
|
"@biomejs/biome": "^1.4.1",
|
||||||
"@parcel/core": "^2.10.3",
|
|
||||||
"@parcel/types": "^2.10.3",
|
|
||||||
"@testing-library/dom": "^9.3.3",
|
"@testing-library/dom": "^9.3.3",
|
||||||
"@testing-library/jest-dom": "^6.1.5",
|
"@testing-library/jest-dom": "^6.1.5",
|
||||||
"@testing-library/react": "^14.1.2",
|
"@testing-library/react": "^14.1.2",
|
||||||
"@testing-library/user-event": "^14.5.1",
|
"@testing-library/user-event": "^14.5.1",
|
||||||
"@types/jest": "^29.5.3",
|
"@types/mocha": "^10.0.6",
|
||||||
"@types/node": "^20.10.6",
|
"@types/node": "^20.10.6",
|
||||||
"@types/react": "^18.2.18",
|
"@types/react": "^18.2.18",
|
||||||
"@types/react-dom": "^18.2.7",
|
"@types/react-dom": "^18.2.7",
|
||||||
|
"@vitejs/plugin-basic-ssl": "^1.0.2",
|
||||||
|
"@vitejs/plugin-legacy": "^5.2.0",
|
||||||
"axios-mock-adapter": "^1.21.5",
|
"axios-mock-adapter": "^1.21.5",
|
||||||
"buffer": "^5.5.0||^6.0.0",
|
"jsdom": "^23.0.1",
|
||||||
"jest": "^29.7.0",
|
"terser": "^5.26.0",
|
||||||
"jest-environment-jsdom": "^29.7.0",
|
"typescript": "^5.3.0",
|
||||||
"parcel": "^2.10.3",
|
"vite": "^5.0.10",
|
||||||
"process": "^0.11.10",
|
"vitest": "^1.1.0"
|
||||||
"ts-jest": "^29.1.1",
|
|
||||||
"typescript": "^5.3.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { vi, expect, describe, it } from "vitest"
|
||||||
import { act } from "@testing-library/react"
|
import { act } from "@testing-library/react"
|
||||||
import { within } from "@testing-library/dom"
|
import { within } from "@testing-library/dom"
|
||||||
import userEvent from "@testing-library/user-event"
|
import userEvent from "@testing-library/user-event"
|
||||||
|
@ -19,9 +20,9 @@ describe("FileDetails", () => {
|
||||||
size: 1,
|
size: 1,
|
||||||
id: "b61bf93d-a9db-473e-822e-a65003b1b7e3",
|
id: "b61bf93d-a9db-473e-822e-a65003b1b7e3",
|
||||||
}
|
}
|
||||||
test("Clicking the download button trigger a file download", async () => {
|
it("Clicking the download button trigger a file download", async () => {
|
||||||
// FIXME: Validating file downloads is ... tricky. The current interaction with dynamically created DOM
|
// FIXME: Validating file downloads is ... tricky. The current interaction with dynamically created DOM
|
||||||
// elements is not visible by jest.
|
// elements is not visible by vi.
|
||||||
|
|
||||||
const expectedUrlPattern = new RegExp(`/files/${mockItem.id}/content/$`)
|
const expectedUrlPattern = new RegExp(`/files/${mockItem.id}/content/$`)
|
||||||
|
|
||||||
|
@ -29,12 +30,10 @@ describe("FileDetails", () => {
|
||||||
|
|
||||||
axiosMock.onGet(expectedUrlPattern).reply(200, mockItem)
|
axiosMock.onGet(expectedUrlPattern).reply(200, mockItem)
|
||||||
|
|
||||||
jest
|
vi.spyOn(fileQueries, "useFileDetails").mockReturnValue({
|
||||||
.spyOn(fileQueries, "useFileDetails")
|
data: mockItem,
|
||||||
.mockReturnValue({ data: mockItem, isLoading: false } as UseQueryResult<
|
isLoading: false,
|
||||||
FileData,
|
} as UseQueryResult<FileData, unknown>)
|
||||||
unknown
|
|
||||||
>)
|
|
||||||
const user = userEvent.setup()
|
const user = userEvent.setup()
|
||||||
|
|
||||||
const { getByLabelText, debug, rerender } = render(
|
const { getByLabelText, debug, rerender } = render(
|
||||||
|
@ -54,19 +53,17 @@ describe("FileDetails", () => {
|
||||||
expect(downloadRequest.url).toMatch(expectedUrlPattern)
|
expect(downloadRequest.url).toMatch(expectedUrlPattern)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("Clicking the delete button fires request to delete file", async () => {
|
it("Clicking the delete button fires request to delete file", async () => {
|
||||||
const expectedUrlPattern = new RegExp(`/files/${mockItem.id}/$`)
|
const expectedUrlPattern = new RegExp(`/files/${mockItem.id}/$`)
|
||||||
|
|
||||||
const axiosMock = getAxiosMockAdapter()
|
const axiosMock = getAxiosMockAdapter()
|
||||||
|
|
||||||
axiosMock.onDelete(expectedUrlPattern).reply(200, mockItem)
|
axiosMock.onDelete(expectedUrlPattern).reply(200, mockItem)
|
||||||
|
|
||||||
jest
|
vi.spyOn(fileQueries, "useFileDetails").mockReturnValue({
|
||||||
.spyOn(fileQueries, "useFileDetails")
|
data: mockItem,
|
||||||
.mockReturnValue({ data: mockItem, isLoading: false } as UseQueryResult<
|
isLoading: false,
|
||||||
FileData,
|
} as UseQueryResult<FileData, unknown>)
|
||||||
unknown
|
|
||||||
>)
|
|
||||||
const user = userEvent.setup()
|
const user = userEvent.setup()
|
||||||
|
|
||||||
const { getByLabelText, debug, rerender } = render(
|
const { getByLabelText, debug, rerender } = render(
|
||||||
|
@ -86,22 +83,20 @@ describe("FileDetails", () => {
|
||||||
expect(deleteRequest.url).toMatch(expectedUrlPattern)
|
expect(deleteRequest.url).toMatch(expectedUrlPattern)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("Clicking the delete button redirects to the file list after success", async () => {
|
it("Clicking the delete button redirects to the file list after success", async () => {
|
||||||
const expectedUrlPattern = new RegExp(`/files/${mockItem.id}/$`)
|
const expectedUrlPattern = new RegExp(`/files/${mockItem.id}/$`)
|
||||||
|
|
||||||
const axiosMock = getAxiosMockAdapter()
|
const axiosMock = getAxiosMockAdapter()
|
||||||
|
|
||||||
axiosMock.onDelete(expectedUrlPattern).reply(200, mockItem)
|
axiosMock.onDelete(expectedUrlPattern).reply(200, mockItem)
|
||||||
|
|
||||||
jest
|
vi.spyOn(fileQueries, "useFileDetails").mockReturnValue({
|
||||||
.spyOn(fileQueries, "useFileDetails")
|
data: mockItem,
|
||||||
.mockReturnValue({ data: mockItem, isLoading: false } as UseQueryResult<
|
isLoading: false,
|
||||||
FileData,
|
} as UseQueryResult<FileData, unknown>)
|
||||||
unknown
|
|
||||||
>)
|
|
||||||
|
|
||||||
const navigateMock = jest.fn().mockImplementation((a: string) => {})
|
const navigateMock = vi.fn().mockImplementation((a: string) => {})
|
||||||
jest.spyOn(locationContextUtils, "useLocationContext").mockReturnValue({
|
vi.spyOn(locationContextUtils, "useLocationContext").mockReturnValue({
|
||||||
location: {
|
location: {
|
||||||
path: "",
|
path: "",
|
||||||
label: null,
|
label: null,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { expect, describe, it, vi } from "vitest"
|
||||||
import { within } from "@testing-library/dom"
|
import { within } from "@testing-library/dom"
|
||||||
import userEvent from "@testing-library/user-event"
|
import userEvent from "@testing-library/user-event"
|
||||||
|
|
||||||
|
@ -28,14 +29,14 @@ describe("FileList", () => {
|
||||||
{ title: "Async Item 0", filename: "async.txt", size: 2, type: "upload" },
|
{ title: "Async Item 0", filename: "async.txt", size: 2, type: "upload" },
|
||||||
]
|
]
|
||||||
|
|
||||||
test("Renders list items provided", () => {
|
it("Renders list items provided", () => {
|
||||||
const { getAllByText } = render(<FileList data={mockItems} />)
|
const { getAllByText } = render(<FileList data={mockItems} />)
|
||||||
const renderedItems = getAllByText(/Item/)
|
const renderedItems = getAllByText(/Item/)
|
||||||
|
|
||||||
expect(renderedItems.length).toEqual(mockItems.length)
|
expect(renderedItems.length).toEqual(mockItems.length)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("Prepends items in flight as tracked by async task context", () => {
|
it("Prepends items in flight as tracked by async task context", () => {
|
||||||
const { getAllByText, getByText } = render(
|
const { getAllByText, getByText } = render(
|
||||||
<FileList data={[mockItems[0]]} />,
|
<FileList data={[mockItems[0]]} />,
|
||||||
{ asyncTaskContext: mockAsyncTasks },
|
{ asyncTaskContext: mockAsyncTasks },
|
||||||
|
@ -50,7 +51,7 @@ describe("FileList", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("FileListItem", () => {
|
describe("FileListItem", () => {
|
||||||
test("Renders the item title", () => {
|
it("Renders the item title", () => {
|
||||||
const { getByLabelText, debug } = render(
|
const { getByLabelText, debug } = render(
|
||||||
<FileList data={[mockItems[0]]} />,
|
<FileList data={[mockItems[0]]} />,
|
||||||
)
|
)
|
||||||
|
@ -58,7 +59,7 @@ describe("FileList", () => {
|
||||||
within(title).getByText(mockItems[0].title)
|
within(title).getByText(mockItems[0].title)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("Renders the item size", () => {
|
it("Renders the item size", () => {
|
||||||
const { getByLabelText, debug } = render(
|
const { getByLabelText, debug } = render(
|
||||||
<FileList data={[mockItems[0]]} />,
|
<FileList data={[mockItems[0]]} />,
|
||||||
)
|
)
|
||||||
|
@ -66,7 +67,7 @@ describe("FileList", () => {
|
||||||
within(title).getByText(`${mockItems[0].size} B`)
|
within(title).getByText(`${mockItems[0].size} B`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test.each(["download item", "delete item"])(
|
it.each(["download item", "delete item"])(
|
||||||
"Renders secondary action buttons (%s)",
|
"Renders secondary action buttons (%s)",
|
||||||
(action) => {
|
(action) => {
|
||||||
const { getByLabelText, debug } = render(
|
const { getByLabelText, debug } = render(
|
||||||
|
@ -76,7 +77,7 @@ describe("FileList", () => {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
test("Clicking the delete button fires request to delete file", async () => {
|
it("Clicking the delete button fires request to delete file", async () => {
|
||||||
const expectedUrlPattern = new RegExp(`/files/${mockItems[0].id}/$`)
|
const expectedUrlPattern = new RegExp(`/files/${mockItems[0].id}/$`)
|
||||||
|
|
||||||
const axiosMock = getAxiosMockAdapter()
|
const axiosMock = getAxiosMockAdapter()
|
||||||
|
@ -101,9 +102,9 @@ describe("FileList", () => {
|
||||||
expect(deleteRequest.url).toMatch(expectedUrlPattern)
|
expect(deleteRequest.url).toMatch(expectedUrlPattern)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("Clicking the download button trigger a file download", async () => {
|
it("Clicking the download button trigger a file download", async () => {
|
||||||
// FIXME: Validating file downloads is ... tricky. The current interaction with dynamically created DOM
|
// FIXME: Validating file downloads is ... tricky. The current interaction with dynamically created DOM
|
||||||
// elements is not visible by jest.
|
// elements is not visible by vi.
|
||||||
const expectedUrlPattern = new RegExp(
|
const expectedUrlPattern = new RegExp(
|
||||||
`/files/${mockItems[0].id}/content/$`,
|
`/files/${mockItems[0].id}/content/$`,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { vi, expect, describe, it, afterEach } from "vitest"
|
||||||
import { render, screen, waitFor } from "@testing-library/react"
|
import { render, screen, waitFor } from "@testing-library/react"
|
||||||
import { QueryClientProvider, QueryClient } from "@tanstack/react-query"
|
import { QueryClientProvider, QueryClient } from "@tanstack/react-query"
|
||||||
import AxiosMockAdapter from "axios-mock-adapter"
|
import AxiosMockAdapter from "axios-mock-adapter"
|
||||||
|
@ -21,11 +22,11 @@ function renderComponent() {
|
||||||
|
|
||||||
describe("FileListView", () => {
|
describe("FileListView", () => {
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.resetAllMocks()
|
vi.resetAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("renders no sidebar if no item is in the path", async () => {
|
it("renders no sidebar if no item is in the path", async () => {
|
||||||
jest.spyOn(globalThis, "location", "get").mockReturnValue({
|
vi.spyOn(globalThis, "location", "get").mockReturnValue({
|
||||||
...globalThis.location,
|
...globalThis.location,
|
||||||
pathname: "/",
|
pathname: "/",
|
||||||
})
|
})
|
||||||
|
@ -54,7 +55,7 @@ describe("FileListView", () => {
|
||||||
|
|
||||||
it("renders a sidebar if an item is selected", async () => {
|
it("renders a sidebar if an item is selected", async () => {
|
||||||
const mockItemId = "b61bf93d-a9db-473e-822e-a65003b1b7e3"
|
const mockItemId = "b61bf93d-a9db-473e-822e-a65003b1b7e3"
|
||||||
jest.spyOn(globalThis, "location", "get").mockReturnValue({
|
vi.spyOn(globalThis, "location", "get").mockReturnValue({
|
||||||
...globalThis.location,
|
...globalThis.location,
|
||||||
pathname: `/item/${mockItemId}/`,
|
pathname: `/item/${mockItemId}/`,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { expect, describe, it, vi } from "vitest"
|
||||||
|
|
||||||
import { render, screen, waitFor } from "@testing-library/react"
|
import { render, screen, waitFor } from "@testing-library/react"
|
||||||
import userEvent from "@testing-library/user-event"
|
import userEvent from "@testing-library/user-event"
|
||||||
import { QueryClientProvider, QueryClient } from "@tanstack/react-query"
|
import { QueryClientProvider, QueryClient } from "@tanstack/react-query"
|
||||||
|
@ -41,7 +43,7 @@ describe("LoginView", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it("renders a registration link", async () => {
|
it("renders a registration link", async () => {
|
||||||
const mock = jest.fn()
|
const mock = vi.fn()
|
||||||
const { user } = renderComponent()
|
const { user } = renderComponent()
|
||||||
|
|
||||||
expect(screen.getByText(/don\'t have an account yet?/i)).toBeInTheDocument()
|
expect(screen.getByText(/don\'t have an account yet?/i)).toBeInTheDocument()
|
||||||
|
@ -113,8 +115,8 @@ describe("LoginView", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it("redirects the user on success", async () => {
|
it("redirects the user on success", async () => {
|
||||||
const mockNavigate = jest.fn()
|
const mockNavigate = vi.fn()
|
||||||
const mockLocationHook = jest
|
const mockLocationHook = vi
|
||||||
.spyOn(locationHook, "useLocationContext")
|
.spyOn(locationHook, "useLocationContext")
|
||||||
.mockImplementation(() => ({
|
.mockImplementation(() => ({
|
||||||
location: {
|
location: {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { vi, it, describe, expect } from "vitest"
|
||||||
import { within } from "@testing-library/dom"
|
import { within } from "@testing-library/dom"
|
||||||
import userEvent from "@testing-library/user-event"
|
import userEvent from "@testing-library/user-event"
|
||||||
|
|
||||||
|
@ -11,12 +12,12 @@ import { type FileData } from "../../types/files"
|
||||||
|
|
||||||
describe("NavigationBar", () => {
|
describe("NavigationBar", () => {
|
||||||
describe("Upload functionality", () => {
|
describe("Upload functionality", () => {
|
||||||
test("Renders the upload button", () => {
|
it("Renders the upload button", () => {
|
||||||
const { getByText } = render(<NavigationBar />)
|
const { getByText } = render(<NavigationBar />)
|
||||||
getByText("Upload file")
|
getByText("Upload file")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("Clicking the upload button and selecting a file POSTs the file", async () => {
|
it("Clicking the upload button and selecting a file POSTs the file", async () => {
|
||||||
const axiosMock = getAxiosMockAdapter()
|
const axiosMock = getAxiosMockAdapter()
|
||||||
const expectedUrlPattern = new RegExp("/files/$")
|
const expectedUrlPattern = new RegExp("/files/$")
|
||||||
axiosMock.onPost(expectedUrlPattern).reply(200, {
|
axiosMock.onPost(expectedUrlPattern).reply(200, {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { expect, it, vi, describe } from "vitest"
|
||||||
import { screen, render, waitFor } from "@testing-library/react"
|
import { screen, render, waitFor } from "@testing-library/react"
|
||||||
import userEvent from "@testing-library/user-event"
|
import userEvent from "@testing-library/user-event"
|
||||||
import { QueryClientProvider, QueryClient } from "@tanstack/react-query"
|
import { QueryClientProvider, QueryClient } from "@tanstack/react-query"
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { describe, it, expect } from "vitest"
|
||||||
import { validateEmail, validatePassword } from "./validation"
|
import { validateEmail, validatePassword } from "./validation"
|
||||||
|
|
||||||
describe("Email address format validation", () => {
|
describe("Email address format validation", () => {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { describe, it, expect, vi } from "vitest"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import { screen, render, waitFor } from "@testing-library/react"
|
import { screen, render, waitFor } from "@testing-library/react"
|
||||||
import userEvent from "@testing-library/user-event"
|
import userEvent from "@testing-library/user-event"
|
||||||
|
@ -46,7 +47,7 @@ function renderComponent(props?: Partial<TextInputProps>) {
|
||||||
|
|
||||||
describe("TextInput", () => {
|
describe("TextInput", () => {
|
||||||
it("runs the provided onChange on input", async () => {
|
it("runs the provided onChange on input", async () => {
|
||||||
const mockOnChange = jest.fn()
|
const mockOnChange = vi.fn()
|
||||||
const mockInput = "testinput"
|
const mockInput = "testinput"
|
||||||
|
|
||||||
const { user } = renderComponent({ onChange: mockOnChange })
|
const { user } = renderComponent({ onChange: mockOnChange })
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import React from "react"
|
||||||
|
import { describe, expect, it } from "vitest"
|
||||||
import { render, screen } from "@testing-library/react"
|
import { render, screen } from "@testing-library/react"
|
||||||
|
|
||||||
import Route from "./Route"
|
import Route from "./Route"
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { afterEach, describe, it, vi, expect } from "vitest"
|
||||||
import { render, screen } from "@testing-library/react"
|
import { render, screen } from "@testing-library/react"
|
||||||
|
|
||||||
import { LocationContext } from "../contexts/LocationContext"
|
import { LocationContext } from "../contexts/LocationContext"
|
||||||
|
@ -10,17 +11,17 @@ function renderComponent(component: React.ReactElement) {
|
||||||
|
|
||||||
describe("Router", () => {
|
describe("Router", () => {
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.resetAllMocks()
|
vi.resetAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("throws an error if no Route exists for the given location", () => {
|
it("throws an error if no Route exists for the given location", () => {
|
||||||
jest.spyOn(globalThis, "location", "get").mockReturnValue({
|
vi.spyOn(globalThis, "location", "get").mockReturnValue({
|
||||||
...globalThis.location,
|
...globalThis.location,
|
||||||
pathname: "/doesnotexist",
|
pathname: "/doesnotexist",
|
||||||
})
|
})
|
||||||
|
|
||||||
// Silence the error to avoid logspam in tests.
|
// Silence the error to avoid logspam in tests.
|
||||||
jest.spyOn(console, "error").mockImplementation(() => {})
|
vi.spyOn(console, "error").mockImplementation(() => {})
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
renderComponent(
|
renderComponent(
|
||||||
|
@ -34,7 +35,7 @@ describe("Router", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it("renders the route matching the given location", () => {
|
it("renders the route matching the given location", () => {
|
||||||
jest.spyOn(globalThis, "location", "get").mockReturnValue({
|
vi.spyOn(globalThis, "location", "get").mockReturnValue({
|
||||||
...globalThis.location,
|
...globalThis.location,
|
||||||
pathname: "/exists",
|
pathname: "/exists",
|
||||||
})
|
})
|
||||||
|
@ -51,7 +52,7 @@ describe("Router", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it("only renders the route that matches", () => {
|
it("only renders the route that matches", () => {
|
||||||
jest.spyOn(globalThis, "location", "get").mockReturnValue({
|
vi.spyOn(globalThis, "location", "get").mockReturnValue({
|
||||||
...globalThis.location,
|
...globalThis.location,
|
||||||
pathname: "/matches",
|
pathname: "/matches",
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
import { vi } from "vitest"
|
||||||
import "@testing-library/jest-dom"
|
import "@testing-library/jest-dom"
|
||||||
|
|
||||||
// URL.createObjectURL does not exist in jest-jsdom.
|
// URL.createObjectURL does not exist in jest-jsdom.
|
||||||
globalThis.URL.createObjectURL = jest
|
globalThis.URL.createObjectURL = vi
|
||||||
.fn()
|
.fn()
|
||||||
.mockImplementation(() => "http://localhost/downloadUrl")
|
.mockImplementation(() => "http://localhost/downloadUrl")
|
||||||
|
|
||||||
// Clicking DOM objects is not implemented in jest-jsdom.
|
// Clicking DOM objects is not implemented in jest-jsdom.
|
||||||
HTMLAnchorElement.prototype.click = jest.fn()
|
HTMLAnchorElement.prototype.click = vi.fn()
|
||||||
|
|
|
@ -11,6 +11,6 @@
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"types": ["jest", "node"]
|
"types": ["node", "mocha"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
19
frontend/vite.config.js
Normal file
19
frontend/vite.config.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import legacy from "@vitejs/plugin-legacy"
|
||||||
|
import basicSSL from "@vitejs/plugin-basic-ssl"
|
||||||
|
|
||||||
|
import { defineConfig } from "vite"
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [legacy(), basicSSL()],
|
||||||
|
server: {
|
||||||
|
port: 1234,
|
||||||
|
strictPort: true,
|
||||||
|
https: false,
|
||||||
|
},
|
||||||
|
test: {
|
||||||
|
environment: "jsdom",
|
||||||
|
setupFiles: ["./src/tests/testSetup.ts"],
|
||||||
|
testMatch: ["./src/**/*.test.tsx?"],
|
||||||
|
globals: true,
|
||||||
|
},
|
||||||
|
})
|
5927
frontend/yarn.lock
5927
frontend/yarn.lock
File diff suppressed because it is too large
Load diff
Reference in a new issue