From b0302ac52cb90935da802b2069af82ef6fe60be0 Mon Sep 17 00:00:00 2001 From: Stefan Verhoeven Date: Thu, 6 Apr 2023 08:08:28 +0200 Subject: [PATCH 01/13] Page to show report.html files --- app/models/job.server.ts | 10 ++++++++++ app/routes/jobs/$id.tsx | 11 ++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/app/models/job.server.ts b/app/models/job.server.ts index f6b9fde9..fb62cd6c 100644 --- a/app/models/job.server.ts +++ b/app/models/job.server.ts @@ -44,3 +44,13 @@ export async function getJobfile(jobid: number, path: string, accessToken: strin return response.raw; } +export async function getHTMLfiles(jobid: number, accessToken: string) { + const api = buildJobApi(accessToken) + const items = await api.retrieveJobDirectoriesFromPathApiJobJobidDirectoriesPathGet({ + jobid, + path: 'output', + maxDepth: 3 + }) + // Filter on html files + return items +} \ No newline at end of file diff --git a/app/routes/jobs/$id.tsx b/app/routes/jobs/$id.tsx index 904fc595..b041a78d 100644 --- a/app/routes/jobs/$id.tsx +++ b/app/routes/jobs/$id.tsx @@ -4,14 +4,14 @@ import { getAccessToken } from "~/token.server"; import { applicationByName } from "~/models/applicaton.server"; import { getJobById } from "~/models/job.server"; import { CompletedJobs } from "~/utils"; +import { checkAuthenticated } from "~/models/user.server"; export const loader = async ({ params, request }: LoaderArgs) => { const job_id = params.id || ""; - const access_token = await getAccessToken(request); - if (access_token === undefined) { - throw new Error("Unauthenticated"); - } - const job = await getJobById(parseInt(job_id), access_token); + const accessToken = await getAccessToken(request); + checkAuthenticated(accessToken); + const job = await getJobById(parseInt(job_id), accessToken!); + // TODO check if job belongs to user const app = await applicationByName(job.application); return json({ job, app }); }; @@ -49,6 +49,7 @@ export default function JobPage() { {app.config}

+

Result

)} From 274eabe98d0e48823e16de0705b7bb719fb92afe Mon Sep 17 00:00:00 2001 From: Stefan Verhoeven Date: Thu, 6 Apr 2023 15:30:21 +0200 Subject: [PATCH 02/13] List all report.html on job page. --- app/components/ListReportFiles.tsx | 29 ++++++++++ app/models/application.server.test.ts | 2 +- app/models/applicaton.server.ts | 24 ++++++--- app/models/constants.ts | 3 ++ app/models/job.server.ts | 5 +- app/routes/jobs/$id.tsx | 77 ++++++++++++++++----------- app/routes/jobs/index.tsx | 18 +++++-- 7 files changed, 116 insertions(+), 42 deletions(-) create mode 100644 app/components/ListReportFiles.tsx create mode 100644 app/models/constants.ts diff --git a/app/components/ListReportFiles.tsx b/app/components/ListReportFiles.tsx new file mode 100644 index 00000000..62fec222 --- /dev/null +++ b/app/components/ListReportFiles.tsx @@ -0,0 +1,29 @@ +import { useMemo } from "react"; +import type { DirectoryItem } from "~/bartender-client"; + +export function ListReportFiles({ files, prefix }: { files: DirectoryItem, prefix: string }) { + const htmlFiles: [string, DirectoryItem[]][] = useMemo(() => { + if (!files.children) { + return []; + } + const analyisRoot = files.children.find((i) => i.name === "analysis"); + if (!analyisRoot|| !analyisRoot.children) { + return []; + } + return analyisRoot.children.map((module) => { + if (!module.children) { + return [module.name, []] + } + const htmls = module.children.filter((file) => file.name.endsWith("report.html")) + .map((file) => file); + return [module.name, htmls]; + }); + }, [files]); + return ( + + ); +} diff --git a/app/models/application.server.test.ts b/app/models/application.server.test.ts index 631d6b5f..960c9107 100644 --- a/app/models/application.server.test.ts +++ b/app/models/application.server.test.ts @@ -3,8 +3,8 @@ import { assert, describe, test } from "vitest"; import { rewriteConfigInArchive, - WORKFLOW_CONFIG_FILENAME, } from "./applicaton.server"; +import { WORKFLOW_CONFIG_FILENAME } from "./constants"; const HY3_PDB = `\ ATOM 1 SHA SHA S 1 30.913 40.332 2.133 1.00 36.12 S diff --git a/app/models/applicaton.server.ts b/app/models/applicaton.server.ts index dd5d7f3f..d25eafbf 100644 --- a/app/models/applicaton.server.ts +++ b/app/models/applicaton.server.ts @@ -4,9 +4,7 @@ import { stringify, parse } from "@ltd/j-toml"; import { ApplicationApi } from "~/bartender-client/apis/ApplicationApi"; import type { JobModelDTO } from "~/bartender-client/models/JobModelDTO"; import { buildConfig } from "./config.server"; - -export const WORKFLOW_CONFIG_FILENAME = "workflow.cfg"; -const JOB_OUTPUT_DIR = "output"; +import { JOB_OUTPUT_DIR, WORKFLOW_CONFIG_FILENAME } from './constants'; function buildApplicationApi(accessToken: string = "") { return new ApplicationApi(buildConfig(accessToken)); @@ -30,11 +28,21 @@ export async function submitJob( accessToken: string ) { const api = buildApplicationApi(accessToken); - const rewritten_upload = await rewriteConfigInArchive(upload); + const rewritten_upload = new File([await rewriteConfigInArchive(upload)], upload.name, { + type: upload.type, + lastModified: upload.lastModified, + }); const response = await api.uploadJobApiApplicationApplicationJobPutRaw({ application, upload: rewritten_upload, }); + if (!response.raw.ok) { + console.log([ + response.raw.status, + response.raw.statusText, + await response.raw.text() + ]); + } const job: JobModelDTO = await response.raw.json(); return job; } @@ -52,7 +60,11 @@ export async function submitJob( * @param config_body Body of workflow config file to rewrite * @returns The rewritten config file */ -function rewriteConfig(config_body: string) { +async function rewriteConfig(config_body: string) { + // TODO handle config file with duplicated sections + // use dedupWorkflow from https://github.com/i-VRESSE/workflow-builder/blob/807a2007963376906d801f20ac3731eb2b49429a/packages/core/src/toml.ts#L258 + // Got stuck on papaparse import error + // so for now use workflow-builder web app to dedup the config file by uploading and downloading it const table = parse(config_body, { bigint: false }); table.run_dir = JOB_OUTPUT_DIR; table.mode = "local"; @@ -87,7 +99,7 @@ export async function rewriteConfigInArchive(upload: Blob) { // TODO validate config using catalog and ajv - const new_config = rewriteConfig(config_body); + const new_config = await rewriteConfig(config_body); zip.file(WORKFLOW_CONFIG_FILENAME, new_config); return await zip.generateAsync({type: "blob"}); diff --git a/app/models/constants.ts b/app/models/constants.ts new file mode 100644 index 00000000..c288857a --- /dev/null +++ b/app/models/constants.ts @@ -0,0 +1,3 @@ + +export const WORKFLOW_CONFIG_FILENAME = "workflow.cfg"; +export const JOB_OUTPUT_DIR = "output"; diff --git a/app/models/job.server.ts b/app/models/job.server.ts index fb62cd6c..2368ed7e 100644 --- a/app/models/job.server.ts +++ b/app/models/job.server.ts @@ -1,5 +1,6 @@ import { JobApi } from "~/bartender-client/apis/JobApi"; import { buildConfig } from "./config.server"; +import { JOB_OUTPUT_DIR } from "./constants"; function buildJobApi(accessToken: string = '') { return new JobApi(buildConfig(accessToken)); @@ -44,11 +45,11 @@ export async function getJobfile(jobid: number, path: string, accessToken: strin return response.raw; } -export async function getHTMLfiles(jobid: number, accessToken: string) { +export async function listOutputFiles(jobid: number, accessToken: string) { const api = buildJobApi(accessToken) const items = await api.retrieveJobDirectoriesFromPathApiJobJobidDirectoriesPathGet({ jobid, - path: 'output', + path: JOB_OUTPUT_DIR, maxDepth: 3 }) // Filter on html files diff --git a/app/routes/jobs/$id.tsx b/app/routes/jobs/$id.tsx index b041a78d..8ebeaaea 100644 --- a/app/routes/jobs/$id.tsx +++ b/app/routes/jobs/$id.tsx @@ -1,56 +1,73 @@ import { json, type LoaderArgs } from "@remix-run/node"; -import { Link, useLoaderData } from "@remix-run/react"; +import { useLoaderData } from "@remix-run/react"; import { getAccessToken } from "~/token.server"; -import { applicationByName } from "~/models/applicaton.server"; -import { getJobById } from "~/models/job.server"; +import { WORKFLOW_CONFIG_FILENAME } from "~/models/constants"; +import { listOutputFiles, getJobById } from "~/models/job.server"; import { CompletedJobs } from "~/utils"; import { checkAuthenticated } from "~/models/user.server"; +import type { DirectoryItem } from "~/bartender-client"; +import { ListReportFiles } from "~/components/ListReportFiles"; export const loader = async ({ params, request }: LoaderArgs) => { - const job_id = params.id || ""; + const jobId = parseInt(params.id || ""); const accessToken = await getAccessToken(request); checkAuthenticated(accessToken); - const job = await getJobById(parseInt(job_id), accessToken!); + const job = await getJobById(jobId, accessToken!); // TODO check if job belongs to user - const app = await applicationByName(job.application); - return json({ job, app }); + let outputFiles: DirectoryItem | undefined = undefined; + if (CompletedJobs.has(job.state)) { + outputFiles = await listOutputFiles(jobId, accessToken!); + } + return json({ job, outputFiles}); }; export default function JobPage() { - const { job, app } = useLoaderData(); + const { job, outputFiles } = useLoaderData(); return ( -
-

- Application: - {job.application} -

+
+

State: {job.state}

-

createdOn: {job.createdOn}

-

updatedOn: {job.updatedOn}

+

Created on: {job.createdOn}

+

Updated on: {job.updatedOn}

Name: {job.name}

+
+
+

Input

+ +
{CompletedJobs.has(job.state) && ( - <> -

+

)}
); diff --git a/app/routes/jobs/index.tsx b/app/routes/jobs/index.tsx index eac5785c..392b59d4 100644 --- a/app/routes/jobs/index.tsx +++ b/app/routes/jobs/index.tsx @@ -16,12 +16,14 @@ export default function JobPage() { const { jobs } = useLoaderData(); return (
- +
+ + @@ -30,8 +32,18 @@ export default function JobPage() { - - + + + + ))} From 091a363cd376c75ceeea7721149a69ee781b1676 Mon Sep 17 00:00:00 2001 From: Stefan Verhoeven Date: Thu, 6 Apr 2023 15:40:37 +0200 Subject: [PATCH 03/13] Open report.html in new tab --- app/components/ListReportFiles.tsx | 2 +- app/routes/jobs/$id.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/ListReportFiles.tsx b/app/components/ListReportFiles.tsx index 62fec222..2bb7d05c 100644 --- a/app/components/ListReportFiles.tsx +++ b/app/components/ListReportFiles.tsx @@ -22,7 +22,7 @@ export function ListReportFiles({ files, prefix }: { files: DirectoryItem, prefi return (
    {htmlFiles.map(([module, htmls]) => { - return
  • {module}
  • ; + return
  • {module}
  • ; })}
); diff --git a/app/routes/jobs/$id.tsx b/app/routes/jobs/$id.tsx index 8ebeaaea..c019dba0 100644 --- a/app/routes/jobs/$id.tsx +++ b/app/routes/jobs/$id.tsx @@ -24,7 +24,7 @@ export const loader = async ({ params, request }: LoaderArgs) => { export default function JobPage() { const { job, outputFiles } = useLoaderData(); return ( -
+

State: {job.state}

Created on: {job.createdOn}

From 4c69813bf03c34140a97b15b8bf9ae6d19f8ee86 Mon Sep 17 00:00:00 2001 From: Stefan Verhoeven Date: Thu, 6 Apr 2023 15:58:34 +0200 Subject: [PATCH 04/13] This web app is haddock3 only, remove any multi bartender application items --- app/components/Haddock3/Form.client.tsx | 2 +- app/components/Navbar.tsx | 4 ++-- app/models/applicaton.server.ts | 17 ++------------ app/models/constants.ts | 1 + app/routes/{applications => }/builder.tsx | 16 +++++++------- app/routes/index.tsx | 4 ++-- app/routes/jobs/$id.tsx | 4 ++-- app/routes/{applications => }/upload.tsx | 27 +++++++++++------------ 8 files changed, 31 insertions(+), 44 deletions(-) rename app/routes/{applications => }/builder.tsx (85%) rename app/routes/{applications => }/upload.tsx (73%) diff --git a/app/components/Haddock3/Form.client.tsx b/app/components/Haddock3/Form.client.tsx index cb382a65..90946c32 100644 --- a/app/components/Haddock3/Form.client.tsx +++ b/app/components/Haddock3/Form.client.tsx @@ -10,7 +10,7 @@ import { prepareCatalog } from "@i-vresse/wb-core/dist/catalog"; import { useEffect } from "react"; import { WorkflowSubmitButton } from "./SubmitButton"; import { useLoaderData } from "@remix-run/react"; -import type { loader } from "~/routes/applications/builder"; +import type { loader } from "~/routes/builder"; import { WorkflowDownloadButton } from "./DownloadButton"; import { FormActions } from "./FormActions"; diff --git a/app/components/Navbar.tsx b/app/components/Navbar.tsx index 5c83c572..0d39b02e 100644 --- a/app/components/Navbar.tsx +++ b/app/components/Navbar.tsx @@ -46,10 +46,10 @@ export const Navbar = () => {
  • - Build + Build
  • - Upload + Upload
  • Manage diff --git a/app/models/applicaton.server.ts b/app/models/applicaton.server.ts index d25eafbf..442f72f0 100644 --- a/app/models/applicaton.server.ts +++ b/app/models/applicaton.server.ts @@ -4,17 +4,12 @@ import { stringify, parse } from "@ltd/j-toml"; import { ApplicationApi } from "~/bartender-client/apis/ApplicationApi"; import type { JobModelDTO } from "~/bartender-client/models/JobModelDTO"; import { buildConfig } from "./config.server"; -import { JOB_OUTPUT_DIR, WORKFLOW_CONFIG_FILENAME } from './constants'; +import { BARTENDER_APPLICATION_NAME, JOB_OUTPUT_DIR, WORKFLOW_CONFIG_FILENAME } from './constants'; function buildApplicationApi(accessToken: string = "") { return new ApplicationApi(buildConfig(accessToken)); } -export async function applicationNames() { - const api = buildApplicationApi(); - return await api.listApplicationsApiApplicationGet(); -} - export async function applicationByName(name: string) { const api = buildApplicationApi(); return await api.getApplicationApiApplicationApplicationGet({ @@ -23,7 +18,6 @@ export async function applicationByName(name: string) { } export async function submitJob( - application: string, upload: File, accessToken: string ) { @@ -33,16 +27,9 @@ export async function submitJob( lastModified: upload.lastModified, }); const response = await api.uploadJobApiApplicationApplicationJobPutRaw({ - application, + application: BARTENDER_APPLICATION_NAME, upload: rewritten_upload, }); - if (!response.raw.ok) { - console.log([ - response.raw.status, - response.raw.statusText, - await response.raw.text() - ]); - } const job: JobModelDTO = await response.raw.json(); return job; } diff --git a/app/models/constants.ts b/app/models/constants.ts index c288857a..97037726 100644 --- a/app/models/constants.ts +++ b/app/models/constants.ts @@ -1,3 +1,4 @@ +export const BARTENDER_APPLICATION_NAME = "haddock3"; export const WORKFLOW_CONFIG_FILENAME = "workflow.cfg"; export const JOB_OUTPUT_DIR = "output"; diff --git a/app/routes/applications/builder.tsx b/app/routes/builder.tsx similarity index 85% rename from app/routes/applications/builder.tsx rename to app/routes/builder.tsx index 07759056..94e578a8 100644 --- a/app/routes/applications/builder.tsx +++ b/app/routes/builder.tsx @@ -5,9 +5,8 @@ import { type ActionArgs, type LoaderArgs, redirect } from "@remix-run/node"; import { getCatalog } from "~/catalogs/index.server"; import { Haddock3WorkflowBuilder } from "~/components/Haddock3/Form.client"; import { haddock3Styles } from "~/components/Haddock3/styles"; -import { getAccessToken } from "~/token.server"; import { submitJob } from "~/models/applicaton.server"; -import { getLevel, isSubmitAllowed } from "~/models/user.server"; +import { checkAuthenticated, getLevel, isSubmitAllowed } from "~/models/user.server"; import { getSession } from "~/session.server"; export const loader = async ({ request }: LoaderArgs) => { @@ -22,19 +21,20 @@ export const loader = async ({ request }: LoaderArgs) => { }; export const action = async ({ request }: ActionArgs) => { - const name = "haddock3"; const formData = await request.formData(); const upload = formData.get("upload"); if (typeof upload === "string" || upload === null) { throw new Error("Bad upload"); } - const access_token = await getAccessToken(request); - if (access_token === undefined) { - throw new Error("Unauthenticated"); + const session = await getSession(request) + const accessToken = session.data.bartenderToken + checkAuthenticated(accessToken); + const level = await getLevel(session.data.roles) + if (!isSubmitAllowed(level)) { + throw new Error("Forbidden"); } - - const job = await submitJob(name, upload, access_token); + const job = await submitJob(upload, accessToken!); const job_url = `/jobs/${job.id}`; return redirect(job_url); }; diff --git a/app/routes/index.tsx b/app/routes/index.tsx index 90a58cfb..6a1ecaf8 100644 --- a/app/routes/index.tsx +++ b/app/routes/index.tsx @@ -2,13 +2,13 @@ import Card from "~/components/Card"; const cards = [ { - "target": "/applications/builder", + "target": "/builder", "image": "https://static.thenounproject.com/png/1781890-200.png", "title": "Build", "description": "Use the workflow builder to create and submit a job.", }, { - "target": "/applications/upload", + "target": "/upload", "image": "https://www.filemail.com/images/marketing/anonymously-upload-files.svg", "title": "Upload", "description": "Upload a workflow and submit as job.", diff --git a/app/routes/jobs/$id.tsx b/app/routes/jobs/$id.tsx index c019dba0..2147a044 100644 --- a/app/routes/jobs/$id.tsx +++ b/app/routes/jobs/$id.tsx @@ -26,10 +26,10 @@ export default function JobPage() { return (
    -

    State: {job.state}

    +

    Name: {job.name}

    +

    State: {job.state}

    Created on: {job.createdOn}

    Updated on: {job.updatedOn}

    -

    Name: {job.name}

    Input

    diff --git a/app/routes/applications/upload.tsx b/app/routes/upload.tsx similarity index 73% rename from app/routes/applications/upload.tsx rename to app/routes/upload.tsx index 4e0b2d80..930569bd 100644 --- a/app/routes/applications/upload.tsx +++ b/app/routes/upload.tsx @@ -4,49 +4,48 @@ import { type LoaderArgs, redirect, } from "@remix-run/node"; -import { Form, useLoaderData } from "@remix-run/react"; +import { Form } from "@remix-run/react"; import { getAccessToken } from "~/token.server"; -import { applicationByName, submitJob } from "~/models/applicaton.server"; +import { submitJob } from "~/models/applicaton.server"; import { checkAuthenticated, getLevel, isSubmitAllowed } from "~/models/user.server"; import { getSession } from "~/session.server"; +import { WORKFLOW_CONFIG_FILENAME } from "~/models/constants"; export const loader = async ({ request }: LoaderArgs) => { - const name = "haddock3"; - const app = await applicationByName(name); const session = await getSession(request); checkAuthenticated(session.data.bartenderToken); const level = await getLevel(session.data.roles) - if (isSubmitAllowed(level)) { + if (!isSubmitAllowed(level)) { throw new Error("Forbidden"); } - return json({ name, ...app }); + return json({ level }); }; export const action = async ({ request }: ActionArgs) => { - const name = "haddock3"; const formData = await request.formData(); const upload = formData.get("upload"); if (typeof upload === "string" || upload === null) { throw new Error("Bad upload"); } - const access_token = await getAccessToken(request); - if (access_token === undefined) { - throw new Error("Unauthenticated"); + const session = await getSession(request) + const accessToken = session.data.bartenderToken + checkAuthenticated(accessToken); + const level = await getLevel(session.data.roles) + if (!isSubmitAllowed(level)) { + throw new Error("Forbidden"); } - - const job = await submitJob(name, upload, access_token); + const job = await submitJob(upload, accessToken!); const job_url = `/jobs/${job.id}`; return redirect(job_url); }; export default function ApplicationSlug() { - const { config } = useLoaderData(); return (

    Upload haddock3 archive

    -

    Archive should contain workfow configuration file called {config}.

    +

    Archive should contain workfow configuration file called {WORKFLOW_CONFIG_FILENAME}.

    -
    -

    Input

    - -
    {CompletedJobs.has(job.state) && ( -
    -

    Output

    - - -
    + <> + {/* TODO allow to read input files when job is not completed */} +
    +

    Input

    + +
    +
    +

    Output

    + + +
    + )}
    ); From 0faa6dfd2e81c9ba9587df832eced3a59d9bc22e Mon Sep 17 00:00:00 2001 From: Stefan Verhoeven Date: Tue, 11 Apr 2023 13:43:23 +0200 Subject: [PATCH 10/13] Make header in toml a single line --- app/components/Haddock3/Form.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/components/Haddock3/Form.css b/app/components/Haddock3/Form.css index 5de1215e..6c1a8a78 100644 --- a/app/components/Haddock3/Form.css +++ b/app/components/Haddock3/Form.css @@ -218,3 +218,7 @@ div.checkbox { padding: 0.25rem; overflow: unset; } + +code .table{ + @apply contents +} From 1e220be2c2b041afcdd62763f12536c95034964a Mon Sep 17 00:00:00 2001 From: sverhoeven Date: Thu, 25 May 2023 11:31:47 +0200 Subject: [PATCH 11/13] Also use shortname for new calls --- app/models/job.server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/job.server.ts b/app/models/job.server.ts index cad76c86..2d54304c 100644 --- a/app/models/job.server.ts +++ b/app/models/job.server.ts @@ -47,7 +47,7 @@ export async function getJobfile(jobid: number, path: string, accessToken: strin export async function listOutputFiles(jobid: number, accessToken: string) { const api = buildJobApi(accessToken) - const items = await api.retrieveJobDirectoriesFromPathApiJobJobidDirectoriesPathGet({ + const items = await api.retrieveJobDirectoriesFromPath({ jobid, path: JOB_OUTPUT_DIR, maxDepth: 3 From c884b1bdfc7750d20f5f85140cfa88d27090e47b Mon Sep 17 00:00:00 2001 From: Stefan Verhoeven Date: Wed, 31 May 2023 13:52:20 +0200 Subject: [PATCH 12/13] Rewrite ListReportFiles to have single report.html per module + add unit test for ListReportFiles component. --- .github/workflows/ci.yml | 2 +- .gitignore | 1 + app/components/ListReportFiles.test.tsx | 134 +++ app/components/ListReportFiles.tsx | 47 +- package-lock.json | 1365 +++++++++++++++++------ package.json | 7 +- vite.config.ts | 12 + 7 files changed, 1200 insertions(+), 368 deletions(-) create mode 100644 app/components/ListReportFiles.test.tsx diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 49e52ffe..98da2682 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,5 +28,5 @@ jobs: cache: 'npm' - run: npm ci - run: npm run build --if-present - - run: npm test + - run: npm test -- --coverage - run: npm run typecheck diff --git a/.gitignore b/.gitignore index e5e3a169..81235d52 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ node_modules /openapitools.json /sessions +/coverage diff --git a/app/components/ListReportFiles.test.tsx b/app/components/ListReportFiles.test.tsx new file mode 100644 index 00000000..83a70561 --- /dev/null +++ b/app/components/ListReportFiles.test.tsx @@ -0,0 +1,134 @@ +import { describe, it, expect, afterEach} from 'vitest'; +import { render } from "@testing-library/react"; +import { cleanup } from '@testing-library/react'; +import matchers from '@testing-library/jest-dom/matchers'; + +import { ListReportFiles } from "./ListReportFiles"; +import type { DirectoryItem } from '~/bartender-client'; + +expect.extend(matchers); + +afterEach(() => { + cleanup(); +}); + + +describe("ListReportFiles", () => { + it("renders a list of report files", () => { + const files: DirectoryItem = { + name: "root", + path: "", + isDir: true, + isFile: false, + children: [ + { + name: "analysis", + path: "analysis", + isDir: true, + isFile: false, + children: [ + { + name: "module1", + path: "analysis/module1", + isDir: true, + isFile: false, + children: [ + { name: "report.html", path: "analysis/module1/report.html", isDir: false, isFile: true }, + ], + }, + { + name: "module2", + path: "analysis/module2", + isDir: true, + isFile: false, + children: [ + { name: "report.html", path: "analysis/module2/report.html", isDir: false, isFile: true }, + ], + }, + ], + }, + ], + }; + const prefix = "https://example.com/"; + const { getByText } = render( + + ); + expect(getByText("module1")).toHaveAttribute( + "href", + "https://example.com/analysis/module1/report.html" + ); + expect(getByText("module2")).toHaveAttribute( + "href", + "https://example.com/analysis/module2/report.html" + ); + }); + + it("renders a module with no report.html file", () => { + const files: DirectoryItem = { + name: "root", + path: "", + isDir: true, + isFile: false, + children: [ + { + name: "analysis", + path: "analysis", + isDir: true, + isFile: false, + children: [ + { + name: "module1", + path: "analysis/module1", + isDir: true, + isFile: false, + children: [], + }, + ], + }, + ], + }; + const prefix = "https://example.com/"; + const { queryByText, } = render( + + ); + expect(queryByText("module1")).toBeFalsy() + }); + + it("renders correctly when analysis has no children", () => { + const files: DirectoryItem = { + name: "root", + path: "", + isDir: true, + isFile: false, + children: [ + { + name: "analysis", + path: "analysis", + isDir: true, + isFile: false, + }, + ], + }; + const prefix = "https://example.com/"; + const { queryByText } = render( + + ); + expect(queryByText("analysis")).toBeFalsy(); + }); + + it("renders correctly when root has no children", () => { + const files: DirectoryItem = { + name: "root", + path: "", + isDir: true, + isFile: false, + }; + const prefix = "https://example.com/"; + const { queryByText } = render( + + ); + expect(queryByText("analysis")).toBeFalsy(); + }); +}); + + diff --git a/app/components/ListReportFiles.tsx b/app/components/ListReportFiles.tsx index 2bb7d05c..9570a4af 100644 --- a/app/components/ListReportFiles.tsx +++ b/app/components/ListReportFiles.tsx @@ -1,29 +1,44 @@ import { useMemo } from "react"; import type { DirectoryItem } from "~/bartender-client"; -export function ListReportFiles({ files, prefix }: { files: DirectoryItem, prefix: string }) { - const htmlFiles: [string, DirectoryItem[]][] = useMemo(() => { +export function ListReportFiles({ + files, + prefix, +}: { + files: DirectoryItem; + prefix: string; +}) { + const reportFiles = useMemo(() => { + const result = new Map(); if (!files.children) { - return []; + return result; } const analyisRoot = files.children.find((i) => i.name === "analysis"); - if (!analyisRoot|| !analyisRoot.children) { - return []; + if (!analyisRoot || !analyisRoot.children) { + return result; } - return analyisRoot.children.map((module) => { - if (!module.children) { - return [module.name, []] - } - const htmls = module.children.filter((file) => file.name.endsWith("report.html")) - .map((file) => file); - return [module.name, htmls]; - }); + analyisRoot.children + .filter((module) => module.children !== undefined) + .forEach((module) => { + const html = module.children?.find((file) => + file.name.endsWith("report.html") + ); + if (html !== undefined) { + result.set(module.name, html.path); + } + }); + return result; }, [files]); + return (
      - {htmlFiles.map(([module, htmls]) => { - return
    • {module}
    • ; - })} + {Array.from(reportFiles).map(([module, report]) => ( +
    • + + {module} + +
    • + ))}
    ); } diff --git a/package-lock.json b/package-lock.json index dcb2d94a..92304d38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,28 +23,37 @@ "@remix-run/eslint-config": "^1.15.0", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/typography": "^0.5.9", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^14.0.0", "@types/js-yaml": "^4.0.5", "@types/jszip": "^3.4.1", "@types/react": "^18.0.25", "@types/react-dom": "^18.0.8", - "@vitest/coverage-c8": "^0.29.1", + "@vitest/coverage-c8": "^0.31.2", "daisyui": "^2.51.0", "eslint": "^8.27.0", + "happy-dom": "^9.20.3", "tailwindcss": "^3.2.7", "typescript": "~4.8.4", "vite-tsconfig-paths": "^4.0.5", - "vitest": "^0.29.1" + "vitest": "^0.31.2" }, "engines": { "node": ">=18" } }, + "node_modules/@adobe/css-tools": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.2.0.tgz", + "integrity": "sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==", + "dev": true + }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { @@ -147,19 +156,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/generator/node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -2670,13 +2666,55 @@ "node": ">=8" } }, + "node_modules/@jest/expect-utils": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", + "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.4.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.25.16" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", + "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.4.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "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.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" @@ -2717,15 +2755,39 @@ "resolved": "https://registry.npmjs.org/@ltd/j-toml/-/j-toml-1.38.0.tgz", "integrity": "sha512-lYtBcmvHustHQtg4X7TXUu1Xa/tbLC3p2wLvgQI+fWVySguVZJF60Snxijw5EiohumxZbR10kWYFFebh1zotiw==" }, + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nestjs/axios": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-0.0.8.tgz", + "integrity": "sha512-oJyfR9/h9tVk776il0829xyj3b2e81yTu6HjPraxynwNtMNGqZBHHmAQL24yMB3tVbBM0RvG3eUXH8+pRCGwlg==", + "dev": true, + "dependencies": { + "axios": "0.27.2" + }, + "peerDependencies": { + "@nestjs/common": "^7.0.0 || ^8.0.0", + "reflect-metadata": "^0.1.12", + "rxjs": "^6.0.0 || ^7.0.0" + } + }, "node_modules/@nestjs/common": { - "version": "8.4.4", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-8.4.4.tgz", - "integrity": "sha512-QHi7QcgH/5Jinz+SCfIZJkFHc6Cch1YsAEGFEhi6wSp6MILb0sJMQ1CX06e9tCOAjSlBwaJj4PH0eFCVau5v9Q==", + "version": "8.4.7", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-8.4.7.tgz", + "integrity": "sha512-m/YsbcBal+gA5CFrDpqXqsSfylo+DIQrkFY3qhVIltsYRfu8ct8J9pqsTO6OPf3mvqdOpFGrV5sBjoyAzOBvsw==", "dev": true, + "peer": true, "dependencies": { - "axios": "0.26.1", + "axios": "0.27.2", "iterare": "1.2.1", - "tslib": "2.3.1", + "tslib": "2.4.0", "uuid": "8.3.2" }, "funding": { @@ -2752,61 +2814,11 @@ } }, "node_modules/@nestjs/common/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "node_modules/@nestjs/core": { - "version": "8.4.4", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-8.4.4.tgz", - "integrity": "sha512-Ef3yJPuzAttpNfehnGqIV5kHIL9SHptB5F4ERxoU7pT61H3xiYpZw6hSjx68cJO7cc6rm7/N+b4zeuJvFHtvBg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nuxtjs/opencollective": "0.3.2", - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "object-hash": "3.0.0", - "path-to-regexp": "3.2.0", - "tslib": "2.3.1", - "uuid": "8.3.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0", - "@nestjs/microservices": "^8.0.0", - "@nestjs/platform-express": "^8.0.0", - "@nestjs/websockets": "^8.0.0", - "reflect-metadata": "^0.1.12", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { - "optional": true - }, - "@nestjs/websockets": { - "optional": true - } - } - }, - "node_modules/@nestjs/core/node_modules/path-to-regexp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", - "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==", - "dev": true - }, - "node_modules/@nestjs/core/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true + "peer": true }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", @@ -2907,26 +2919,27 @@ } }, "node_modules/@openapitools/openapi-generator-cli": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.5.2.tgz", - "integrity": "sha512-FLgkjzpDiHVsH821db0VDSElDoA6TcspGyq3RD4zLBJaJhbSsRwr4u87sNoyuHKBg4OMJbZMT4iJxAhkosKrzw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.6.0.tgz", + "integrity": "sha512-M/aOpR7G+Y1nMf+ofuar8pGszajgfhs1aSPSijkcr2tHTxKAI3sA3YYcOGbszxaNRKFyvOcDq+KP9pcJvKoCHg==", "dev": true, "hasInstallScript": true, "dependencies": { - "@nestjs/common": "8.4.4", - "@nestjs/core": "8.4.4", + "@nestjs/axios": "0.0.8", + "@nestjs/common": "9.3.11", + "@nestjs/core": "9.3.11", "@nuxtjs/opencollective": "0.3.2", "chalk": "4.1.2", "commander": "8.3.0", - "compare-versions": "4.1.3", + "compare-versions": "4.1.4", "concurrently": "6.5.1", "console.table": "0.10.0", - "fs-extra": "10.0.1", + "fs-extra": "10.1.0", "glob": "7.1.6", - "inquirer": "8.2.2", + "inquirer": "8.2.5", "lodash": "4.17.21", "reflect-metadata": "0.1.13", - "rxjs": "7.5.5", + "rxjs": "7.8.0", "tslib": "2.0.3" }, "bin": { @@ -2940,20 +2953,89 @@ "url": "https://opencollective.com/openapi_generator" } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/fs-extra": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", - "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common": { + "version": "9.3.11", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.3.11.tgz", + "integrity": "sha512-IFZ2G/5UKWC2Uo7tJ4SxGed2+aiA+sJyWeWsGTogKVDhq90oxVBToh+uCDeI31HNUpqYGoWmkletfty42zUd8A==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "iterare": "1.2.1", + "tslib": "2.5.0", + "uid": "2.0.1" }, - "engines": { - "node": ">=12" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "cache-manager": "<=5", + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "cache-manager": { + "optional": true + }, + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common/node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core": { + "version": "9.3.11", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.3.11.tgz", + "integrity": "sha512-CI27a2JFd5rvvbgkalWqsiwQNhcP4EAG5BUK8usjp29wVp1kx30ghfBT8FLqIgmkRVo65A0IcEnWsxeXMntkxQ==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nuxtjs/opencollective": "0.3.2", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "3.2.0", + "tslib": "2.5.0", + "uid": "2.0.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^9.0.0", + "@nestjs/microservices": "^9.0.0", + "@nestjs/platform-express": "^9.0.0", + "@nestjs/websockets": "^9.0.0", + "reflect-metadata": "^0.1.12", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } } }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core/node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + }, "node_modules/@openapitools/openapi-generator-cli/node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -2974,44 +3056,10 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/inquirer": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.2.tgz", - "integrity": "sha512-pG7I/si6K/0X7p1qU+rfWnpTE1UIkTONN1wxtzh0d+dHXtT/JG6qBgLxoyHVsQa8cFABxAPh0pD6uUUHiAoaow==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/rxjs": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", - "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/rxjs/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "node_modules/@openapitools/openapi-generator-cli/node_modules/path-to-regexp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", + "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==", "dev": true }, "node_modules/@openapitools/openapi-generator-cli/node_modules/tslib": { @@ -3164,9 +3212,9 @@ } }, "node_modules/@remix-run/dev/node_modules/yaml": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", "dev": true, "engines": { "node": ">= 14" @@ -3439,6 +3487,12 @@ "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==", "dev": true }, + "node_modules/@sinclair/typebox": { + "version": "0.25.24", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", + "dev": true + }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -3522,6 +3576,78 @@ "node": ">=12" } }, + "node_modules/@testing-library/jest-dom": { + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", + "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.0.1", + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=8", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.0.0.tgz", + "integrity": "sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^9.0.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@testing-library/react/node_modules/@testing-library/dom": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.0.tgz", + "integrity": "sha512-Dffe68pGwI6WlLRYR2I0piIkyole9cSBH5jGQKCGMRpHW5RHCqAUaqc2Kv0tUyd4dU4DLPKhJIjyKOnjv4tuUw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "^5.0.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -3559,9 +3685,9 @@ } }, "node_modules/@types/chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", + "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", "dev": true }, "node_modules/@types/chai-subset": { @@ -3637,6 +3763,66 @@ "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", "dev": true }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.1.tgz", + "integrity": "sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/jest/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@types/jest/node_modules/pretty-format": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.4.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, "node_modules/@types/js-yaml": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", @@ -3763,6 +3949,21 @@ "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", "dev": true }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/testing-library__jest-dom": { + "version": "5.14.6", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.6.tgz", + "integrity": "sha512-FkHXCb+ikSoUP4Y4rOslzTdX5sqYwMxfefKh1GmZ8ce1GOkEHntSp6b5cGadmNfp5e4BMEWOMx+WSKd5/MqlDA==", + "dev": true, + "dependencies": { + "@types/jest": "*" + } + }, "node_modules/@types/unist": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", @@ -3773,6 +3974,21 @@ "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" }, + "node_modules/@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.51.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.51.0.tgz", @@ -4449,42 +4665,63 @@ "dev": true }, "node_modules/@vitest/coverage-c8": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/@vitest/coverage-c8/-/coverage-c8-0.29.1.tgz", - "integrity": "sha512-YQZp1xGNxOcZD/zQBvD4bNpUDMJW7+FhBAEBlgvJp+DQ+aNK+dKcoWOTfsod27KQhXSr6UUYI8EYXWCOQqY6Eg==", + "version": "0.31.2", + "resolved": "https://registry.npmjs.org/@vitest/coverage-c8/-/coverage-c8-0.31.2.tgz", + "integrity": "sha512-RznxfxFtoV8xYt8e0h57OeulqOfFZJsa5pxXKW+xFW9ZHamSZ0wJC57FS4oh3Xbe0JNaHwSJ0KeClXgnuW1fkw==", "dev": true, "dependencies": { + "@ampproject/remapping": "^2.2.1", "c8": "^7.13.0", + "magic-string": "^0.30.0", "picocolors": "^1.0.0", - "std-env": "^3.3.1" + "std-env": "^3.3.2" }, "funding": { - "url": "https://github.com/sponsors/antfu" + "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": ">=0.29.0 <1" + "vitest": ">=0.30.0 <1" + } + }, + "node_modules/@vitest/coverage-c8/node_modules/magic-string": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", + "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" } }, "node_modules/@vitest/expect": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.29.1.tgz", - "integrity": "sha512-VFt1u34D+/L4pqjLA8VGPdHbdF8dgjX9Nq573L9KG6/7MIAL9jmbEIKpXudmxjoTwcyczOXRyDuUWBQHZafjoA==", + "version": "0.31.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.31.2.tgz", + "integrity": "sha512-AOuh2NLN9zJ0SkvsItRkS/W39akYpUvo5LOnay3zEhGSnRgivPu2D3S8QlMij1hFMQcX+dlMilPgJatUHiGQ4A==", "dev": true, "dependencies": { - "@vitest/spy": "0.29.1", - "@vitest/utils": "0.29.1", + "@vitest/spy": "0.31.2", + "@vitest/utils": "0.31.2", "chai": "^4.3.7" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.29.1.tgz", - "integrity": "sha512-VZ6D+kWpd/LVJjvxkt79OA29FUpyrI5L/EEwoBxH5m9KmKgs1QWNgobo/CGQtIWdifLQLvZdzYEK7Qj96w/ixQ==", + "version": "0.31.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.31.2.tgz", + "integrity": "sha512-k2mWrzZD1xsWfzwEXeVr2XF4v8ELpFOKLxRbcnzZclHelOLn27nXvnw1A4JwJtmca64C3/6lo4WHZDlq3TefLQ==", "dev": true, "dependencies": { - "@vitest/utils": "0.29.1", + "@vitest/utils": "0.31.2", + "concordance": "^5.0.4", "p-limit": "^4.0.0", "pathe": "^1.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner/node_modules/p-limit": { @@ -4514,26 +4751,56 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@vitest/snapshot": { + "version": "0.31.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.31.2.tgz", + "integrity": "sha512-NXRlbP3sM5+KELb8oXVHf7UWD+liBnSsS+4JlDVPD5+KPquZmgNR0xPLW5VEb5HoQZQpKTAFhtGf1AczRCbAhg==", + "dev": true, + "dependencies": { + "magic-string": "^0.30.0", + "pathe": "^1.1.0", + "pretty-format": "^27.5.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot/node_modules/magic-string": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", + "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@vitest/spy": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.29.1.tgz", - "integrity": "sha512-sRXXK44pPzaizpiZOIQP7YMhxIs80J/b6v1yR3SItpxG952c8tdA7n0O2j4OsVkjiO/ZDrjAYFrXL3gq6hLx6Q==", + "version": "0.31.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.31.2.tgz", + "integrity": "sha512-81zcAkCCgAc1gA7UvLOWCvkIwrgzaqHBdv9sskOt2xh1+l+RMX9G7sVYj3AOsib3UDR0MCSXit49xKILTMnikw==", "dev": true, "dependencies": { - "tinyspy": "^1.0.2" + "tinyspy": "^2.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.29.1.tgz", - "integrity": "sha512-6npOEpmyE6zPS2wsWb7yX5oDpp6WY++cC5BX6/qaaMhGC3ZlPd8BbTz3RtGPi1PfPerPvfs4KqS/JDOIaB6J3w==", + "version": "0.31.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.31.2.tgz", + "integrity": "sha512-B2AoocMpIiBezediqFzSqvuXI7AZlmlPkh3oj20Jh3bL35c8YYWk9KfOLkEjsLCrOHOUFXoYFc+ACiELCIJVRw==", "dev": true, "dependencies": { - "cli-truncate": "^3.1.0", - "diff": "^5.1.0", + "concordance": "^5.0.4", "loupe": "^2.3.6", - "picocolors": "^1.0.0", "pretty-format": "^27.5.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, "node_modules/@web3-storage/multipart-parser": { @@ -4913,6 +5180,12 @@ "astring": "bin/astring" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, "node_modules/autoprefixer": { "version": "10.4.13", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", @@ -4968,12 +5241,13 @@ } }, "node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", "dev": true, "dependencies": { - "follow-redirects": "^1.14.8" + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" } }, "node_modules/axobject-query": { @@ -5140,6 +5414,12 @@ "readable-stream": "^3.4.0" } }, + "node_modules/blueimp-md5": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", + "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", + "dev": true + }, "node_modules/body-parser": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", @@ -5603,6 +5883,21 @@ "node": ">=10" } }, + "node_modules/ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, "node_modules/classnames": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", @@ -5641,66 +5936,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/cli-width": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", @@ -5791,6 +6026,18 @@ "simple-swizzle": "^0.2.2" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -5811,9 +6058,9 @@ } }, "node_modules/compare-versions": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-4.1.3.tgz", - "integrity": "sha512-WQfnbDcrYnGr55UwbxKiQKASnTtNnaAWVi8jZyy8NTpVAXWACSne8lMD1iaIo9AiU6mnuLvSVshCzewVuWxHUg==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-4.1.4.tgz", + "integrity": "sha512-FemMreK9xNyL8gQevsdRMrvO4lFCkQP7qbuktn1q8ndcNk1+0mz7lgE7b/sNvbhVgY4w6tMN1FDp6aADjqw2rw==", "dev": true }, "node_modules/compressible": { @@ -5884,6 +6131,25 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/concordance": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz", + "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==", + "dev": true, + "dependencies": { + "date-time": "^3.1.0", + "esutils": "^2.0.3", + "fast-diff": "^1.2.0", + "js-string-escape": "^1.0.1", + "lodash": "^4.17.15", + "md5-hex": "^3.0.1", + "semver": "^7.3.2", + "well-known-symbols": "^2.0.0" + }, + "engines": { + "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14" + } + }, "node_modules/concurrently": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-6.5.1.tgz", @@ -6095,6 +6361,12 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -6159,6 +6431,18 @@ "url": "https://opencollective.com/date-fns" } }, + "node_modules/date-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz", + "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==", + "dev": true, + "dependencies": { + "time-zone": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/deasync": { "version": "0.1.28", "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.28.tgz", @@ -6361,6 +6645,15 @@ "node": ">= 6" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -6436,6 +6729,15 @@ "node": ">=0.3.1" } }, + "node_modules/diff-sequences": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -6542,12 +6844,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, "node_modules/easy-table": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.1.0.tgz", @@ -6612,6 +6908,18 @@ "node": ">=10.13.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -8101,6 +8409,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/expect": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.5.0", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/express": { "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", @@ -8212,6 +8536,12 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, "node_modules/fast-glob": { "version": "3.2.11", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", @@ -8446,6 +8776,20 @@ "node": ">=8.0.0" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/format": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", @@ -8918,11 +9262,46 @@ "gunzip-maybe": "bin.js" } }, - "node_modules/hamt_plus": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz", - "integrity": "sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA==" - }, + "node_modules/hamt_plus": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz", + "integrity": "sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA==" + }, + "node_modules/happy-dom": { + "version": "9.20.3", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-9.20.3.tgz", + "integrity": "sha512-eBsgauT435fXFvQDNcmm5QbGtYzxEzOaX35Ia+h6yP/wwa4xSWZh1CfP+mGby8Hk6Xu59mTkpyf72rUXHNxY7A==", + "dev": true, + "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" + } + }, + "node_modules/happy-dom/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/happy-dom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -9950,6 +10329,178 @@ "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", "dev": true }, + "node_modules/jest-diff": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", + "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/pretty-format": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.4.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", + "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.5.0", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/pretty-format": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.4.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/jest-message-util": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", + "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.5.0", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.5.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/pretty-format": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.4.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/jest-util": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", + "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.5.0", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jose": { "version": "4.13.1", "resolved": "https://registry.npmjs.org/jose/-/jose-4.13.1.tgz", @@ -9974,6 +10525,15 @@ "url": "https://opencollective.com/js-sdsl" } }, + "node_modules/js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -10374,9 +10934,9 @@ } }, "node_modules/lz-string": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", - "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "bin": { "lz-string": "bin/bin.js" @@ -10424,6 +10984,18 @@ "node": ">=0.10.0" } }, + "node_modules/md5-hex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", + "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==", + "dev": true, + "dependencies": { + "blueimp-md5": "^2.10.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/mdast-util-definitions": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz", @@ -11363,6 +11935,15 @@ "node": ">=4" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/mini-svg-data-uri": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", @@ -11473,15 +12054,15 @@ "dev": true }, "node_modules/mlly": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.1.0.tgz", - "integrity": "sha512-cwzBrBfwGC1gYJyfcy8TcZU1f+dbH/T+TuOhtYP2wLv/Fb51/uV7HJQfBPtEupZ2ORLRU1EKFS/QfS3eo9+kBQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.3.0.tgz", + "integrity": "sha512-HT5mcgIQKkOrZecOjOX3DJorTikWXwsBfpcr/MGBkhfWcjiqvnaL/9ppxvIUXfjT6xt4DVIAsN9fMUz1ev4bIw==", "dev": true, "dependencies": { - "acorn": "^8.8.1", - "pathe": "^1.0.0", - "pkg-types": "^1.0.1", - "ufo": "^1.0.1" + "acorn": "^8.8.2", + "pathe": "^1.1.0", + "pkg-types": "^1.0.3", + "ufo": "^1.1.2" } }, "node_modules/morgan": { @@ -12192,14 +12773,14 @@ } }, "node_modules/pkg-types": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.1.tgz", - "integrity": "sha512-jHv9HB+Ho7dj6ItwppRDDl0iZRYBD0jsakHXtFgoLr+cHSF6xC+QL54sJmWxyGxOLYSHm0afhXhXcQDQqH9z8g==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", + "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", "dev": true, "dependencies": { "jsonc-parser": "^3.2.0", - "mlly": "^1.0.0", - "pathe": "^1.0.0" + "mlly": "^1.2.0", + "pathe": "^1.1.0" } }, "node_modules/popper.js": { @@ -12984,6 +13565,19 @@ } } }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/redux": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", @@ -13684,46 +14278,6 @@ "node": ">=8" } }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -13888,6 +14442,27 @@ "node": ">= 8" } }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -14077,6 +14652,18 @@ "node": ">=6" } }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -14380,6 +14967,15 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/time-zone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", + "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/tiny-glob": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", @@ -14391,24 +14987,24 @@ } }, "node_modules/tinybench": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.1.tgz", - "integrity": "sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.0.tgz", + "integrity": "sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==", "dev": true }, "node_modules/tinypool": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.3.1.tgz", - "integrity": "sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.5.0.tgz", + "integrity": "sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==", "dev": true, "engines": { "node": ">=14.0.0" } }, "node_modules/tinyspy": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-1.1.1.tgz", - "integrity": "sha512-UVq5AXt/gQlti7oxoIg5oi/9r0WpF7DGEVwXgqWSMmyN16+e3tl5lIvTaOpJ3TAtu5xFzWccFRM4R5NaWHF+4g==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.1.1.tgz", + "integrity": "sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==", "dev": true, "engines": { "node": ">=14.0.0" @@ -14618,11 +15214,23 @@ } }, "node_modules/ufo": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.0.1.tgz", - "integrity": "sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.1.2.tgz", + "integrity": "sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==", "dev": true }, + "node_modules/uid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.1.tgz", + "integrity": "sha512-PF+1AnZgycpAIEmNtjxGBVmKbZAQguaa4pBUq6KNaGEcpzZ2klCNZLM34tsjp76maN00TttiiUf6zkIBpJQm2A==", + "dev": true, + "dependencies": { + "@lukeed/csprng": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -14944,6 +15552,7 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, + "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -15114,14 +15723,14 @@ } }, "node_modules/vite-node": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.29.1.tgz", - "integrity": "sha512-Ey9bTlQOQrCxQN0oJ7sTg+GrU4nTMLg44iKTFCKf31ry60csqQz4E+Q04hdWhwE4cTgpxUC+zEB1kHbf5jNkFA==", + "version": "0.31.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.31.2.tgz", + "integrity": "sha512-NvoO7+zSvxROC4JY8cyp/cO7DHAX3dwMOHQVDdNtCZ4Zq8wInnR/bJ/lfsXqE6wrUgtYCE5/84qHS+A7vllI3A==", "dev": true, "dependencies": { "cac": "^6.7.14", "debug": "^4.3.4", - "mlly": "^1.1.0", + "mlly": "^1.2.0", "pathe": "^1.1.0", "picocolors": "^1.0.0", "vite": "^3.0.0 || ^4.0.0" @@ -15130,10 +15739,10 @@ "vite-node": "vite-node.mjs" }, "engines": { - "node": ">=v14.16.0" + "node": ">=v14.18.0" }, "funding": { - "url": "https://github.com/sponsors/antfu" + "url": "https://opencollective.com/vitest" } }, "node_modules/vite-tsconfig-paths": { @@ -15201,51 +15810,55 @@ } }, "node_modules/vitest": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.29.1.tgz", - "integrity": "sha512-iSy6d9VwsIn7pz5I8SjVwdTLDRGKNZCRJVzROwjt0O0cffoymKwazIZ2epyMpRGpeL5tsXAl1cjXiT7agTyVug==", + "version": "0.31.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.31.2.tgz", + "integrity": "sha512-O0qKHDbI+zXxwq1WOeqFjxP5v1mDqqM6gllPuOUJkK2YFyQ2nEo8CELR4Mg68ryTSSh527ysBmEN69bDvL2LkQ==", "dev": true, "dependencies": { - "@types/chai": "^4.3.4", + "@types/chai": "^4.3.5", "@types/chai-subset": "^1.3.3", "@types/node": "*", - "@vitest/expect": "0.29.1", - "@vitest/runner": "0.29.1", - "@vitest/spy": "0.29.1", - "@vitest/utils": "0.29.1", - "acorn": "^8.8.1", + "@vitest/expect": "0.31.2", + "@vitest/runner": "0.31.2", + "@vitest/snapshot": "0.31.2", + "@vitest/spy": "0.31.2", + "@vitest/utils": "0.31.2", + "acorn": "^8.8.2", "acorn-walk": "^8.2.0", "cac": "^6.7.14", "chai": "^4.3.7", + "concordance": "^5.0.4", "debug": "^4.3.4", - "local-pkg": "^0.4.2", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.0", "pathe": "^1.1.0", "picocolors": "^1.0.0", - "source-map": "^0.6.1", - "std-env": "^3.3.1", - "strip-literal": "^1.0.0", - "tinybench": "^2.3.1", - "tinypool": "^0.3.1", - "tinyspy": "^1.0.2", + "std-env": "^3.3.2", + "strip-literal": "^1.0.1", + "tinybench": "^2.5.0", + "tinypool": "^0.5.0", "vite": "^3.0.0 || ^4.0.0", - "vite-node": "0.29.1", + "vite-node": "0.31.2", "why-is-node-running": "^2.2.2" }, "bin": { "vitest": "vitest.mjs" }, "engines": { - "node": ">=v14.16.0" + "node": ">=v14.18.0" }, "funding": { - "url": "https://github.com/sponsors/antfu" + "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", "@vitest/browser": "*", "@vitest/ui": "*", "happy-dom": "*", - "jsdom": "*" + "jsdom": "*", + "playwright": "*", + "safaridriver": "*", + "webdriverio": "*" }, "peerDependenciesMeta": { "@edge-runtime/vm": { @@ -15262,22 +15875,34 @@ }, "jsdom": { "optional": true + }, + "playwright": { + "optional": true + }, + "safaridriver": { + "optional": true + }, + "webdriverio": { + "optional": true } } }, - "node_modules/vitest/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/vitest/node_modules/magic-string": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", + "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, "node_modules/vm2": { - "version": "3.9.14", - "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.14.tgz", - "integrity": "sha512-HgvPHYHeQy8+QhzlFryvSteA4uQLBCOub02mgqdR+0bN/akRZ48TGB1v0aCv7ksyc0HXx16AZtMHKS38alc6TA==", + "version": "3.9.19", + "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.19.tgz", + "integrity": "sha512-J637XF0DHDMV57R6JyVsTak7nIL8gy5KH4r1HiwWLf/4GBbb5MKL5y7LpmF4A8E2nR6XmzpmMFQ7V7ppPTmUQg==", "dev": true, "dependencies": { "acorn": "^8.7.0", @@ -15332,6 +15957,48 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "dev": true }, + "node_modules/well-known-symbols": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", + "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", diff --git a/package.json b/package.json index 282ba6c7..53c8b8d3 100644 --- a/package.json +++ b/package.json @@ -32,17 +32,20 @@ "@remix-run/eslint-config": "^1.15.0", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/typography": "^0.5.9", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^14.0.0", "@types/js-yaml": "^4.0.5", "@types/jszip": "^3.4.1", "@types/react": "^18.0.25", "@types/react-dom": "^18.0.8", - "@vitest/coverage-c8": "^0.29.1", + "@vitest/coverage-c8": "^0.31.2", "daisyui": "^2.51.0", "eslint": "^8.27.0", + "happy-dom": "^9.20.3", "tailwindcss": "^3.2.7", "typescript": "~4.8.4", "vite-tsconfig-paths": "^4.0.5", - "vitest": "^0.29.1" + "vitest": "^0.31.2" }, "engines": { "node": ">=18" diff --git a/vite.config.ts b/vite.config.ts index 6f087538..c0685097 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -3,4 +3,16 @@ import tsconfigPaths from 'vite-tsconfig-paths' export default defineConfig({ plugins: [tsconfigPaths()], + test: { + environment: "happy-dom", + include: ["./app/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], + watchExclude: [ + ".*\\/node_modules\\/.*", + ".*\\/build\\/.*", + ".*\\/postgres-data\\/.*", + ], + coverage: { + provider: "c8", + } + }, }) \ No newline at end of file From 15b36741592fbc6b6ab12106772bb0047722ed13 Mon Sep 17 00:00:00 2001 From: Stefan Verhoeven Date: Wed, 31 May 2023 13:57:25 +0200 Subject: [PATCH 13/13] Format + simplify report.html name check --- app/components/ListReportFiles.test.tsx | 241 ++++++++++++------------ app/components/ListReportFiles.tsx | 4 +- 2 files changed, 126 insertions(+), 119 deletions(-) diff --git a/app/components/ListReportFiles.test.tsx b/app/components/ListReportFiles.test.tsx index 83a70561..37aecd93 100644 --- a/app/components/ListReportFiles.test.tsx +++ b/app/components/ListReportFiles.test.tsx @@ -1,134 +1,141 @@ -import { describe, it, expect, afterEach} from 'vitest'; +import { describe, it, expect, afterEach } from "vitest"; import { render } from "@testing-library/react"; -import { cleanup } from '@testing-library/react'; -import matchers from '@testing-library/jest-dom/matchers'; +import { cleanup } from "@testing-library/react"; +import matchers from "@testing-library/jest-dom/matchers"; import { ListReportFiles } from "./ListReportFiles"; -import type { DirectoryItem } from '~/bartender-client'; +import type { DirectoryItem } from "~/bartender-client"; expect.extend(matchers); afterEach(() => { - cleanup(); + cleanup(); }); - describe("ListReportFiles", () => { - it("renders a list of report files", () => { - const files: DirectoryItem = { - name: "root", - path: "", - isDir: true, - isFile: false, - children: [ + it("renders a list of report files", () => { + const files: DirectoryItem = { + name: "root", + path: "", + isDir: true, + isFile: false, + children: [ + { + name: "analysis", + path: "analysis", + isDir: true, + isFile: false, + children: [ + { + name: "module1", + path: "analysis/module1", + isDir: true, + isFile: false, + children: [ { - name: "analysis", - path: "analysis", - isDir: true, - isFile: false, - children: [ - { - name: "module1", - path: "analysis/module1", - isDir: true, - isFile: false, - children: [ - { name: "report.html", path: "analysis/module1/report.html", isDir: false, isFile: true }, - ], - }, - { - name: "module2", - path: "analysis/module2", - isDir: true, - isFile: false, - children: [ - { name: "report.html", path: "analysis/module2/report.html", isDir: false, isFile: true }, - ], - }, - ], + name: "report.html", + path: "analysis/module1/report.html", + isDir: false, + isFile: true, }, - ], - }; - const prefix = "https://example.com/"; - const { getByText } = render( - - ); - expect(getByText("module1")).toHaveAttribute( - "href", - "https://example.com/analysis/module1/report.html" - ); - expect(getByText("module2")).toHaveAttribute( - "href", - "https://example.com/analysis/module2/report.html" - ); - }); - - it("renders a module with no report.html file", () => { - const files: DirectoryItem = { - name: "root", - path: "", - isDir: true, - isFile: false, - children: [ + ], + }, + { + name: "module2", + path: "analysis/module2", + isDir: true, + isFile: false, + children: [ { - name: "analysis", - path: "analysis", - isDir: true, - isFile: false, - children: [ - { - name: "module1", - path: "analysis/module1", - isDir: true, - isFile: false, - children: [], - }, - ], + name: "report.html", + path: "analysis/module2/report.html", + isDir: false, + isFile: true, }, - ], - }; - const prefix = "https://example.com/"; - const { queryByText, } = render( - - ); - expect(queryByText("module1")).toBeFalsy() - }); + ], + }, + ], + }, + ], + }; + const prefix = "https://example.com/"; + const { getByText } = render( + + ); + expect(getByText("module1")).toHaveAttribute( + "href", + "https://example.com/analysis/module1/report.html" + ); + expect(getByText("module2")).toHaveAttribute( + "href", + "https://example.com/analysis/module2/report.html" + ); + }); - it("renders correctly when analysis has no children", () => { - const files: DirectoryItem = { - name: "root", - path: "", - isDir: true, - isFile: false, - children: [ - { - name: "analysis", - path: "analysis", - isDir: true, - isFile: false, - }, - ], - }; - const prefix = "https://example.com/"; - const { queryByText } = render( - - ); - expect(queryByText("analysis")).toBeFalsy(); - }); - - it("renders correctly when root has no children", () => { - const files: DirectoryItem = { - name: "root", - path: "", - isDir: true, - isFile: false, - }; - const prefix = "https://example.com/"; - const { queryByText } = render( - - ); - expect(queryByText("analysis")).toBeFalsy(); - }); -}); + it("renders a module with no report.html file", () => { + const files: DirectoryItem = { + name: "root", + path: "", + isDir: true, + isFile: false, + children: [ + { + name: "analysis", + path: "analysis", + isDir: true, + isFile: false, + children: [ + { + name: "module1", + path: "analysis/module1", + isDir: true, + isFile: false, + children: [], + }, + ], + }, + ], + }; + const prefix = "https://example.com/"; + const { queryByText } = render( + + ); + expect(queryByText("module1")).toBeFalsy(); + }); + it("renders correctly when analysis has no children", () => { + const files: DirectoryItem = { + name: "root", + path: "", + isDir: true, + isFile: false, + children: [ + { + name: "analysis", + path: "analysis", + isDir: true, + isFile: false, + }, + ], + }; + const prefix = "https://example.com/"; + const { queryByText } = render( + + ); + expect(queryByText("analysis")).toBeFalsy(); + }); + it("renders correctly when root has no children", () => { + const files: DirectoryItem = { + name: "root", + path: "", + isDir: true, + isFile: false, + }; + const prefix = "https://example.com/"; + const { queryByText } = render( + + ); + expect(queryByText("analysis")).toBeFalsy(); + }); +}); diff --git a/app/components/ListReportFiles.tsx b/app/components/ListReportFiles.tsx index 9570a4af..98f33e52 100644 --- a/app/components/ListReportFiles.tsx +++ b/app/components/ListReportFiles.tsx @@ -20,8 +20,8 @@ export function ListReportFiles({ analyisRoot.children .filter((module) => module.children !== undefined) .forEach((module) => { - const html = module.children?.find((file) => - file.name.endsWith("report.html") + const html = module.children?.find( + (file) => file.name === "report.html" ); if (html !== undefined) { result.set(module.name, html.path);
ID Status NameCreated onUpdated on
{job.id} {job.state}{job.name} + {job.state} + + {job.name} + + {job.createdOn} + + {job.updatedOn} +