mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2026-02-04 14:39:02 +08:00
refactor: add currentTarget back to regular listeners, add childTarget to onChild listeners (@fehmer) (#7273)
rework `onChild` to behave mostly like jQuery `.on` with selector. - we remove `currentTarget` from the `onChild` event handler because native events and jQuery events have different values for it - the jQuery `currentTarget` is available with `childTarget` in our events --------- Co-authored-by: Miodec <jack@monkeytype.com>
This commit is contained in:
parent
86ed9c2570
commit
bd3cd75c94
10 changed files with 386 additions and 92 deletions
6
frontend/__tests__/setup-jsdom.ts
Normal file
6
frontend/__tests__/setup-jsdom.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import $ from "jquery";
|
||||
|
||||
//@ts-expect-error add to global
|
||||
global["$"] = $;
|
||||
//@ts-expect-error add to global
|
||||
global["jQuery"] = $;
|
||||
|
|
@ -2,9 +2,9 @@ import { vi } from "vitest";
|
|||
import $ from "jquery";
|
||||
import { ElementWithUtils } from "../src/ts/utils/dom";
|
||||
|
||||
//@ts-expect-error add to globl
|
||||
//@ts-expect-error add to global
|
||||
global["$"] = $;
|
||||
//@ts-expect-error add to globl
|
||||
//@ts-expect-error add to global
|
||||
global["jQuery"] = $;
|
||||
|
||||
vi.mock("../src/ts/constants/env-config", () => ({
|
||||
|
|
|
|||
|
|
@ -6,5 +6,5 @@
|
|||
"noEmit": true
|
||||
},
|
||||
"files": ["vitest.d.ts"],
|
||||
"include": ["./**/*.spec.ts", "./setup-tests.ts"]
|
||||
"include": ["./**/*.spec.ts", "./**/*.jsdom-spec.ts", "./setup-tests.ts"]
|
||||
}
|
||||
|
|
|
|||
150
frontend/__tests__/utils/dom.jsdom-spec.ts
Normal file
150
frontend/__tests__/utils/dom.jsdom-spec.ts
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { screen } from "@testing-library/dom";
|
||||
import { userEvent } from "@testing-library/user-event";
|
||||
import { qs } from "../../src/ts/utils/dom";
|
||||
|
||||
describe("dom", () => {
|
||||
describe("ElementWithUtils", () => {
|
||||
describe("onChild", () => {
|
||||
const handler = vi.fn();
|
||||
|
||||
function registerOnChild(event: string, selector: string): void {
|
||||
const parent = qs("#parent");
|
||||
parent?.onChild(event, selector, (e) =>
|
||||
handler({
|
||||
target: e.target,
|
||||
childTarget: e.childTarget,
|
||||
//@ts-expect-error will be added later, check TODO on the ChildEvent
|
||||
currentTarget: e.currentTarget,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
handler.mockReset();
|
||||
|
||||
document.body.innerHTML = "";
|
||||
const root = document.createElement("div");
|
||||
|
||||
root.innerHTML = `
|
||||
<div id="parent" data-testid="parent">
|
||||
<section id="decoy">
|
||||
<div id="mid1" data-testid="mid1" class="middle">
|
||||
<div id="inner1" class="inner">test</div>
|
||||
<div id="inner2" data-testid="inner2" class="inner">
|
||||
test
|
||||
<button id="button" data-testid="button">click</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mid2" class="middle">
|
||||
<div id="inner3" class="inner">test</div>
|
||||
<div id="inner4" class="inner">test</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
`;
|
||||
document.body.appendChild(root);
|
||||
});
|
||||
|
||||
it("should not fire when parent element is clicked", async () => {
|
||||
//GIVEN
|
||||
registerOnChild("click", "div");
|
||||
|
||||
//WHEN
|
||||
await userEvent.click(screen.getByTestId("parent"));
|
||||
|
||||
//THEN
|
||||
expect(handler).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should fire when selector is clicked", async () => {
|
||||
//GIVEN
|
||||
registerOnChild("click", "div");
|
||||
|
||||
//WHEN
|
||||
const clickTarget = screen.getByTestId("mid1");
|
||||
await userEvent.click(clickTarget);
|
||||
|
||||
//THEN
|
||||
expect(handler).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
target: clickTarget,
|
||||
childTarget: clickTarget,
|
||||
currentTarget: screen.getByTestId("parent"),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("should fire when child of selector is clicked", async () => {
|
||||
//GIVEN
|
||||
registerOnChild("click", "div.middle");
|
||||
|
||||
//WHEN
|
||||
const selectorTarget = screen.getByTestId("mid1");
|
||||
const clickTarget = screen.getByTestId("button");
|
||||
await userEvent.click(clickTarget);
|
||||
|
||||
//THEN
|
||||
expect(handler).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
target: clickTarget,
|
||||
childTarget: selectorTarget,
|
||||
currentTarget: screen.getByTestId("parent"),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("should fire on each element matching the selector from the child up to the parent", async () => {
|
||||
//GIVEN
|
||||
registerOnChild("click", "div.middle, div.inner");
|
||||
|
||||
//WHEN
|
||||
let clickTarget = screen.getByTestId("button");
|
||||
await userEvent.click(clickTarget);
|
||||
|
||||
//THEN
|
||||
|
||||
//This is the same behavior as jQuery `.on` with selector.
|
||||
//The handler will be called two times,
|
||||
//It does NOT call on the <section> or the parent element itself
|
||||
expect(handler).toHaveBeenCalledTimes(2);
|
||||
|
||||
//First call is for childTarget inner2 (grand child of parent)
|
||||
expect(handler).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
expect.objectContaining({
|
||||
target: clickTarget,
|
||||
childTarget: screen.getByTestId("inner2"),
|
||||
currentTarget: screen.getByTestId("parent"),
|
||||
}),
|
||||
);
|
||||
|
||||
//Second call is for childTarget mid1 (child of parent)
|
||||
expect(handler).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
expect.objectContaining({
|
||||
target: clickTarget,
|
||||
childTarget: screen.getByTestId("mid1"),
|
||||
currentTarget: screen.getByTestId("parent"),
|
||||
}),
|
||||
);
|
||||
|
||||
//WHEN click on mid1 handler is only called one time
|
||||
handler.mockReset();
|
||||
clickTarget = screen.getByTestId("mid1");
|
||||
await userEvent.click(clickTarget);
|
||||
|
||||
//THEN
|
||||
expect(handler).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(handler).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
target: clickTarget,
|
||||
childTarget: clickTarget,
|
||||
currentTarget: screen.getByTestId("parent"),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -61,6 +61,8 @@
|
|||
"@fortawesome/fontawesome-free": "5.15.4",
|
||||
"@monkeytype/oxlint-config": "workspace:*",
|
||||
"@monkeytype/typescript-config": "workspace:*",
|
||||
"@testing-library/dom": "10.4.1",
|
||||
"@testing-library/user-event": "14.6.1",
|
||||
"@types/canvas-confetti": "1.4.3",
|
||||
"@types/chartjs-plugin-trendline": "1.0.1",
|
||||
"@types/damerau-levenshtein": "1.0.0",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
} from "@monkeytype/schemas/configs";
|
||||
import Config, { setConfig } from "../config";
|
||||
import * as Notifications from "../elements/notifications";
|
||||
import { DomUtilsEvent, ElementWithUtils } from "../utils/dom";
|
||||
import { ElementWithUtils } from "../utils/dom";
|
||||
|
||||
export type ValidationResult = {
|
||||
status: "checking" | "success" | "failed" | "warning";
|
||||
|
|
@ -60,7 +60,7 @@ export function createInputEventHandler<T>(
|
|||
callback: (result: ValidationResult) => void,
|
||||
validation: Validation<T>,
|
||||
inputValueConvert?: (val: string) => T,
|
||||
): (e: DomUtilsEvent) => Promise<void> {
|
||||
): (e: Event) => Promise<void> {
|
||||
let callIsValid =
|
||||
validation.isValid !== undefined
|
||||
? debounceIfNeeded(
|
||||
|
|
|
|||
|
|
@ -105,11 +105,18 @@ type ElementWithValue =
|
|||
| HTMLTextAreaElement
|
||||
| HTMLSelectElement;
|
||||
|
||||
export type DomUtilsEvent<T extends Event = Event> = Omit<T, "currentTarget">;
|
||||
//TODO: after the migration from jQuery to dom-utils we might want to add currentTarget back to the event object, if we have a use-case for it.
|
||||
// For now we remove it because currentTarget is not the same element when using dom-utils intead of jQuery to get compile errors.
|
||||
export type OnChildEvent<T extends Event = Event> = Omit<T, "currentTarget"> & {
|
||||
/**
|
||||
* target element matching the selector. This emulates the behavior of `currentTarget` in jQuery events registered with `.on(events, selector, handler)`
|
||||
*/
|
||||
childTarget: EventTarget | null;
|
||||
};
|
||||
|
||||
type DomUtilsEventListenerOrEventListenerObject =
|
||||
| { (evt: DomUtilsEvent): void }
|
||||
| { handleEvent(object: DomUtilsEvent): void };
|
||||
type OnChildEventListenerOrEventListenerObject =
|
||||
| { (evt: OnChildEvent): void }
|
||||
| { handleEvent(object: OnChildEvent): void };
|
||||
|
||||
export class ElementWithUtils<T extends HTMLElement = HTMLElement> {
|
||||
/**
|
||||
|
|
@ -244,56 +251,80 @@ export class ElementWithUtils<T extends HTMLElement = HTMLElement> {
|
|||
*/
|
||||
on<K extends keyof HTMLElementEventMap>(
|
||||
event: K,
|
||||
handler: (this: T, ev: DomUtilsEvent<HTMLElementEventMap[K]>) => void,
|
||||
handler: (this: T, ev: HTMLElementEventMap[K]) => void,
|
||||
): this;
|
||||
on(event: string, handler: DomUtilsEventListenerOrEventListenerObject): this;
|
||||
on(event: string, handler: EventListenerOrEventListenerObject): this;
|
||||
on(
|
||||
event: keyof HTMLElementEventMap | string,
|
||||
handler:
|
||||
| DomUtilsEventListenerOrEventListenerObject
|
||||
| ((this: T, ev: DomUtilsEvent) => void),
|
||||
| EventListenerOrEventListenerObject
|
||||
| ((this: T, ev: Event) => void),
|
||||
): this {
|
||||
// this type was some AI magic but if it works it works
|
||||
this.native.addEventListener(
|
||||
event,
|
||||
handler as DomUtilsEventListenerOrEventListenerObject,
|
||||
handler as EventListenerOrEventListenerObject,
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach an event listener to child elements matching the query.
|
||||
* Attach an event listener to child elements matching the selector.
|
||||
* Useful for dynamically added elements.
|
||||
*
|
||||
* The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements)
|
||||
* that match the selector. Bubbles the event from the event target up to the element where the handler is attached
|
||||
* (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.
|
||||
*/
|
||||
onChild<K extends keyof HTMLElementEventMap>(
|
||||
event: K,
|
||||
query: string,
|
||||
/**
|
||||
* A selector string to filter the descendants of the selected elements that will call the handler.
|
||||
*/
|
||||
selector: string,
|
||||
handler: (
|
||||
this: HTMLElement,
|
||||
ev: DomUtilsEvent<HTMLElementEventMap[K]>,
|
||||
ev: OnChildEvent<HTMLElementEventMap[K]>,
|
||||
) => void,
|
||||
): this;
|
||||
onChild(
|
||||
event: string,
|
||||
query: string,
|
||||
handler: DomUtilsEventListenerOrEventListenerObject,
|
||||
/**
|
||||
* A selector string to filter the descendants of the selected elements that will call the handler.
|
||||
*/
|
||||
selector: string,
|
||||
handler: OnChildEventListenerOrEventListenerObject,
|
||||
): this;
|
||||
onChild(
|
||||
event: keyof HTMLElementEventMap | string,
|
||||
query: string,
|
||||
/**
|
||||
* A selector string to filter the descendants of the selected elements that will call the handler.
|
||||
*/
|
||||
selector: string,
|
||||
handler:
|
||||
| DomUtilsEventListenerOrEventListenerObject
|
||||
| ((this: HTMLElement, ev: DomUtilsEvent) => void),
|
||||
| OnChildEventListenerOrEventListenerObject
|
||||
| ((this: HTMLElement, ev: OnChildEvent) => void),
|
||||
): this {
|
||||
// this type was some AI magic but if it works it works
|
||||
this.native.addEventListener(event, (e) => {
|
||||
const target = e.target as HTMLElement;
|
||||
if (target !== null && target.matches(query)) {
|
||||
if (target === null) return; //ignore event
|
||||
|
||||
let childTarget = target.closest(selector);
|
||||
//bubble up until no match found or the parent element is reached
|
||||
while (childTarget !== null && childTarget !== this.native) {
|
||||
if (typeof handler === "function") {
|
||||
handler.call(target, e);
|
||||
handler.call(
|
||||
childTarget as HTMLElement,
|
||||
Object.assign(e, { childTarget }),
|
||||
);
|
||||
} else {
|
||||
handler.handleEvent(e);
|
||||
handler.handleEvent(Object.assign(e, { childTarget }));
|
||||
}
|
||||
|
||||
childTarget =
|
||||
childTarget.parentElement !== null
|
||||
? childTarget.parentElement.closest(selector)
|
||||
: null;
|
||||
}
|
||||
});
|
||||
return this;
|
||||
|
|
@ -680,21 +711,20 @@ export class ElementsWithUtils<
|
|||
*/
|
||||
on<K extends keyof HTMLElementEventMap>(
|
||||
event: K,
|
||||
handler: (this: T, ev: DomUtilsEvent<HTMLElementEventMap[K]>) => void,
|
||||
handler: (this: T, ev: HTMLElementEventMap[K]) => void,
|
||||
): this;
|
||||
on(event: string, handler: DomUtilsEventListenerOrEventListenerObject): this;
|
||||
on(event: string, handler: EventListenerOrEventListenerObject): this;
|
||||
on(
|
||||
event: keyof HTMLElementEventMap | string,
|
||||
handler:
|
||||
| DomUtilsEventListenerOrEventListenerObject
|
||||
| ((this: T, ev: DomUtilsEvent) => void),
|
||||
| EventListenerOrEventListenerObject
|
||||
| ((this: T, ev: Event) => void),
|
||||
): this {
|
||||
for (const item of this) {
|
||||
item.on(event, handler);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set attribute value on all elements in the array
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,13 +1,39 @@
|
|||
import { defineConfig } from "vitest/config";
|
||||
import { defineConfig, UserWorkspaceConfig } from "vitest/config";
|
||||
import { languageHashes } from "./vite-plugins/language-hashes";
|
||||
import { envConfig } from "./vite-plugins/env-config";
|
||||
|
||||
const plugins = [
|
||||
languageHashes({ skip: true }),
|
||||
envConfig({ isDevelopment: true, clientVersion: "TESTING", env: {} }),
|
||||
];
|
||||
|
||||
export const projects: UserWorkspaceConfig[] = [
|
||||
{
|
||||
test: {
|
||||
name: { label: "unit", color: "blue" },
|
||||
include: ["__tests__/**/*.spec.ts"],
|
||||
exclude: ["__tests__/**/*.jsdom-spec.ts"],
|
||||
environment: "happy-dom",
|
||||
globalSetup: "__tests__/global-setup.ts",
|
||||
setupFiles: ["__tests__/setup-tests.ts"],
|
||||
},
|
||||
plugins,
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: { label: "jsdom", color: "yellow" },
|
||||
include: ["__tests__/**/*.jsdom-spec.ts"],
|
||||
exclude: ["__tests__/**/*.spec.ts"],
|
||||
environment: "happy-dom",
|
||||
globalSetup: "__tests__/global-setup.ts",
|
||||
setupFiles: ["__tests__/setup-jsdom.ts"],
|
||||
},
|
||||
plugins,
|
||||
},
|
||||
];
|
||||
export default defineConfig({
|
||||
test: {
|
||||
environment: "happy-dom",
|
||||
globalSetup: "__tests__/global-setup.ts",
|
||||
setupFiles: ["__tests__/setup-tests.ts"],
|
||||
|
||||
projects: projects,
|
||||
coverage: {
|
||||
include: ["**/*.ts"],
|
||||
},
|
||||
|
|
@ -19,9 +45,4 @@ export default defineConfig({
|
|||
},
|
||||
},
|
||||
},
|
||||
|
||||
plugins: [
|
||||
languageHashes({ skip: true }),
|
||||
envConfig({ isDevelopment: true, clientVersion: "TESTING", env: {} }),
|
||||
],
|
||||
});
|
||||
|
|
|
|||
155
pnpm-lock.yaml
generated
155
pnpm-lock.yaml
generated
|
|
@ -370,6 +370,12 @@ importers:
|
|||
'@monkeytype/typescript-config':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/typescript-config
|
||||
'@testing-library/dom':
|
||||
specifier: 10.4.1
|
||||
version: 10.4.1
|
||||
'@testing-library/user-event':
|
||||
specifier: 14.6.1
|
||||
version: 14.6.1(@testing-library/dom@10.4.1)
|
||||
'@types/canvas-confetti':
|
||||
specifier: 1.4.3
|
||||
version: 1.4.3
|
||||
|
|
@ -1198,10 +1204,6 @@ packages:
|
|||
resolution: {integrity: sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/runtime@7.28.2':
|
||||
resolution: {integrity: sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/runtime@7.28.4':
|
||||
resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
|
@ -3111,6 +3113,16 @@ packages:
|
|||
'@surma/rollup-plugin-off-main-thread@2.2.3':
|
||||
resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==}
|
||||
|
||||
'@testing-library/dom@10.4.1':
|
||||
resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@testing-library/user-event@14.6.1':
|
||||
resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==}
|
||||
engines: {node: '>=12', npm: '>=6'}
|
||||
peerDependencies:
|
||||
'@testing-library/dom': '>=7.21.4'
|
||||
|
||||
'@tootallnate/once@2.0.0':
|
||||
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
|
||||
engines: {node: '>= 10'}
|
||||
|
|
@ -3173,6 +3185,9 @@ packages:
|
|||
'@tsconfig/node16@1.0.4':
|
||||
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
|
||||
|
||||
'@types/aria-query@5.0.4':
|
||||
resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
|
||||
|
||||
'@types/bcrypt@5.0.2':
|
||||
resolution: {integrity: sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==}
|
||||
|
||||
|
|
@ -3552,10 +3567,6 @@ packages:
|
|||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-regex@6.0.1:
|
||||
resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
ansi-regex@6.2.2:
|
||||
resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
|
||||
engines: {node: '>=12'}
|
||||
|
|
@ -3611,6 +3622,9 @@ packages:
|
|||
argparse@2.0.1:
|
||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||
|
||||
aria-query@5.3.0:
|
||||
resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
|
||||
|
||||
arity-n@1.0.4:
|
||||
resolution: {integrity: sha512-fExL2kFDC1Q2DUOx3whE/9KoN66IzkY4b4zUHUBFM1ojEYjZZYDcUW3bek/ufGionX9giIKDC5redH2IlGqcQQ==}
|
||||
|
||||
|
|
@ -4628,6 +4642,10 @@ packages:
|
|||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
dequal@2.0.3:
|
||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
destroy@1.2.0:
|
||||
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
|
||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||
|
|
@ -4715,6 +4733,9 @@ packages:
|
|||
resolution: {integrity: sha512-iND4mcOWhPaCNh54WmK/KoSb35AFqPAUWFMffTQcp52uQt36b5uNwEJTSXntJZBbeGad72Crbi/hvDIv6us/6Q==}
|
||||
engines: {node: '>= 8.0'}
|
||||
|
||||
dom-accessibility-api@0.5.16:
|
||||
resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
|
||||
|
||||
dom-serializer@1.4.1:
|
||||
resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==}
|
||||
|
||||
|
|
@ -6452,6 +6473,10 @@ packages:
|
|||
resolution: {integrity: sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
lz-string@1.5.0:
|
||||
resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
|
||||
hasBin: true
|
||||
|
||||
lz-ts@1.1.2:
|
||||
resolution: {integrity: sha512-ye8sVndmvzs46cPgX1Yjlk3o/Sueu0VHn253rKpsWiK2/bAbsVkD7DEJiaueiPfbZTi17GLRPkv3W5O3BUNd2g==}
|
||||
|
||||
|
|
@ -7552,6 +7577,10 @@ packages:
|
|||
resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
|
||||
engines: {node: ^14.13.1 || >=16.0.0}
|
||||
|
||||
pretty-format@27.5.1:
|
||||
resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
|
||||
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
|
||||
|
||||
pretty-format@29.7.0:
|
||||
resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
|
|
@ -7715,6 +7744,9 @@ packages:
|
|||
react-is@16.13.1:
|
||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||
|
||||
react-is@17.0.2:
|
||||
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
|
||||
|
||||
react-is@18.3.1:
|
||||
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
|
||||
|
||||
|
|
@ -10225,8 +10257,6 @@ snapshots:
|
|||
dependencies:
|
||||
regenerator-runtime: 0.14.1
|
||||
|
||||
'@babel/runtime@7.28.2': {}
|
||||
|
||||
'@babel/runtime@7.28.4': {}
|
||||
|
||||
'@babel/template@7.25.0':
|
||||
|
|
@ -12194,6 +12224,21 @@ snapshots:
|
|||
magic-string: 0.25.9
|
||||
string.prototype.matchall: 4.0.12
|
||||
|
||||
'@testing-library/dom@10.4.1':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.27.1
|
||||
'@babel/runtime': 7.28.4
|
||||
'@types/aria-query': 5.0.4
|
||||
aria-query: 5.3.0
|
||||
dom-accessibility-api: 0.5.16
|
||||
lz-string: 1.5.0
|
||||
picocolors: 1.1.1
|
||||
pretty-format: 27.5.1
|
||||
|
||||
'@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)':
|
||||
dependencies:
|
||||
'@testing-library/dom': 10.4.1
|
||||
|
||||
'@tootallnate/once@2.0.0': {}
|
||||
|
||||
'@tootallnate/quickjs-emscripten@0.23.0': {}
|
||||
|
|
@ -12240,6 +12285,8 @@ snapshots:
|
|||
|
||||
'@tsconfig/node16@1.0.4': {}
|
||||
|
||||
'@types/aria-query@5.0.4': {}
|
||||
|
||||
'@types/bcrypt@5.0.2':
|
||||
dependencies:
|
||||
'@types/node': 24.9.1
|
||||
|
|
@ -12734,8 +12781,6 @@ snapshots:
|
|||
|
||||
ansi-regex@5.0.1: {}
|
||||
|
||||
ansi-regex@6.0.1: {}
|
||||
|
||||
ansi-regex@6.2.2: {}
|
||||
|
||||
ansi-styles@4.3.0:
|
||||
|
|
@ -12790,6 +12835,10 @@ snapshots:
|
|||
|
||||
argparse@2.0.1: {}
|
||||
|
||||
aria-query@5.3.0:
|
||||
dependencies:
|
||||
dequal: 2.0.3
|
||||
|
||||
arity-n@1.0.4: {}
|
||||
|
||||
array-buffer-byte-length@1.0.2:
|
||||
|
|
@ -13853,6 +13902,8 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
dequal@2.0.3: {}
|
||||
|
||||
destroy@1.2.0: {}
|
||||
|
||||
detect-libc@2.0.3: {}
|
||||
|
|
@ -13956,6 +14007,8 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
dom-accessibility-api@0.5.16: {}
|
||||
|
||||
dom-serializer@1.4.1:
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
|
|
@ -16181,6 +16234,8 @@ snapshots:
|
|||
|
||||
luxon@3.4.4: {}
|
||||
|
||||
lz-string@1.5.0: {}
|
||||
|
||||
lz-ts@1.1.2: {}
|
||||
|
||||
madge@8.0.0(typescript@5.9.3):
|
||||
|
|
@ -16426,7 +16481,7 @@ snapshots:
|
|||
|
||||
mjml-accordion@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16434,7 +16489,7 @@ snapshots:
|
|||
|
||||
mjml-body@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16442,7 +16497,7 @@ snapshots:
|
|||
|
||||
mjml-button@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16450,7 +16505,7 @@ snapshots:
|
|||
|
||||
mjml-carousel@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16458,7 +16513,7 @@ snapshots:
|
|||
|
||||
mjml-cli@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
chokidar: 3.6.0
|
||||
glob: 10.4.5
|
||||
html-minifier: 4.0.0
|
||||
|
|
@ -16474,7 +16529,7 @@ snapshots:
|
|||
|
||||
mjml-column@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16482,7 +16537,7 @@ snapshots:
|
|||
|
||||
mjml-core@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
cheerio: 1.0.0-rc.12
|
||||
detect-node: 2.1.0
|
||||
html-minifier: 4.0.0
|
||||
|
|
@ -16497,7 +16552,7 @@ snapshots:
|
|||
|
||||
mjml-divider@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16505,7 +16560,7 @@ snapshots:
|
|||
|
||||
mjml-group@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16513,7 +16568,7 @@ snapshots:
|
|||
|
||||
mjml-head-attributes@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16521,7 +16576,7 @@ snapshots:
|
|||
|
||||
mjml-head-breakpoint@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16529,7 +16584,7 @@ snapshots:
|
|||
|
||||
mjml-head-font@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16537,7 +16592,7 @@ snapshots:
|
|||
|
||||
mjml-head-html-attributes@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16545,7 +16600,7 @@ snapshots:
|
|||
|
||||
mjml-head-preview@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16553,7 +16608,7 @@ snapshots:
|
|||
|
||||
mjml-head-style@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16561,7 +16616,7 @@ snapshots:
|
|||
|
||||
mjml-head-title@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16569,7 +16624,7 @@ snapshots:
|
|||
|
||||
mjml-head@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16577,7 +16632,7 @@ snapshots:
|
|||
|
||||
mjml-hero@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16585,7 +16640,7 @@ snapshots:
|
|||
|
||||
mjml-image@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16593,7 +16648,7 @@ snapshots:
|
|||
|
||||
mjml-migrate@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
js-beautify: 1.15.1
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
|
|
@ -16604,7 +16659,7 @@ snapshots:
|
|||
|
||||
mjml-navbar@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16612,14 +16667,14 @@ snapshots:
|
|||
|
||||
mjml-parser-xml@4.15.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
detect-node: 2.1.0
|
||||
htmlparser2: 9.1.0
|
||||
lodash: 4.17.21
|
||||
|
||||
mjml-preset-core@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
mjml-accordion: 4.15.0(encoding@0.1.13)
|
||||
mjml-body: 4.15.0(encoding@0.1.13)
|
||||
mjml-button: 4.15.0(encoding@0.1.13)
|
||||
|
|
@ -16650,7 +16705,7 @@ snapshots:
|
|||
|
||||
mjml-raw@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16658,7 +16713,7 @@ snapshots:
|
|||
|
||||
mjml-section@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16666,7 +16721,7 @@ snapshots:
|
|||
|
||||
mjml-social@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16674,7 +16729,7 @@ snapshots:
|
|||
|
||||
mjml-spacer@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16682,7 +16737,7 @@ snapshots:
|
|||
|
||||
mjml-table@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16690,7 +16745,7 @@ snapshots:
|
|||
|
||||
mjml-text@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -16698,11 +16753,11 @@ snapshots:
|
|||
|
||||
mjml-validator@4.13.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
|
||||
mjml-wrapper@4.15.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
'@babel/runtime': 7.28.4
|
||||
lodash: 4.17.21
|
||||
mjml-core: 4.15.0(encoding@0.1.13)
|
||||
mjml-section: 4.15.0(encoding@0.1.13)
|
||||
|
|
@ -17393,7 +17448,7 @@ snapshots:
|
|||
|
||||
polished@4.3.1:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.2
|
||||
'@babel/runtime': 7.28.4
|
||||
|
||||
portfinder@1.0.32:
|
||||
dependencies:
|
||||
|
|
@ -17478,6 +17533,12 @@ snapshots:
|
|||
|
||||
pretty-bytes@6.1.1: {}
|
||||
|
||||
pretty-format@27.5.1:
|
||||
dependencies:
|
||||
ansi-regex: 5.0.1
|
||||
ansi-styles: 5.2.0
|
||||
react-is: 17.0.2
|
||||
|
||||
pretty-format@29.7.0:
|
||||
dependencies:
|
||||
'@jest/schemas': 29.6.3
|
||||
|
|
@ -17667,6 +17728,8 @@ snapshots:
|
|||
|
||||
react-is@16.13.1: {}
|
||||
|
||||
react-is@17.0.2: {}
|
||||
|
||||
react-is@18.3.1: {}
|
||||
|
||||
react-tabs@6.0.2(react@18.3.1):
|
||||
|
|
@ -18561,7 +18624,7 @@ snapshots:
|
|||
|
||||
strip-ansi@7.1.0:
|
||||
dependencies:
|
||||
ansi-regex: 6.0.1
|
||||
ansi-regex: 6.2.2
|
||||
|
||||
strip-ansi@7.1.2:
|
||||
dependencies:
|
||||
|
|
@ -19208,7 +19271,7 @@ snapshots:
|
|||
dependencies:
|
||||
browserslist: 4.23.3
|
||||
escalade: 3.2.0
|
||||
picocolors: 1.0.1
|
||||
picocolors: 1.1.1
|
||||
|
||||
update-browserslist-db@1.1.3(browserslist@4.24.4):
|
||||
dependencies:
|
||||
|
|
|
|||
|
|
@ -1,15 +1,37 @@
|
|||
import { defineConfig, UserWorkspaceConfig } from "vitest/config";
|
||||
import { projects as backendProjects } from "./backend/vitest.config";
|
||||
import { projects as frontendProjects } from "./frontend/vitest.config";
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
projects: [
|
||||
...backendProjects.map(
|
||||
(it) =>
|
||||
({ test: { ...it.test, root: "backend" } }) as UserWorkspaceConfig,
|
||||
),
|
||||
"frontend/vitest.config.ts",
|
||||
...convertTests(backendProjects, "backend"),
|
||||
...convertTests(frontendProjects, "frontend"),
|
||||
"packages/**/vitest.config.ts",
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
function convertTests(
|
||||
projects: unknown[],
|
||||
root: string,
|
||||
): UserWorkspaceConfig[] {
|
||||
return (projects as UserWorkspaceConfig[]).map((it) => {
|
||||
const test = it.test ?? {};
|
||||
const name: string | { label: string } = test.name ?? "unknown";
|
||||
|
||||
let updatedName =
|
||||
name === null || typeof name === "string"
|
||||
? `${name} (${root})`
|
||||
: { ...name, label: `${name.label} (${root})` };
|
||||
|
||||
return {
|
||||
...it,
|
||||
test: {
|
||||
...test,
|
||||
root,
|
||||
name: updatedName,
|
||||
},
|
||||
} as UserWorkspaceConfig;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue