twd-js 1.7.2 → 1.7.3
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 +26 -4
- package/dist/asserts/index.d.ts +2 -0
- package/dist/bundled.d.ts +1 -1
- package/dist/bundled.es.js +8 -4
- package/dist/cli.js +11 -11
- package/dist/commands/mockBridge.d.ts +117 -0
- package/dist/commands/url.d.ts +33 -0
- package/dist/commands/viewport.d.ts +2 -0
- package/dist/commands/visit.d.ts +1 -0
- package/dist/constants/version.d.ts +1 -0
- package/dist/global.d.ts +20 -0
- package/dist/index.cjs.js +26 -26
- package/dist/index.d.ts +8 -664
- package/dist/index.es.js +540 -525
- package/dist/initializers/initSidebar.d.ts +29 -0
- package/dist/initializers/initTests.d.ts +36 -0
- package/dist/mock-sw.js +1 -1
- package/dist/plugin/removeMockServiceWorker.d.ts +18 -0
- package/dist/plugin/twdHmr.d.ts +45 -0
- package/dist/proxies/domMessage.d.ts +1 -0
- package/dist/proxies/eventsMessage.d.ts +1 -0
- package/dist/proxies/screenDom.d.ts +45 -0
- package/dist/proxies/userEvent.d.ts +4 -0
- package/dist/runner-ci.d.ts +12 -28
- package/dist/runner.d.ts +52 -63
- package/dist/twd-types.d.ts +120 -0
- package/dist/twd.d.ts +291 -0
- package/dist/ui/ClosedSidebar.d.ts +6 -0
- package/dist/ui/Icons/BaseIcon.d.ts +7 -0
- package/dist/ui/Icons/ChevronDown.d.ts +2 -0
- package/dist/ui/Icons/ChevronRight.d.ts +2 -0
- package/dist/ui/Icons/Loader.d.ts +2 -0
- package/dist/ui/Icons/MockRequestIcon.d.ts +2 -0
- package/dist/ui/Icons/Play.d.ts +2 -0
- package/dist/ui/LogItem.d.ts +6 -0
- package/dist/ui/MockRulesButton.d.ts +1 -0
- package/dist/ui/MockedComponent.d.ts +6 -0
- package/dist/ui/SearchInput.d.ts +6 -0
- package/dist/ui/SkipOnlyName.d.ts +8 -0
- package/dist/ui/TWDSidebar.d.ts +20 -0
- package/dist/ui/TestList.d.ts +8 -0
- package/dist/ui/TestListItem.d.ts +19 -0
- package/dist/ui/componentMocks.d.ts +3 -0
- package/dist/ui/hooks/useLayout.d.ts +6 -0
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/utils/buildTreeFromHandlers.d.ts +16 -0
- package/dist/ui/utils/chaiErrorFormat.d.ts +22 -0
- package/dist/ui/utils/filterTree.d.ts +2 -0
- package/dist/ui/utils/formatLogs.d.ts +30 -0
- package/dist/ui/utils/screenReaderMessages.d.ts +9 -0
- package/dist/ui/utils/styles.d.ts +7 -0
- package/dist/ui/utils/theme.d.ts +74 -0
- package/dist/ui.d.ts +2 -10
- package/dist/utils/assertionMessage.d.ts +1 -0
- package/dist/utils/log.d.ts +1 -0
- package/dist/utils/wait.d.ts +3 -0
- package/dist/utils/waitFor.d.ts +2 -0
- package/dist/vite-plugin.d.ts +2 -67
- package/package.json +31 -7
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { TWDTheme } from '../ui/utils/theme';
|
|
2
|
+
interface Options {
|
|
3
|
+
Component: React.ReactNode;
|
|
4
|
+
createRoot: (el: HTMLElement) => {
|
|
5
|
+
render: (el: React.ReactNode) => void;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Optional theme customization
|
|
9
|
+
* Users can override default theme values by passing a partial theme object
|
|
10
|
+
*/
|
|
11
|
+
theme?: Partial<TWDTheme>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Initialize the TWD sidebar.
|
|
15
|
+
* @param options - Options for initializing the sidebar.
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { initSidebar } from 'twd-js';
|
|
19
|
+
*
|
|
20
|
+
* // Initialize the sidebar (e.g., in your main app file)
|
|
21
|
+
* initSidebar({
|
|
22
|
+
* Component: <TWDSidebar open={true} position="left" />,
|
|
23
|
+
* createRoot,
|
|
24
|
+
* theme: { primary: '#ff0000', background: '#ffffff' }
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare const initSidebar: (options: Options) => void;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { TWDTheme } from '../ui/utils/theme';
|
|
2
|
+
/**
|
|
3
|
+
* A record of test module paths to their loader functions.
|
|
4
|
+
* Each function returns a promise that resolves when the module is loaded.
|
|
5
|
+
* This is typically used with Vite's `import.meta.glob` to dynamically import test modules.
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const testModules = {
|
|
9
|
+
* './test1.twd.test.ts': () => import('./test1.twd.test.ts'),
|
|
10
|
+
* './test2.twd.test.ts': () => import('./test2.twd.test.ts'),
|
|
11
|
+
* };
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
type TestModule = Record<string, () => Promise<unknown>>;
|
|
15
|
+
/**
|
|
16
|
+
* Initialize Vite test loading.
|
|
17
|
+
* @param testModules - The test modules to load.
|
|
18
|
+
* @param component - The React component to render the sidebar.
|
|
19
|
+
* @param createRoot - Function to create a React root.
|
|
20
|
+
* @param theme - Optional theme customization
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* if (import.meta.env.DEV) {
|
|
24
|
+
* const testModules = import.meta.glob("./example.twd.test.ts");
|
|
25
|
+
* const { initTests, TWDSidebar } = await import('twd-js');
|
|
26
|
+
* await initTests(testModules, <TWDSidebar open={true} position="left" />, createRoot, {
|
|
27
|
+
* primary: '#ff0000',
|
|
28
|
+
* background: '#ffffff'
|
|
29
|
+
* });
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare const initTests: (testModules: TestModule, Component: React.ReactNode, createRoot: (el: HTMLElement) => {
|
|
34
|
+
render: (el: React.ReactNode) => void;
|
|
35
|
+
}, theme?: Partial<TWDTheme>) => Promise<void>;
|
|
36
|
+
export {};
|
package/dist/mock-sw.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(){var d=t=>{try{return new RegExp(t),!0}catch{return!1}},f=new Set(["js","mjs","cjs","ts","tsx","jsx","mts","cts","css","scss","sass","less","styl","html","htm","xml","xhtml","vue","svelte","json","yaml","yml","toml","csv","txt","md","mdx","pdf","doc","docx","png","jpg","jpeg","gif","svg","webp","ico","bmp","avif","woff","woff2","ttf","eot","otf","mp3","mp4","webm","ogg","wav","zip","tar","gz","rar","map"]),c=t=>{const s=t.split("?")[0].match(/\.([a-zA-Z0-9]+)$/);return s?f.has(s[1].toLowerCase()):!1},h=(t,s)=>{const i=t.indexOf(s);if(i===-1)return!1;const e=i+s.length,a=t[e];if(a===void 0)return!0;const n=t.indexOf("?");return n!==-1&&e>n?!0:"?#&".includes(a)};function m(t,s,i){return i.find(e=>{const a=e.method.toLowerCase()===t.toLowerCase();if(e.urlRegex&&d(e.url)){const l=new RegExp(e.url);return a&&l.test(s)}if(c(e.url))return a&&s.includes(e.url);const n=e.url===s||h(s,e.url);return a&&n&&!c(s)})}function p(t,s,i,e){t.forEach(a=>a.postMessage({type:"EXECUTED",alias:s.alias,request:i,hitCount:e}))}var y=(t,s,i)=>{const e=![204,205,304].includes(s),a=e?JSON.stringify(t):null;return new Response(a,{status:s,headers:e?i||{"Content-Type":"application/json"}:i||{}})},u="1.7.
|
|
1
|
+
(function(){var d=t=>{try{return new RegExp(t),!0}catch{return!1}},f=new Set(["js","mjs","cjs","ts","tsx","jsx","mts","cts","css","scss","sass","less","styl","html","htm","xml","xhtml","vue","svelte","json","yaml","yml","toml","csv","txt","md","mdx","pdf","doc","docx","png","jpg","jpeg","gif","svg","webp","ico","bmp","avif","woff","woff2","ttf","eot","otf","mp3","mp4","webm","ogg","wav","zip","tar","gz","rar","map"]),c=t=>{const s=t.split("?")[0].match(/\.([a-zA-Z0-9]+)$/);return s?f.has(s[1].toLowerCase()):!1},h=(t,s)=>{const i=t.indexOf(s);if(i===-1)return!1;const e=i+s.length,a=t[e];if(a===void 0)return!0;const n=t.indexOf("?");return n!==-1&&e>n?!0:"?#&".includes(a)};function m(t,s,i){return i.find(e=>{const a=e.method.toLowerCase()===t.toLowerCase();if(e.urlRegex&&d(e.url)){const l=new RegExp(e.url);return a&&l.test(s)}if(c(e.url))return a&&s.includes(e.url);const n=e.url===s||h(s,e.url);return a&&n&&!c(s)})}function p(t,s,i,e){t.forEach(a=>a.postMessage({type:"EXECUTED",alias:s.alias,request:i,hitCount:e}))}var y=(t,s,i)=>{const e=![204,205,304].includes(s),a=e?JSON.stringify(t):null;return new Response(a,{status:s,headers:e?i||{"Content-Type":"application/json"}:i||{}})},u="1.7.3",r=[],o={},g=async t=>{const{method:s}=t.request,i=t.request.url,e=m(s,i,r);e&&(console.log("[TWD] Mock hit:",e.alias,s,i),t.respondWith((async()=>{let a=null;const n=t.request.headers.get("content-type")||"application/json";if(n.includes("application/json"))try{a=await t.request.clone().json()}catch{}else if(n.includes("form"))try{const l=await t.request.clone().formData();a={},l.forEach((x,E)=>{a[E]=x})}catch{}else if(n.includes("text"))try{a=await t.request.clone().text()}catch{}else if(n.includes("octet-stream"))try{a=await t.request.clone().arrayBuffer()}catch{}else if(n.includes("image"))try{a=await t.request.clone().blob()}catch{}else try{a=await t.request.clone().text()}catch{}return o[e.alias]||(o[e.alias]=0),o[e.alias]++,p(await self.clients.matchAll(),e,a,o[e.alias]),e.delay&&e.delay>0&&await new Promise(l=>setTimeout(l,e.delay)),y(e.response,e.status??200,e.responseHeaders)})()))},w=t=>{t!=="1.7.3"&&console.warn(`[TWD] ⚠️ Version mismatch detected:
|
|
2
2
|
Client version: ${t}
|
|
3
3
|
Service Worker version: ${u}
|
|
4
4
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
/**
|
|
3
|
+
* Vite plugin to remove the mock service worker file from the build output.
|
|
4
|
+
* This is useful for production builds where you don't want the mock service worker to be included.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { removeMockServiceWorker } from 'twd-js';
|
|
9
|
+
*
|
|
10
|
+
* export default defineConfig({
|
|
11
|
+
* plugins: [
|
|
12
|
+
* // ... other plugins
|
|
13
|
+
* removeMockServiceWorker()
|
|
14
|
+
* ]
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function removeMockServiceWorker(): Plugin;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
/**
|
|
3
|
+
* Options for the TWD HMR plugin.
|
|
4
|
+
*/
|
|
5
|
+
export interface TwdHmrOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Pattern to match test files. Defaults to `.twd.test.ts`.
|
|
8
|
+
* Can be a string (checked with `endsWith`) or a function that returns a boolean.
|
|
9
|
+
* @default ".twd.test.ts"
|
|
10
|
+
*/
|
|
11
|
+
testFilePattern?: string | ((file: string) => boolean);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Vite plugin to handle HMR for TWD test files.
|
|
15
|
+
* When a TWD test file is updated, it forces a full page reload to prevent
|
|
16
|
+
* duplicate test entries that occur when HMR reloads test modules.
|
|
17
|
+
*
|
|
18
|
+
* This plugin only runs in development mode (serve) and does not affect Vitest test runs.
|
|
19
|
+
*
|
|
20
|
+
* @param options - Configuration options for the plugin
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { twdHmr } from 'twd-js/vite-plugin';
|
|
24
|
+
*
|
|
25
|
+
* export default defineConfig({
|
|
26
|
+
* plugins: [
|
|
27
|
+
* // ... other plugins
|
|
28
|
+
* twdHmr() // Uses default pattern: .twd.test.ts
|
|
29
|
+
* ]
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* // Custom pattern
|
|
35
|
+
* twdHmr({ testFilePattern: '.twd.test.tsx' })
|
|
36
|
+
* ```
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* // Custom function
|
|
40
|
+
* twdHmr({
|
|
41
|
+
* testFilePattern: (file) => file.includes('.twd.test.')
|
|
42
|
+
* })
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function twdHmr(options?: TwdHmrOptions): Plugin;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function domMessage(prefix: string, prop: PropertyKey, args: any[]): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function eventsMessage(prefix: string, prop: PropertyKey, args: any[]): string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { screen, configure } from '@testing-library/dom';
|
|
2
|
+
type ScreenDom = typeof screen;
|
|
3
|
+
/**
|
|
4
|
+
* Set the app root selector used by screenDom queries. Package-internal —
|
|
5
|
+
* wired through `initTWD({ rootSelector })`. Not re-exported from `src/index.ts`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const setRootSelector: (selector: string) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Reset screenDom module state. Only use in tests.
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
export declare const resetScreenDomState: () => void;
|
|
13
|
+
/**
|
|
14
|
+
* screenDom - Scoped queries that exclude the TWD sidebar
|
|
15
|
+
*
|
|
16
|
+
* Searches only within the main app container (typically #root).
|
|
17
|
+
* Use this for most queries to avoid matching elements in the sidebar.
|
|
18
|
+
*
|
|
19
|
+
* Note: This will NOT find portal-rendered elements (modals, dialogs) that are
|
|
20
|
+
* rendered outside the root container. For portals, use `screenDomGlobal` instead.
|
|
21
|
+
*/
|
|
22
|
+
export declare const screenDom: ScreenDom;
|
|
23
|
+
/**
|
|
24
|
+
* screenDomGlobal - Global queries that search the entire document.body
|
|
25
|
+
*
|
|
26
|
+
* Searches all elements in document.body, including portal-rendered elements
|
|
27
|
+
* (modals, dialogs, tooltips, etc.).
|
|
28
|
+
*
|
|
29
|
+
* ⚠️ WARNING: This may also match elements inside the TWD sidebar if your selectors
|
|
30
|
+
* are not specific enough. Use more specific queries (e.g., getByRole with name)
|
|
31
|
+
* to avoid matching sidebar elements.
|
|
32
|
+
*
|
|
33
|
+
* Use this when:
|
|
34
|
+
* - Querying portal-rendered elements (modals, dialogs)
|
|
35
|
+
* - You need to search outside the root container
|
|
36
|
+
*
|
|
37
|
+
* Example:
|
|
38
|
+
* ```ts
|
|
39
|
+
* // For a modal rendered via portal
|
|
40
|
+
* const modal = screenDomGlobal.getByRole('dialog', { name: 'Confirm' });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare const screenDomGlobal: ScreenDom;
|
|
44
|
+
export declare const configureScreenDom: typeof configure;
|
|
45
|
+
export {};
|
package/dist/runner-ci.d.ts
CHANGED
|
@@ -1,28 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
status?: 'idle' | 'pass' | 'fail' | 'skip' | 'running';
|
|
14
|
-
logs: string[];
|
|
15
|
-
depth: number;
|
|
16
|
-
only?: boolean;
|
|
17
|
-
skip?: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export declare const reportResults: (handlers: Handler[], testResults: TestResult[]) => void;
|
|
21
|
-
|
|
22
|
-
declare interface TestResult {
|
|
23
|
-
id: string;
|
|
24
|
-
status: 'pass' | 'fail' | 'skip';
|
|
25
|
-
error?: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export { }
|
|
1
|
+
import { Handler } from './runner';
|
|
2
|
+
interface TestResult {
|
|
3
|
+
id: string;
|
|
4
|
+
status: 'pass' | 'fail' | 'skip';
|
|
5
|
+
error?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const reportResults: (handlers: Handler[], testResults: TestResult[]) => void;
|
|
8
|
+
export declare const executeTests: () => Promise<{
|
|
9
|
+
handlers: Handler[];
|
|
10
|
+
testStatus: TestResult[];
|
|
11
|
+
}>;
|
|
12
|
+
export {};
|
package/dist/runner.d.ts
CHANGED
|
@@ -1,63 +1,52 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
handler: () => void
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
only
|
|
24
|
-
skip?:
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export declare const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
export
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
private
|
|
48
|
-
private
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
private runSuiteByIds;
|
|
54
|
-
private hasDescendantInSet;
|
|
55
|
-
private runSuite;
|
|
56
|
-
private runTest;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export declare interface TestRunnerOptions {
|
|
60
|
-
retryCount?: number;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export { }
|
|
1
|
+
export interface Handler {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
parent?: string;
|
|
5
|
+
handler: () => void | Promise<void>;
|
|
6
|
+
children?: string[];
|
|
7
|
+
type: 'suite' | 'test';
|
|
8
|
+
status?: 'idle' | 'pass' | 'fail' | 'skip' | 'running';
|
|
9
|
+
logs: string[];
|
|
10
|
+
depth: number;
|
|
11
|
+
only?: boolean;
|
|
12
|
+
skip?: boolean;
|
|
13
|
+
}
|
|
14
|
+
type HookFn = () => void | Promise<void>;
|
|
15
|
+
export declare const handlers: Map<string, Handler>;
|
|
16
|
+
export declare const describe: {
|
|
17
|
+
(name: string, handler: () => void): void;
|
|
18
|
+
only(name: string, handler: () => void): void;
|
|
19
|
+
skip(name: string, handler: () => void): void;
|
|
20
|
+
};
|
|
21
|
+
export declare const it: {
|
|
22
|
+
(name: string, handler: () => void | Promise<void>): void;
|
|
23
|
+
only(name: string, handler: () => void | Promise<void>): void;
|
|
24
|
+
skip(name: string, handler?: () => void | Promise<void>): void;
|
|
25
|
+
};
|
|
26
|
+
export declare const beforeEach: (fn: HookFn) => void;
|
|
27
|
+
export declare const afterEach: (fn: HookFn) => void;
|
|
28
|
+
export declare const clearTests: () => void;
|
|
29
|
+
export interface RunnerEvents {
|
|
30
|
+
onStart: (test: Handler) => void;
|
|
31
|
+
onPass: (test: Handler, retryAttempt?: number) => void;
|
|
32
|
+
onFail: (test: Handler, error: Error) => void;
|
|
33
|
+
onSkip: (test: Handler) => void;
|
|
34
|
+
onSuiteStart?: (suite: Handler) => void;
|
|
35
|
+
onSuiteEnd?: (suite: Handler) => void;
|
|
36
|
+
}
|
|
37
|
+
export interface TestRunnerOptions {
|
|
38
|
+
retryCount?: number;
|
|
39
|
+
}
|
|
40
|
+
export declare class TestRunner {
|
|
41
|
+
private events;
|
|
42
|
+
private retryCount;
|
|
43
|
+
constructor(events: RunnerEvents, options?: TestRunnerOptions);
|
|
44
|
+
runAll(): Promise<Map<string, Handler>>;
|
|
45
|
+
runSingle(id: string): Promise<void>;
|
|
46
|
+
runByIds(ids: string[]): Promise<Map<string, Handler>>;
|
|
47
|
+
private runSuiteByIds;
|
|
48
|
+
private hasDescendantInSet;
|
|
49
|
+
private runSuite;
|
|
50
|
+
private runTest;
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types and interfaces for the TWD testing library.
|
|
3
|
+
*
|
|
4
|
+
* @module twd-types
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* All supported assertion names for the `should` function.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* api.should("have.text", "Hello");
|
|
11
|
+
* api.should("be.empty");
|
|
12
|
+
*/
|
|
13
|
+
export type AssertionName = 'have.text' | 'contain.text' | 'be.empty' | 'have.attr' | 'have.value' | 'be.disabled' | 'be.enabled' | 'be.checked' | 'be.selected' | 'be.focused' | 'be.visible' | 'be.hidden' | 'have.class';
|
|
14
|
+
/**
|
|
15
|
+
* Negatable assertion names (e.g., 'not.have.text').
|
|
16
|
+
*/
|
|
17
|
+
export type Negatable<T extends string> = T | `not.${T}`;
|
|
18
|
+
/**
|
|
19
|
+
* All assertion names, including negated ones.
|
|
20
|
+
*/
|
|
21
|
+
export type AnyAssertion = Negatable<AssertionName>;
|
|
22
|
+
/**
|
|
23
|
+
* Argument types for each assertion.
|
|
24
|
+
*/
|
|
25
|
+
export type AssertionArgs = {
|
|
26
|
+
'have.text': [expected: string];
|
|
27
|
+
'contain.text': [expected: string];
|
|
28
|
+
'be.empty': [];
|
|
29
|
+
'have.attr': [attr: string, value: string];
|
|
30
|
+
'have.value': [value: string];
|
|
31
|
+
'be.disabled': [];
|
|
32
|
+
'be.enabled': [];
|
|
33
|
+
'be.checked': [];
|
|
34
|
+
'be.selected': [];
|
|
35
|
+
'be.focused': [];
|
|
36
|
+
'be.visible': [];
|
|
37
|
+
'be.hidden': [];
|
|
38
|
+
'have.class': [className: string];
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Maps assertion name to its argument tuple.
|
|
42
|
+
*/
|
|
43
|
+
export type ArgsFor<A extends AnyAssertion> = A extends `not.${infer Base extends AssertionName}` ? AssertionArgs[Base] : A extends AssertionName ? AssertionArgs[A] : never;
|
|
44
|
+
/**
|
|
45
|
+
* Overloads for the `should` function, for best IntelliSense.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* twd.should("have.text", "Hello");
|
|
49
|
+
* twd.should("be.empty");
|
|
50
|
+
* twd.should("have.class", "active");
|
|
51
|
+
*/
|
|
52
|
+
export type ShouldFn = {
|
|
53
|
+
(name: 'have.text', expected: string): TWDElemAPI;
|
|
54
|
+
(name: 'not.have.text', expected: string): TWDElemAPI;
|
|
55
|
+
(name: 'contain.text', expected: string): TWDElemAPI;
|
|
56
|
+
(name: 'not.contain.text', expected: string): TWDElemAPI;
|
|
57
|
+
(name: 'be.empty'): TWDElemAPI;
|
|
58
|
+
(name: 'not.be.empty'): TWDElemAPI;
|
|
59
|
+
(name: 'have.attr', attr: string, value: string): TWDElemAPI;
|
|
60
|
+
(name: 'not.have.attr', attr: string, value: string): TWDElemAPI;
|
|
61
|
+
(name: 'have.value', value: string): TWDElemAPI;
|
|
62
|
+
(name: 'not.have.value', value: string): TWDElemAPI;
|
|
63
|
+
(name: 'be.disabled'): TWDElemAPI;
|
|
64
|
+
(name: 'not.be.disabled'): TWDElemAPI;
|
|
65
|
+
(name: 'be.enabled'): TWDElemAPI;
|
|
66
|
+
(name: 'not.be.enabled'): TWDElemAPI;
|
|
67
|
+
(name: 'be.checked'): TWDElemAPI;
|
|
68
|
+
(name: 'not.be.checked'): TWDElemAPI;
|
|
69
|
+
(name: 'be.selected'): TWDElemAPI;
|
|
70
|
+
(name: 'not.be.selected'): TWDElemAPI;
|
|
71
|
+
(name: 'be.focused'): TWDElemAPI;
|
|
72
|
+
(name: 'not.be.focused'): TWDElemAPI;
|
|
73
|
+
(name: 'be.visible'): TWDElemAPI;
|
|
74
|
+
(name: 'not.be.visible'): TWDElemAPI;
|
|
75
|
+
(name: 'be.hidden'): TWDElemAPI;
|
|
76
|
+
(name: 'not.be.hidden'): TWDElemAPI;
|
|
77
|
+
(name: 'have.class', className: string): TWDElemAPI;
|
|
78
|
+
(name: 'not.have.class', className: string): TWDElemAPI;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* The main API returned by `twd.get()`.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* const btn = await twd.get("button");
|
|
86
|
+
* btn.should("have.text", "Clicked").click();
|
|
87
|
+
*
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
*/
|
|
91
|
+
export interface TWDElemAPI {
|
|
92
|
+
/** The underlying DOM element. */
|
|
93
|
+
el: Element;
|
|
94
|
+
/**
|
|
95
|
+
* Asserts something about the element.
|
|
96
|
+
* @param name The name of the assertion.
|
|
97
|
+
* @param args Arguments for the assertion.
|
|
98
|
+
* @returns The same API for chaining.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* const btn = await twd.get("button");
|
|
103
|
+
* btn.should("have.text", "Click me").should("not.be.disabled");
|
|
104
|
+
*
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
*/
|
|
108
|
+
should: ShouldFn;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Options for `twd.waitFor()`.
|
|
112
|
+
*/
|
|
113
|
+
export interface WaitForOptions {
|
|
114
|
+
/** Max time to wait in ms. Default: 2000 */
|
|
115
|
+
timeout?: number;
|
|
116
|
+
/** Poll interval in ms. Default: 50 */
|
|
117
|
+
interval?: number;
|
|
118
|
+
/** Context message included in timeout errors */
|
|
119
|
+
message?: string;
|
|
120
|
+
}
|