@multiplatform.one/test-utils 6.1.0 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -0
- package/package.json +12 -8
- package/src/setup.ts +36 -37
- package/types/index.d.ts +96 -0
- package/types/index.d.ts.map +1 -0
- package/types/mocks.d.ts +125 -0
- package/types/mocks.d.ts.map +1 -0
- package/types/setup.d.ts +18 -0
- package/types/setup.d.ts.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# @multiplatform.one/test-utils
|
|
2
|
+
|
|
3
|
+
Shared testing utilities for multiplatform.one packages and apps: provider-aware
|
|
4
|
+
rendering for Tamagui/React Native Web components, DOM query helpers, and mocks
|
|
5
|
+
for Frappe and Keycloak.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add -D @multiplatform.one/test-utils
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Peers: `react`, `react-dom`, `vitest` (pairs with `@testing-library/react`).
|
|
14
|
+
|
|
15
|
+
## What it owns
|
|
16
|
+
|
|
17
|
+
- **`renderWithProviders(ui, options?)`** — renders inside `TamaguiProvider` +
|
|
18
|
+
`QueryClientProvider` (both on by default), optional theme / Frappe / Keycloak
|
|
19
|
+
wrappers; returns an enhanced result with RNW-aware queries (`getInput`,
|
|
20
|
+
`getButton`, `getCheckbox`, `getSelect`, `getSlider`, `getSwitch`,
|
|
21
|
+
`getLabel`, `getError`, …)
|
|
22
|
+
- **`TestProviders`**, `createFixture`, `findTextInContainer`
|
|
23
|
+
- **`/mocks`** — `createMockFrappeApp`, `mockDocList`, `mockGetDoc`,
|
|
24
|
+
`mockCreateDoc`, `mockUpdateDoc`, `mockDeleteDoc`,
|
|
25
|
+
`createMockKeycloakContext`
|
|
26
|
+
- **`/setup`** — vitest setup entry (jsdom shims) for `setupFiles`
|
|
27
|
+
|
|
28
|
+
## What it must not do
|
|
29
|
+
|
|
30
|
+
- Never imported by production code — dev dependency only
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
36
|
+
|
|
37
|
+
test("renders the user card", () => {
|
|
38
|
+
const { getByText, getButton } = renderWithProviders(<UserCard name="Ada" />);
|
|
39
|
+
expect(getByText("Ada")).toBeInTheDocument();
|
|
40
|
+
expect(getButton("Save")).toBeDefined();
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
// vitest.config.ts
|
|
46
|
+
export default defineConfig({
|
|
47
|
+
test: { setupFiles: ["@multiplatform.one/test-utils/setup"] },
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## License
|
|
52
|
+
|
|
53
|
+
Apache-2.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplatform.one/test-utils",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"description": "Shared testing utilities for multiplatform.one packages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"multiplatform.one",
|
|
@@ -18,30 +18,33 @@
|
|
|
18
18
|
"author": "BitSpur <support@risserlabs.com> (https://risserlabs.com)",
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
21
|
-
"url": "https://gitlab.com/bitspur/multiplatform.one
|
|
21
|
+
"url": "git+https://gitlab.com/bitspur/frappe/multiplatform.one.git",
|
|
22
|
+
"directory": "public/test-utils"
|
|
22
23
|
},
|
|
23
24
|
"source": "src/index.tsx",
|
|
24
25
|
"files": [
|
|
25
|
-
"src"
|
|
26
|
+
"src",
|
|
27
|
+
"types",
|
|
28
|
+
"!types/.tsbuildinfo"
|
|
26
29
|
],
|
|
27
30
|
"sideEffects": false,
|
|
28
31
|
"main": "src/index.tsx",
|
|
29
32
|
"module": "src/index.tsx",
|
|
30
|
-
"types": "
|
|
33
|
+
"types": "types/index.d.ts",
|
|
31
34
|
"exports": {
|
|
32
35
|
"./package.json": "./package.json",
|
|
33
36
|
".": {
|
|
34
|
-
"types": "./
|
|
37
|
+
"types": "./types/index.d.ts",
|
|
35
38
|
"import": "./src/index.tsx",
|
|
36
39
|
"require": "./src/index.tsx"
|
|
37
40
|
},
|
|
38
41
|
"./setup": {
|
|
39
|
-
"types": "./
|
|
42
|
+
"types": "./types/setup.d.ts",
|
|
40
43
|
"import": "./src/setup.ts",
|
|
41
44
|
"require": "./src/setup.ts"
|
|
42
45
|
},
|
|
43
46
|
"./mocks": {
|
|
44
|
-
"types": "./
|
|
47
|
+
"types": "./types/mocks.d.ts",
|
|
45
48
|
"import": "./src/mocks.ts",
|
|
46
49
|
"require": "./src/mocks.ts"
|
|
47
50
|
}
|
|
@@ -71,6 +74,7 @@
|
|
|
71
74
|
"node": ">=18.0.0"
|
|
72
75
|
},
|
|
73
76
|
"scripts": {
|
|
74
|
-
"typecheck": "tsc --noEmit"
|
|
77
|
+
"typecheck": "tsc --noEmit",
|
|
78
|
+
"build": "rm -rf types 2>/dev/null && tsc -p tsconfig.build.json"
|
|
75
79
|
}
|
|
76
80
|
}
|
package/src/setup.ts
CHANGED
|
@@ -417,44 +417,43 @@ Object.defineProperty(global, "TextEncoder", {
|
|
|
417
417
|
writable: true,
|
|
418
418
|
});
|
|
419
419
|
|
|
420
|
-
// Mock @multiplatform.one/theme
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
heading: { fontFamily: "$heading", fontWeight: "400" },
|
|
440
|
-
body: { fontFamily: "$body", fontWeight: "400" },
|
|
441
|
-
textWeight: { fontWeight: "400" },
|
|
442
|
-
transition: "quick",
|
|
443
|
-
outlined: false,
|
|
444
|
-
textAccent: "high",
|
|
445
|
-
space: "medium",
|
|
446
|
-
hoverStyle: emptyState,
|
|
447
|
-
pressStyle: emptyState,
|
|
448
|
-
focusStyle: emptyState,
|
|
449
|
-
focusVisibleStyle: emptyState,
|
|
450
|
-
};
|
|
420
|
+
// Mock @multiplatform.one/theme as a passthrough partial mock: the REAL module
|
|
421
|
+
// is spread first, so knob/preset resolution (`useResolvedKnobs` / `Preset` /
|
|
422
|
+
// `useSemanticGaps` — specs assert LC-18 knob totality), DEV-warn guards
|
|
423
|
+
// (specs assert their console.warn output, so they must stay real), the date
|
|
424
|
+
// formatters, chart palette, readable-color logic, and any FUTURE theme export
|
|
425
|
+
// all resolve through the actual implementation without touching this file.
|
|
426
|
+
// Only the hooks below are replaced, each because the real implementation is
|
|
427
|
+
// unsafe in the test environment — NOT to pin spec-friendly values. Packages
|
|
428
|
+
// needing different behavior re-register the mock in a later setup file /
|
|
429
|
+
// spec (last `vi.mock` registration for a path wins).
|
|
430
|
+
vi.mock("@multiplatform.one/theme", async (importOriginal) => {
|
|
431
|
+
const actual = (await importOriginal()) as Record<string, unknown>;
|
|
432
|
+
|
|
433
|
+
const getSizeClass = actual.getLayoutSizeClass as (width: number) => string;
|
|
434
|
+
const getPaneBudget = actual.defaultMaxPanes as (sizeClass: string) => 1 | 2;
|
|
435
|
+
// Same SSR fallback the real hook uses (layoutBreakpoints.medium).
|
|
436
|
+
const fallbackWidth = (actual.layoutBreakpoints as { medium: number }).medium;
|
|
437
|
+
const viewportWidth = () => (typeof window === "undefined" ? fallbackWidth : window.innerWidth);
|
|
438
|
+
|
|
451
439
|
return {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
440
|
+
...actual,
|
|
441
|
+
// Real useLayoutSizeClass subscribes via matchMedia().addEventListener,
|
|
442
|
+
// which test matchMedia polyfills / per-spec vi.fn mocks routinely lack;
|
|
443
|
+
// resolve from window.innerWidth at render (the same value the real hook
|
|
444
|
+
// computes at mount) through the real getLayoutSizeClass.
|
|
445
|
+
useLayoutSizeClass: () => getSizeClass(viewportWidth()),
|
|
446
|
+
// Rides useLayoutSizeClass (same matchMedia dependency); derive the pane
|
|
447
|
+
// budget through the real defaultMaxPanes.
|
|
448
|
+
useMultiPane: (maxPanes?: 1 | 2) => {
|
|
449
|
+
const budget = getPaneBudget(getSizeClass(viewportWidth()));
|
|
450
|
+
return (maxPanes ?? budget) >= 2 && budget >= 2;
|
|
451
|
+
},
|
|
452
|
+
// Real tracker installs document-level capture listeners backed by module
|
|
453
|
+
// state, leaking "last input was keyboard" across tests in a file; noop.
|
|
454
|
+
ensureKeyboardModalityTracking: () => {},
|
|
455
|
+
// Pin pointer modality so manual focus-ring painting is deterministic.
|
|
456
|
+
wasKeyboardFocus: () => false,
|
|
458
457
|
};
|
|
459
458
|
});
|
|
460
459
|
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared test utilities for multiplatform.one packages.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```tsx
|
|
6
|
+
* import { renderWithProviders, createFixture } from "@multiplatform.one/test-utils";
|
|
7
|
+
*
|
|
8
|
+
* test("renders pokemon card", () => {
|
|
9
|
+
* const { getByText } = renderWithProviders(<PokemonCard name="Pikachu" />);
|
|
10
|
+
* expect(getByText("Pikachu")).toBeInTheDocument();
|
|
11
|
+
* });
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
import type { RenderOptions, RenderResult } from "@testing-library/react";
|
|
15
|
+
import type { ReactElement, ReactNode } from "react";
|
|
16
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
17
|
+
export interface RenderWithProvidersOptions extends Omit<RenderOptions, "wrapper"> {
|
|
18
|
+
/** Wrap in TamaguiProvider. Defaults to true. */
|
|
19
|
+
tamagui?: boolean;
|
|
20
|
+
/** Wrap in QueryClientProvider. Defaults to true. Pass a QueryClient to use a custom one. */
|
|
21
|
+
queryClient?: boolean | QueryClient;
|
|
22
|
+
/** Wrap in ThemeProvider. Defaults to false. */
|
|
23
|
+
theme?: boolean;
|
|
24
|
+
/** Wrap in FrappeProvider with mock. Defaults to false. */
|
|
25
|
+
frappe?: false | {
|
|
26
|
+
baseURL?: string;
|
|
27
|
+
};
|
|
28
|
+
/** Wrap in KeycloakProvider with mock. Defaults to false. */
|
|
29
|
+
keycloak?: false | {
|
|
30
|
+
authenticated?: boolean;
|
|
31
|
+
roles?: string[];
|
|
32
|
+
token?: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Enhanced render result with extra DOM query helpers for React Native Web
|
|
37
|
+
* components (Tamagui). These helpers handle the unique DOM structure
|
|
38
|
+
* produced by RNW and Tamagui.
|
|
39
|
+
*/
|
|
40
|
+
export interface EnhancedRenderResult extends RenderResult {
|
|
41
|
+
getInput: (name?: string) => Element | null | undefined;
|
|
42
|
+
getAllInputs: () => Element[];
|
|
43
|
+
getButton: (text: string) => Element | undefined;
|
|
44
|
+
getSubmitButton: () => Element | null;
|
|
45
|
+
findTextElement: (text: string) => Element | undefined;
|
|
46
|
+
getTextArea: (name?: string) => Element | null;
|
|
47
|
+
getCheckbox: (name?: string) => Element | null | undefined;
|
|
48
|
+
getRadio: (value?: string) => Element | null | undefined;
|
|
49
|
+
getSelect: (name?: string) => Element | null;
|
|
50
|
+
getSlider: (name?: string) => Element | null;
|
|
51
|
+
getSwitch: (name?: string) => Element | null;
|
|
52
|
+
getLabel: (text: string) => Element | null | undefined;
|
|
53
|
+
getError: () => Element | null | undefined;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Standard test providers wrapper component.
|
|
57
|
+
* Wraps children in TamaguiProvider + YStack.
|
|
58
|
+
* Useful when you need to pass a wrapper directly to `render()`.
|
|
59
|
+
*/
|
|
60
|
+
export declare function TestProviders({ children }: {
|
|
61
|
+
children: ReactNode;
|
|
62
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
63
|
+
/**
|
|
64
|
+
* Render a React element wrapped with configurable providers.
|
|
65
|
+
*
|
|
66
|
+
* By default wraps with TamaguiProvider and QueryClientProvider.
|
|
67
|
+
* Additional providers (theme, frappe, keycloak) can be enabled via options.
|
|
68
|
+
*
|
|
69
|
+
* Returns an enhanced render result with extra DOM query helpers for
|
|
70
|
+
* React Native Web / Tamagui components (getInput, getButton, getSubmitButton, etc.).
|
|
71
|
+
*/
|
|
72
|
+
export declare function renderWithProviders(ui: ReactElement, options?: RenderWithProvidersOptions): EnhancedRenderResult;
|
|
73
|
+
/** Find text within a container element */
|
|
74
|
+
export declare function findTextInContainer(container: HTMLElement, text: string): HTMLElement | null;
|
|
75
|
+
/** Wait for an element to appear within a timeout */
|
|
76
|
+
export declare function waitForElement(getFn: () => HTMLElement | null, timeout?: number): Promise<HTMLElement>;
|
|
77
|
+
/**
|
|
78
|
+
* Generate a test fixture for a Frappe doctype with auto-generated name
|
|
79
|
+
* and sensible defaults. Override any field via the overrides parameter.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* interface Task {
|
|
84
|
+
* name: string;
|
|
85
|
+
* subject: string;
|
|
86
|
+
* status: "Open" | "Working" | "Completed";
|
|
87
|
+
* }
|
|
88
|
+
*
|
|
89
|
+
* const task = createFixture<Task>("Task", { subject: "Test task", status: "Open" });
|
|
90
|
+
* // Returns: { name: "Task-xxxx", subject: "Test task", status: "Open" }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export declare function createFixture<T extends Record<string, unknown>>(doctype: string, overrides?: Partial<T>): T;
|
|
94
|
+
export { render, screen, fireEvent, waitFor, act, within } from "@testing-library/react";
|
|
95
|
+
export { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
96
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
|
package/types/mocks.d.ts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared mock factories for multiplatform.one packages.
|
|
3
|
+
*
|
|
4
|
+
* Provides mock Frappe API and Keycloak auth context for testing.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { createMockFrappeApp, mockDocList, createMockKeycloakContext } from "@multiplatform.one/test-utils/mocks";
|
|
9
|
+
*
|
|
10
|
+
* const mockApp = createMockFrappeApp();
|
|
11
|
+
* mockDocList(mockApp, "ToDo", [{ name: "TODO-001", description: "Buy milk" }]);
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
import { vi } from "vitest";
|
|
15
|
+
export interface MockDbModule {
|
|
16
|
+
getDocList: ReturnType<typeof vi.fn>;
|
|
17
|
+
getDoc: ReturnType<typeof vi.fn>;
|
|
18
|
+
createDoc: ReturnType<typeof vi.fn>;
|
|
19
|
+
updateDoc: ReturnType<typeof vi.fn>;
|
|
20
|
+
deleteDoc: ReturnType<typeof vi.fn>;
|
|
21
|
+
getCount: ReturnType<typeof vi.fn>;
|
|
22
|
+
getValue: ReturnType<typeof vi.fn>;
|
|
23
|
+
setValue: ReturnType<typeof vi.fn>;
|
|
24
|
+
exists: ReturnType<typeof vi.fn>;
|
|
25
|
+
}
|
|
26
|
+
export interface MockCallModule {
|
|
27
|
+
get: ReturnType<typeof vi.fn>;
|
|
28
|
+
post: ReturnType<typeof vi.fn>;
|
|
29
|
+
}
|
|
30
|
+
export interface MockAuthModule {
|
|
31
|
+
getLoggedInUser: ReturnType<typeof vi.fn>;
|
|
32
|
+
login: ReturnType<typeof vi.fn>;
|
|
33
|
+
logout: ReturnType<typeof vi.fn>;
|
|
34
|
+
}
|
|
35
|
+
export interface MockFileModule {
|
|
36
|
+
uploadFile: ReturnType<typeof vi.fn>;
|
|
37
|
+
deleteFile: ReturnType<typeof vi.fn>;
|
|
38
|
+
getFileURL: ReturnType<typeof vi.fn>;
|
|
39
|
+
}
|
|
40
|
+
export interface MockFrappeApp {
|
|
41
|
+
db: MockDbModule;
|
|
42
|
+
call: MockCallModule;
|
|
43
|
+
auth: MockAuthModule;
|
|
44
|
+
file: MockFileModule;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Create a mock FrappeApp with all modules stubbed.
|
|
48
|
+
* Each module method is a vi.fn() that can be configured with
|
|
49
|
+
* the helper functions below.
|
|
50
|
+
*/
|
|
51
|
+
export declare function createMockFrappeApp(): MockFrappeApp;
|
|
52
|
+
/**
|
|
53
|
+
* Mock `db.getDocList` to return specific data for a doctype.
|
|
54
|
+
*/
|
|
55
|
+
export declare function mockDocList(mockApp: MockFrappeApp, doctype: string, data: Record<string, any>[]): void;
|
|
56
|
+
/**
|
|
57
|
+
* Mock `db.getDoc` to return specific data for a doctype + name.
|
|
58
|
+
*/
|
|
59
|
+
export declare function mockGetDoc(mockApp: MockFrappeApp, doctype: string, name: string, data: Record<string, any>): void;
|
|
60
|
+
/**
|
|
61
|
+
* Mock `db.createDoc` to return the created document data.
|
|
62
|
+
*/
|
|
63
|
+
export declare function mockCreateDoc(mockApp: MockFrappeApp, doctype: string, returnData: Record<string, any>): void;
|
|
64
|
+
/**
|
|
65
|
+
* Mock `db.updateDoc` to return the updated document data.
|
|
66
|
+
*/
|
|
67
|
+
export declare function mockUpdateDoc(mockApp: MockFrappeApp, doctype: string, name: string, returnData: Record<string, any>): void;
|
|
68
|
+
/**
|
|
69
|
+
* Mock `db.deleteDoc` to succeed for a specific doctype + name.
|
|
70
|
+
*/
|
|
71
|
+
export declare function mockDeleteDoc(mockApp: MockFrappeApp, doctype: string, name: string): void;
|
|
72
|
+
export interface MockKeycloakOptions {
|
|
73
|
+
/** Whether the user is authenticated. Defaults to false. */
|
|
74
|
+
authenticated?: boolean;
|
|
75
|
+
/** Realm roles the user has. Defaults to []. */
|
|
76
|
+
roles?: string[];
|
|
77
|
+
/** JWT token string. Defaults to "mock-jwt-token". */
|
|
78
|
+
token?: string;
|
|
79
|
+
/** User information. */
|
|
80
|
+
user?: {
|
|
81
|
+
email?: string;
|
|
82
|
+
name?: string;
|
|
83
|
+
sub?: string;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export interface MockKeycloakContext {
|
|
87
|
+
authenticated: boolean;
|
|
88
|
+
token: string | undefined;
|
|
89
|
+
tokenParsed: {
|
|
90
|
+
email?: string;
|
|
91
|
+
name?: string;
|
|
92
|
+
preferred_username?: string;
|
|
93
|
+
sub: string;
|
|
94
|
+
realm_access?: {
|
|
95
|
+
roles: string[];
|
|
96
|
+
};
|
|
97
|
+
} | undefined;
|
|
98
|
+
idToken: string | undefined;
|
|
99
|
+
refreshToken: string | undefined;
|
|
100
|
+
realmAccess: {
|
|
101
|
+
roles: string[];
|
|
102
|
+
} | undefined;
|
|
103
|
+
subject: string | undefined;
|
|
104
|
+
email: string | undefined;
|
|
105
|
+
username: string | undefined;
|
|
106
|
+
login: ReturnType<typeof vi.fn>;
|
|
107
|
+
logout: ReturnType<typeof vi.fn>;
|
|
108
|
+
hasRealmRole: (role: string) => boolean;
|
|
109
|
+
hasResourceRole: (role: string, resource?: string) => boolean;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Create a mock Keycloak context for testing components that depend on auth state.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* const mockCtx = createMockKeycloakContext({
|
|
117
|
+
* authenticated: true,
|
|
118
|
+
* roles: ["System Manager", "HR User"],
|
|
119
|
+
* token: "mock-jwt-token",
|
|
120
|
+
* user: { email: "admin@test.com", name: "Admin" },
|
|
121
|
+
* });
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
export declare function createMockKeycloakContext(options?: MockKeycloakOptions): MockKeycloakContext;
|
|
125
|
+
//# sourceMappingURL=mocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mocks.d.ts","sourceRoot":"","sources":["../src/mocks.ts"],"names":[],"mappings":"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"}
|
package/types/setup.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared test setup for multiplatform.one packages.
|
|
3
|
+
*
|
|
4
|
+
* Use this as a vitest setupFile to get all the polyfills, mocks, and
|
|
5
|
+
* environment patches needed for testing Tamagui + React Native Web components.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* // vitest.config.mjs
|
|
10
|
+
* import { createVitestConfig } from "@multiplatform.one/config/vitest";
|
|
11
|
+
* export default createVitestConfig({
|
|
12
|
+
* setupFiles: ["@multiplatform.one/test-utils/setup"],
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
import "@testing-library/jest-dom";
|
|
17
|
+
import "matchmedia-polyfill";
|
|
18
|
+
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAwMH,OAAO,2BAA2B,CAAC;AACnC,OAAO,qBAAqB,CAAC"}
|