twd-js 1.7.1 → 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.
Files changed (59) hide show
  1. package/README.md +26 -4
  2. package/dist/asserts/index.d.ts +2 -0
  3. package/dist/bundled.d.ts +4 -1
  4. package/dist/bundled.es.js +9861 -602
  5. package/dist/cli.js +11 -11
  6. package/dist/commands/mockBridge.d.ts +117 -0
  7. package/dist/commands/url.d.ts +33 -0
  8. package/dist/commands/viewport.d.ts +2 -0
  9. package/dist/commands/visit.d.ts +1 -0
  10. package/dist/constants/version.d.ts +1 -0
  11. package/dist/global.d.ts +20 -0
  12. package/dist/index.cjs.js +33 -33
  13. package/dist/index.d.ts +8 -664
  14. package/dist/index.es.js +1695 -1657
  15. package/dist/initializers/initSidebar.d.ts +29 -0
  16. package/dist/initializers/initTests.d.ts +36 -0
  17. package/dist/mock-sw.js +1 -1
  18. package/dist/plugin/removeMockServiceWorker.d.ts +18 -0
  19. package/dist/plugin/twdHmr.d.ts +45 -0
  20. package/dist/proxies/domMessage.d.ts +1 -0
  21. package/dist/proxies/eventsMessage.d.ts +1 -0
  22. package/dist/proxies/screenDom.d.ts +45 -0
  23. package/dist/proxies/userEvent.d.ts +4 -0
  24. package/dist/runner-ci.d.ts +12 -28
  25. package/dist/runner.d.ts +52 -63
  26. package/dist/twd-types.d.ts +120 -0
  27. package/dist/twd.d.ts +291 -0
  28. package/dist/ui/ClosedSidebar.d.ts +6 -0
  29. package/dist/ui/Icons/BaseIcon.d.ts +7 -0
  30. package/dist/ui/Icons/ChevronDown.d.ts +2 -0
  31. package/dist/ui/Icons/ChevronRight.d.ts +2 -0
  32. package/dist/ui/Icons/Loader.d.ts +2 -0
  33. package/dist/ui/Icons/MockRequestIcon.d.ts +2 -0
  34. package/dist/ui/Icons/Play.d.ts +2 -0
  35. package/dist/ui/LogItem.d.ts +6 -0
  36. package/dist/ui/MockRulesButton.d.ts +1 -0
  37. package/dist/ui/MockedComponent.d.ts +6 -0
  38. package/dist/ui/SearchInput.d.ts +6 -0
  39. package/dist/ui/SkipOnlyName.d.ts +8 -0
  40. package/dist/ui/TWDSidebar.d.ts +20 -0
  41. package/dist/ui/TestList.d.ts +8 -0
  42. package/dist/ui/TestListItem.d.ts +19 -0
  43. package/dist/ui/componentMocks.d.ts +3 -0
  44. package/dist/ui/hooks/useLayout.d.ts +6 -0
  45. package/dist/ui/index.d.ts +1 -0
  46. package/dist/ui/utils/buildTreeFromHandlers.d.ts +16 -0
  47. package/dist/ui/utils/chaiErrorFormat.d.ts +22 -0
  48. package/dist/ui/utils/filterTree.d.ts +2 -0
  49. package/dist/ui/utils/formatLogs.d.ts +30 -0
  50. package/dist/ui/utils/screenReaderMessages.d.ts +9 -0
  51. package/dist/ui/utils/styles.d.ts +7 -0
  52. package/dist/ui/utils/theme.d.ts +74 -0
  53. package/dist/ui.d.ts +2 -10
  54. package/dist/utils/assertionMessage.d.ts +1 -0
  55. package/dist/utils/log.d.ts +1 -0
  56. package/dist/utils/wait.d.ts +3 -0
  57. package/dist/utils/waitFor.d.ts +2 -0
  58. package/dist/vite-plugin.d.ts +2 -67
  59. 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",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.1"&&console.warn(`[TWD] ⚠️ Version mismatch detected:
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 {};
@@ -0,0 +1,4 @@
1
+ import { default as userEventLib } from '@testing-library/user-event';
2
+ type UserEvent = typeof userEventLib;
3
+ export declare const userEvent: UserEvent;
4
+ export {};
@@ -1,28 +1,12 @@
1
- export declare const executeTests: () => Promise<{
2
- handlers: Handler[];
3
- testStatus: TestResult[];
4
- }>;
5
-
6
- declare interface Handler {
7
- id: string;
8
- name: string;
9
- parent?: string;
10
- handler: () => void | Promise<void>;
11
- children?: string[];
12
- type: 'suite' | 'test';
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 declare const afterEach: (fn: HookFn) => void;
2
-
3
- export declare const beforeEach: (fn: HookFn) => void;
4
-
5
- export declare const clearTests: () => void;
6
-
7
- export declare const describe: {
8
- (name: string, handler: () => void): void;
9
- only(name: string, handler: () => void): void;
10
- skip(name: string, handler: () => void): void;
11
- };
12
-
13
- export declare interface Handler {
14
- id: string;
15
- name: string;
16
- parent?: string;
17
- handler: () => void | Promise<void>;
18
- children?: string[];
19
- type: 'suite' | 'test';
20
- status?: 'idle' | 'pass' | 'fail' | 'skip' | 'running';
21
- logs: string[];
22
- depth: number;
23
- only?: boolean;
24
- skip?: boolean;
25
- }
26
-
27
- export declare const handlers: Map<string, Handler>;
28
-
29
- declare type HookFn = () => void | Promise<void>;
30
-
31
- export declare const it: {
32
- (name: string, handler: () => void | Promise<void>): void;
33
- only(name: string, handler: () => void | Promise<void>): void;
34
- skip(name: string, handler?: () => void | Promise<void>): void;
35
- };
36
-
37
- export declare interface RunnerEvents {
38
- onStart: (test: Handler) => void;
39
- onPass: (test: Handler, retryAttempt?: number) => void;
40
- onFail: (test: Handler, error: Error) => void;
41
- onSkip: (test: Handler) => void;
42
- onSuiteStart?: (suite: Handler) => void;
43
- onSuiteEnd?: (suite: Handler) => void;
44
- }
45
-
46
- export declare class TestRunner {
47
- private events;
48
- private retryCount;
49
- constructor(events: RunnerEvents, options?: TestRunnerOptions);
50
- runAll(): Promise<Map<string, Handler>>;
51
- runSingle(id: string): Promise<void>;
52
- runByIds(ids: string[]): Promise<Map<string, Handler>>;
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
+ }