@rstest/browser 0.11.6 → 0.11.8

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 (88) hide show
  1. package/dist/browser-container/container-static/css/index.43daaf6c93.css +1 -0
  2. package/dist/browser-container/container-static/js/260.3739fe815c.js +194 -0
  3. package/dist/browser-container/container-static/js/index.c0f87bfb3e.js +1 -0
  4. package/dist/browser-container/index.html +1 -1
  5. package/dist/browserRsbuild.d.ts +24 -4
  6. package/dist/browserV8Coverage.d.ts +15 -0
  7. package/dist/client/240~1.js +150 -0
  8. package/dist/{augmentExpect.d.ts → client/client/augmentExpect.d.ts} +1 -1
  9. package/dist/client/{browserRpc.d.ts → client/browserRpc.d.ts} +1 -1
  10. package/dist/client/{dispatchTransport.d.ts → client/dispatchTransport.d.ts} +8 -4
  11. package/dist/client/client/index.d.ts +2 -0
  12. package/dist/client/client/runIdentity.d.ts +12 -0
  13. package/dist/client/client/runner.d.ts +4 -0
  14. package/dist/client/client/snapshot.d.ts +27 -0
  15. package/dist/client/client/sourceMapSupport.d.ts +36 -0
  16. package/dist/{browser.js → client/index.js} +3 -102
  17. package/dist/client/protocol.d.ts +225 -0
  18. package/dist/client/rpcProtocol.d.ts +138 -0
  19. package/dist/client/runner.js +675 -0
  20. package/dist/client/sourceMap/sourceMapLoader.d.ts +25 -0
  21. package/dist/containerRpc.d.ts +27 -19
  22. package/dist/headedRunRegistry.d.ts +51 -0
  23. package/dist/headedScheduler.d.ts +10 -10
  24. package/dist/headlessScheduler.d.ts +5 -4
  25. package/dist/headlessTransport.d.ts +4 -2
  26. package/dist/hostPayloads.d.ts +1 -7
  27. package/dist/index.js +840 -330
  28. package/dist/protocol.d.ts +48 -8
  29. package/dist/providers/index.d.ts +21 -0
  30. package/dist/providers/playwright/v8Coverage.d.ts +2 -0
  31. package/dist/rpcProtocol.d.ts +1 -2
  32. package/dist/schedulerSeam.d.ts +5 -0
  33. package/dist/sourceMap/sourceMapLoader.d.ts +12 -1
  34. package/dist/watchRerunPlanner.d.ts +20 -9
  35. package/dist/watchSignals.d.ts +8 -1
  36. package/package.json +11 -11
  37. package/dist/33.js +0 -7
  38. package/dist/browser-container/container-static/css/index.0521ff95b1.css +0 -1
  39. package/dist/browser-container/container-static/js/683.4f821ce8f1.js +0 -194
  40. package/dist/browser-container/container-static/js/index.568aa7cb35.js +0 -1
  41. package/dist/browser.d.ts +0 -2
  42. package/src/augmentExpect.ts +0 -62
  43. package/src/browser.ts +0 -3
  44. package/src/browserExecutor.ts +0 -222
  45. package/src/browserRpcRegistry.ts +0 -57
  46. package/src/browserRsbuild.ts +0 -1927
  47. package/src/client/api.ts +0 -213
  48. package/src/client/browserRpc.ts +0 -86
  49. package/src/client/dispatchTransport.ts +0 -240
  50. package/src/client/entry.ts +0 -807
  51. package/src/client/locator.ts +0 -448
  52. package/src/client/snapshot.ts +0 -113
  53. package/src/client/sourceMapSupport.ts +0 -159
  54. package/src/concurrency.ts +0 -65
  55. package/src/configValidation.ts +0 -263
  56. package/src/containerRpc.ts +0 -206
  57. package/src/dispatchCapabilities.ts +0 -177
  58. package/src/dispatchRouter.ts +0 -82
  59. package/src/env.d.ts +0 -54
  60. package/src/headedScheduler.ts +0 -664
  61. package/src/headedSerialTaskQueue.ts +0 -23
  62. package/src/headlessScheduler.ts +0 -566
  63. package/src/headlessTransport.ts +0 -28
  64. package/src/hostController.ts +0 -1365
  65. package/src/hostPayloads.ts +0 -62
  66. package/src/index.ts +0 -51
  67. package/src/manifest.d.ts +0 -41
  68. package/src/protocol.ts +0 -225
  69. package/src/providers/index.ts +0 -126
  70. package/src/providers/playwright/compileLocator.ts +0 -130
  71. package/src/providers/playwright/dispatchBrowserRpc.ts +0 -372
  72. package/src/providers/playwright/expectUtils.ts +0 -57
  73. package/src/providers/playwright/implementation.ts +0 -35
  74. package/src/providers/playwright/index.ts +0 -1
  75. package/src/providers/playwright/runtime.ts +0 -159
  76. package/src/providers/playwright/textMatcher.ts +0 -10
  77. package/src/rpcProtocol.ts +0 -218
  78. package/src/runSession.ts +0 -110
  79. package/src/schedulerSeam.ts +0 -49
  80. package/src/sessionRegistry.ts +0 -89
  81. package/src/sourceMap/sourceMapLoader.ts +0 -96
  82. package/src/viewportPresets.ts +0 -69
  83. package/src/watchRerunPlanner.ts +0 -88
  84. package/src/watchRuntime.ts +0 -83
  85. package/src/watchSignals.ts +0 -93
  86. /package/dist/{rslib-runtime.js → 612~0.js} +0 -0
  87. /package/dist/client/{api.d.ts → client/api.d.ts} +0 -0
  88. /package/dist/client/{locator.d.ts → client/locator.d.ts} +0 -0
@@ -1,218 +0,0 @@
1
- export type BrowserLocatorText =
2
- | { type: 'string'; value: string }
3
- | { type: 'regexp'; source: string; flags?: string };
4
-
5
- export type BrowserLocatorStep =
6
- | {
7
- type: 'getByRole';
8
- role: string;
9
- options?: {
10
- name?: BrowserLocatorText;
11
- exact?: boolean;
12
- checked?: boolean;
13
- disabled?: boolean;
14
- expanded?: boolean;
15
- selected?: boolean;
16
- pressed?: boolean;
17
- includeHidden?: boolean;
18
- level?: number;
19
- };
20
- }
21
- | {
22
- type: 'locator';
23
- selector: string;
24
- }
25
- | {
26
- type: 'getByText';
27
- text: BrowserLocatorText;
28
- options?: { exact?: boolean };
29
- }
30
- | {
31
- type: 'getByLabel';
32
- text: BrowserLocatorText;
33
- options?: { exact?: boolean };
34
- }
35
- | {
36
- type: 'getByPlaceholder';
37
- text: BrowserLocatorText;
38
- options?: { exact?: boolean };
39
- }
40
- | {
41
- type: 'getByAltText';
42
- text: BrowserLocatorText;
43
- options?: { exact?: boolean };
44
- }
45
- | {
46
- type: 'getByTitle';
47
- text: BrowserLocatorText;
48
- options?: { exact?: boolean };
49
- }
50
- | {
51
- type: 'getByTestId';
52
- text: BrowserLocatorText;
53
- }
54
- | {
55
- type: 'filter';
56
- options: {
57
- hasText?: BrowserLocatorText;
58
- hasNotText?: BrowserLocatorText;
59
- has?: BrowserLocatorIR;
60
- hasNot?: BrowserLocatorIR;
61
- };
62
- }
63
- | { type: 'and'; locator: BrowserLocatorIR }
64
- | { type: 'or'; locator: BrowserLocatorIR }
65
- | { type: 'nth'; index: number }
66
- | { type: 'first' }
67
- | { type: 'last' };
68
-
69
- export type BrowserLocatorIR = {
70
- steps: BrowserLocatorStep[];
71
- };
72
-
73
- export type BrowserRpcRequest = {
74
- id: string;
75
- /** Absolute test file path for locating runner iframe */
76
- testPath: string;
77
- /** Run identifier generated by container for stale-request protection. */
78
- runId: string;
79
- kind: 'locator' | 'expect' | 'config';
80
- locator: BrowserLocatorIR;
81
- method: string;
82
- args: unknown[];
83
- /**
84
- * Negation for expect matchers (equivalent to Playwright expect(...).not).
85
- * Only meaningful for kind === 'expect'.
86
- */
87
- isNot?: boolean;
88
- /** Optional timeout override (ms). Falls back to browser rpcTimeout. */
89
- timeout?: number;
90
- };
91
-
92
- const isRecord = (value: unknown): value is Record<string, unknown> => {
93
- return typeof value === 'object' && value !== null;
94
- };
95
-
96
- const readString = (
97
- value: Record<string, unknown>,
98
- key: string,
99
- label: string,
100
- ): string => {
101
- const result = value[key];
102
- if (typeof result !== 'string') {
103
- throw new Error(`Invalid browser RPC request: ${label} must be a string`);
104
- }
105
- return result;
106
- };
107
-
108
- const readUnknownArray = (
109
- value: Record<string, unknown>,
110
- key: string,
111
- label: string,
112
- ): unknown[] => {
113
- const result = value[key];
114
- if (!Array.isArray(result)) {
115
- throw new Error(`Invalid browser RPC request: ${label} must be an array`);
116
- }
117
- return result;
118
- };
119
-
120
- const parseBrowserLocatorIR = (
121
- value: unknown,
122
- label: string,
123
- ): BrowserLocatorIR => {
124
- if (!isRecord(value)) {
125
- throw new Error(`Invalid browser RPC request: ${label} must be an object`);
126
- }
127
-
128
- const steps = value.steps;
129
- if (!Array.isArray(steps)) {
130
- throw new Error(
131
- `Invalid browser RPC request: ${label}.steps must be an array`,
132
- );
133
- }
134
-
135
- return value as BrowserLocatorIR;
136
- };
137
-
138
- export const validateBrowserRpcRequest = (
139
- payload: unknown,
140
- ): BrowserRpcRequest => {
141
- if (!isRecord(payload)) {
142
- throw new Error('Invalid browser RPC request: payload must be an object');
143
- }
144
-
145
- const kind = readString(payload, 'kind', 'kind');
146
- if (kind !== 'locator' && kind !== 'expect' && kind !== 'config') {
147
- throw new Error(
148
- `Invalid browser RPC request: unsupported kind ${JSON.stringify(kind)}`,
149
- );
150
- }
151
-
152
- const request: BrowserRpcRequest = {
153
- id: readString(payload, 'id', 'id'),
154
- testPath: readString(payload, 'testPath', 'testPath'),
155
- runId: readString(payload, 'runId', 'runId'),
156
- kind,
157
- locator: parseBrowserLocatorIR(payload.locator, 'locator'),
158
- method: readString(payload, 'method', 'method'),
159
- args: readUnknownArray(payload, 'args', 'args'),
160
- };
161
-
162
- const isNot = payload.isNot;
163
- if (isNot !== undefined) {
164
- if (typeof isNot !== 'boolean') {
165
- throw new Error('Invalid browser RPC request: isNot must be a boolean');
166
- }
167
- request.isNot = isNot;
168
- }
169
-
170
- const timeout = payload.timeout;
171
- if (timeout !== undefined) {
172
- if (typeof timeout !== 'number') {
173
- throw new Error('Invalid browser RPC request: timeout must be a number');
174
- }
175
- request.timeout = timeout;
176
- }
177
-
178
- return request;
179
- };
180
-
181
- /**
182
- * Single source of truth for snapshot RPC methods and their argument shapes.
183
- * The request union, the client sender, both host-side mappers, and every
184
- * exhaustiveness check derive from this map — adding or renaming a method here
185
- * forces a compile error at every site that has not been updated.
186
- */
187
- export type SnapshotRpcMethodArgs = {
188
- resolveSnapshotPath: { testPath: string };
189
- readSnapshotFile: { filepath: string };
190
- saveSnapshotFile: { filepath: string; content: string };
191
- removeSnapshotFile: { filepath: string };
192
- };
193
-
194
- export type SnapshotRpcMethod = keyof SnapshotRpcMethodArgs;
195
-
196
- /**
197
- * Snapshot RPC request from runner iframe.
198
- * The container will forward these to the host via WebSocket RPC.
199
- */
200
- export type SnapshotRpcRequest = {
201
- [M in SnapshotRpcMethod]: {
202
- id: string;
203
- method: M;
204
- args: SnapshotRpcMethodArgs[M];
205
- };
206
- }[SnapshotRpcMethod];
207
-
208
- /**
209
- * Client-side snapshot RPC call (request without the transport `id`).
210
- * Distributive over {@link SnapshotRpcMethod} so `method` and `args` stay paired
211
- * at the call site — a mismatched pair fails to compile.
212
- */
213
- export type SnapshotRpcCall = {
214
- [M in SnapshotRpcMethod]: {
215
- method: M;
216
- args: SnapshotRpcMethodArgs[M];
217
- };
218
- }[SnapshotRpcMethod];
package/src/runSession.ts DELETED
@@ -1,110 +0,0 @@
1
- /**
2
- * Run generation/session lifecycle contract shared by browser scheduling paths.
3
- */
4
- export type RunSession = {
5
- token: number;
6
- cancelled: boolean;
7
- cancelSignal: Promise<void>;
8
- signalCancel: () => void;
9
- done?: Promise<void>;
10
- };
11
-
12
- const createCancelSignal = (): {
13
- signal: Promise<void>;
14
- resolve: () => void;
15
- } => {
16
- let settled = false;
17
- let resolveSignal: () => void = () => {};
18
-
19
- const signal = new Promise<void>((resolve) => {
20
- resolveSignal = () => {
21
- if (!settled) {
22
- settled = true;
23
- resolve();
24
- }
25
- };
26
- });
27
-
28
- return {
29
- signal,
30
- resolve: resolveSignal,
31
- };
32
- };
33
-
34
- export const createRunSession = (token: number): RunSession => {
35
- const { signal, resolve } = createCancelSignal();
36
- return {
37
- token,
38
- cancelled: false,
39
- cancelSignal: signal,
40
- signalCancel: resolve,
41
- };
42
- };
43
-
44
- type CancelOptions<T extends RunSession> = {
45
- waitForDone?: boolean;
46
- onCancel?: (session: T) => Promise<void> | void;
47
- };
48
-
49
- /**
50
- * Canonical run-token lifecycle manager.
51
- * Centralizes token increment, invalidation, and cancellation semantics.
52
- */
53
- export class RunSessionLifecycle<T extends RunSession> {
54
- private currentToken = 0;
55
- private active: T | null = null;
56
-
57
- get activeSession(): T | null {
58
- return this.active;
59
- }
60
-
61
- get activeToken(): number {
62
- return this.currentToken;
63
- }
64
-
65
- createSession(factory: (token: number) => T): T {
66
- const session = factory(++this.currentToken);
67
- this.active = session;
68
- return session;
69
- }
70
-
71
- isTokenActive(token: number): boolean {
72
- return token === this.currentToken;
73
- }
74
-
75
- isTokenStale(token: number): boolean {
76
- return !this.isTokenActive(token);
77
- }
78
-
79
- invalidateActiveToken(): number {
80
- this.currentToken += 1;
81
- return this.currentToken;
82
- }
83
-
84
- clearIfActive(session: T): void {
85
- if (this.active === session) {
86
- this.active = null;
87
- }
88
- }
89
-
90
- async cancel(session: T, options?: CancelOptions<T>): Promise<void> {
91
- const waitForDone = options?.waitForDone ?? true;
92
-
93
- if (!session.cancelled) {
94
- session.cancelled = true;
95
- session.signalCancel();
96
- await options?.onCancel?.(session);
97
- }
98
-
99
- if (waitForDone) {
100
- await session.done?.catch(() => {});
101
- }
102
- }
103
-
104
- async cancelActive(options?: CancelOptions<T>): Promise<void> {
105
- if (!this.active) {
106
- return;
107
- }
108
- await this.cancel(this.active, options);
109
- }
110
- }
@@ -1,49 +0,0 @@
1
- import type { ExecutorCycleOutcome } from '@rstest/core/internal/browser';
2
- import type { BrowserDispatchRequest } from './protocol';
3
- import type { BrowserProviderPage } from './providers';
4
-
5
- /**
6
- * The contract between the controller and whichever run branch executes a run.
7
- * It lives outside both so the schedulers never reach back into the controller
8
- * for a type: the controller owns the run's shape, the schedulers own the run.
9
- */
10
-
11
- /**
12
- * The watch-session control surface a watch-mode controller run hands back with
13
- * its initial cycle. Every rerun trigger the host owns (dev rebuild, HMR, the
14
- * in-page rerun button) resolves its own scope and then signals core's
15
- * invalidation subscriber; core resets the cycle state and calls back into
16
- * {@link BrowserWatchSession.runCycle} to execute it. A trigger that resolves to
17
- * no work never signals, so a scope matching none of this host's files produces
18
- * no cycle and no cycle output.
19
- */
20
- export type BrowserWatchSession = {
21
- /** Execute the scope the last trigger resolved, as one cycle outcome. */
22
- runCycle: (testPaths: string[]) => Promise<ExecutorCycleOutcome>;
23
- /** Explicit path-scoped rerun request (a CLI shortcut's browser fanout). */
24
- requestRerun: (testPaths?: string[]) => Promise<void>;
25
- };
26
-
27
- /**
28
- * What a run branch produces. Results and errors accumulate in the sinks the
29
- * controller owns, so a scheduler reports only what it alone knows: how long
30
- * the tests took, the session it left behind, and how to tear down a runtime
31
- * that does not outlive the run.
32
- */
33
- export type SchedulerRunResult = {
34
- testTime: number;
35
- watchSession?: BrowserWatchSession;
36
- close?: () => Promise<void>;
37
- };
38
-
39
- /**
40
- * How the shared dispatch layer reaches the pages of whichever run branch is
41
- * live. Only the running branch knows its pages, so it installs the resolver
42
- * and the dispatch layer stays branch-agnostic.
43
- */
44
- export type DispatchPageResolver = (
45
- target?: BrowserDispatchRequest['target'],
46
- ) => {
47
- runnerPage?: BrowserProviderPage;
48
- containerPage?: BrowserProviderPage;
49
- };
@@ -1,89 +0,0 @@
1
- import type { BrowserProviderContext, BrowserProviderPage } from './providers';
2
-
3
- type RunnerSessionRecord = {
4
- id: string;
5
- testFile: string;
6
- projectName: string;
7
- runToken: number;
8
- mode: 'headless-page' | 'headed-iframe';
9
- createdAt: number;
10
- context?: BrowserProviderContext;
11
- page?: BrowserProviderPage;
12
- metadata?: Record<string, unknown>;
13
- };
14
-
15
- type RunnerSessionInput = Omit<RunnerSessionRecord, 'id' | 'createdAt'> & {
16
- id?: string;
17
- createdAt?: number;
18
- };
19
-
20
- /**
21
- * Execution target index for host scheduling.
22
- * Provides lookup by session id, test file, and run token without coupling to UI topology.
23
- */
24
- export class RunnerSessionRegistry {
25
- private nextId = 0;
26
- private sessionsById = new Map<string, RunnerSessionRecord>();
27
- private sessionIdByTestFile = new Map<string, string>();
28
-
29
- register(input: RunnerSessionInput): RunnerSessionRecord {
30
- const id = input.id ?? `runner-session-${++this.nextId}`;
31
- const createdAt = input.createdAt ?? Date.now();
32
-
33
- const record: RunnerSessionRecord = {
34
- ...input,
35
- id,
36
- createdAt,
37
- };
38
-
39
- this.sessionsById.set(id, record);
40
- this.sessionIdByTestFile.set(record.testFile, id);
41
- return record;
42
- }
43
-
44
- getById(id: string): RunnerSessionRecord | undefined {
45
- return this.sessionsById.get(id);
46
- }
47
-
48
- getByTestFile(testFile: string): RunnerSessionRecord | undefined {
49
- const id = this.sessionIdByTestFile.get(testFile);
50
- if (!id) {
51
- return undefined;
52
- }
53
- return this.sessionsById.get(id);
54
- }
55
-
56
- list(): RunnerSessionRecord[] {
57
- return Array.from(this.sessionsById.values());
58
- }
59
-
60
- listByRunToken(runToken: number): RunnerSessionRecord[] {
61
- return this.list().filter((session) => session.runToken === runToken);
62
- }
63
-
64
- deleteById(id: string): boolean {
65
- const record = this.sessionsById.get(id);
66
- if (!record) {
67
- return false;
68
- }
69
-
70
- this.sessionsById.delete(id);
71
- if (this.sessionIdByTestFile.get(record.testFile) === id) {
72
- this.sessionIdByTestFile.delete(record.testFile);
73
- }
74
- return true;
75
- }
76
-
77
- deleteByTestFile(testFile: string): boolean {
78
- const id = this.sessionIdByTestFile.get(testFile);
79
- if (!id) {
80
- return false;
81
- }
82
- return this.deleteById(id);
83
- }
84
-
85
- clear(): void {
86
- this.sessionsById.clear();
87
- this.sessionIdByTestFile.clear();
88
- }
89
- }
@@ -1,96 +0,0 @@
1
- import type {
2
- DecodedSourceMapXInput,
3
- EncodedSourceMapXInput,
4
- } from '@jridgewell/trace-mapping';
5
- import convert from 'convert-source-map';
6
-
7
- export type SourceMapPayload = EncodedSourceMapXInput | DecodedSourceMapXInput;
8
-
9
- type Fetcher = typeof fetch;
10
-
11
- export const normalizeJavaScriptUrl = (
12
- value: string,
13
- options?: {
14
- origin?: string;
15
- },
16
- ): string | null => {
17
- try {
18
- const url = options?.origin
19
- ? new URL(value, options.origin)
20
- : new URL(value);
21
-
22
- if (url.protocol !== 'http:' && url.protocol !== 'https:') {
23
- return null;
24
- }
25
-
26
- url.search = '';
27
- url.hash = '';
28
- return url.toString();
29
- } catch {
30
- return null;
31
- }
32
- };
33
-
34
- const resolveInlineSourceMap = (code: string): SourceMapPayload | null => {
35
- const converter = convert.fromSource(code);
36
- if (!converter) {
37
- return null;
38
- }
39
-
40
- return converter.toObject() as SourceMapPayload;
41
- };
42
-
43
- const fetchSourceMap = async (
44
- jsUrl: string,
45
- fetcher: Fetcher,
46
- ): Promise<SourceMapPayload | null> => {
47
- const jsResponse = await fetcher(jsUrl);
48
- if (!jsResponse.ok) {
49
- return null;
50
- }
51
-
52
- const code = await jsResponse.text();
53
- const inlineMap = resolveInlineSourceMap(code);
54
- if (inlineMap) {
55
- return inlineMap;
56
- }
57
-
58
- const mapResponse = await fetcher(`${jsUrl}.map`);
59
- if (!mapResponse.ok) {
60
- return null;
61
- }
62
-
63
- return (await mapResponse.json()) as SourceMapPayload;
64
- };
65
-
66
- export const loadSourceMapWithCache = async ({
67
- jsUrl,
68
- cache,
69
- force = false,
70
- origin,
71
- fetcher = fetch,
72
- }: {
73
- jsUrl: string;
74
- cache: Map<string, SourceMapPayload | null>;
75
- force?: boolean;
76
- origin?: string;
77
- fetcher?: Fetcher;
78
- }): Promise<SourceMapPayload | null> => {
79
- const normalizedUrl = normalizeJavaScriptUrl(jsUrl, { origin });
80
- if (!normalizedUrl) {
81
- return null;
82
- }
83
-
84
- if (!force && cache.has(normalizedUrl)) {
85
- return cache.get(normalizedUrl) ?? null;
86
- }
87
-
88
- try {
89
- const sourceMap = await fetchSourceMap(normalizedUrl, fetcher);
90
- cache.set(normalizedUrl, sourceMap);
91
- return sourceMap;
92
- } catch {
93
- cache.set(normalizedUrl, null);
94
- return null;
95
- }
96
- };
@@ -1,69 +0,0 @@
1
- /**
2
- * Runtime source of truth for browser viewport presets.
3
- *
4
- * IMPORTANT: Keep this list/map in sync with `DevicePreset` typing in
5
- * `@rstest/core` (`packages/core/src/types/config.ts`) so `defineConfig`
6
- * autocomplete and runtime validation stay consistent.
7
- *
8
- * Upstream source of truth for ids/dimensions is the Chrome DevTools emulated
9
- * device list — mirror each device's `screen.vertical` `{ width, height }`:
10
- * https://github.com/ChromeDevTools/devtools-frontend/blob/main/front_end/models/emulation/EmulatedDevices.ts
11
- * Last verified in sync (all 17): 2026-04-22, devtools-frontend commit abaac05e.
12
- */
13
- export const BROWSER_VIEWPORT_PRESET_IDS = [
14
- 'iPhoneSE',
15
- 'iPhoneXR',
16
- 'iPhone12Pro',
17
- 'iPhone14ProMax',
18
- 'Pixel7',
19
- 'SamsungGalaxyS8Plus',
20
- 'SamsungGalaxyS20Ultra',
21
- 'iPadMini',
22
- 'iPadAir',
23
- 'iPadPro',
24
- 'SurfacePro7',
25
- 'SurfaceDuo',
26
- 'GalaxyZFold5',
27
- 'AsusZenbookFold',
28
- 'SamsungGalaxyA51A71',
29
- 'NestHub',
30
- 'NestHubMax',
31
- ] as const;
32
-
33
- type BrowserViewportPresetId = (typeof BROWSER_VIEWPORT_PRESET_IDS)[number];
34
-
35
- type BrowserViewportSize = {
36
- width: number;
37
- height: number;
38
- };
39
-
40
- export const BROWSER_VIEWPORT_PRESET_DIMENSIONS: Record<
41
- BrowserViewportPresetId,
42
- BrowserViewportSize
43
- > = {
44
- iPhoneSE: { width: 375, height: 667 },
45
- iPhoneXR: { width: 414, height: 896 },
46
- iPhone12Pro: { width: 390, height: 844 },
47
- iPhone14ProMax: { width: 430, height: 932 },
48
- Pixel7: { width: 412, height: 915 },
49
- SamsungGalaxyS8Plus: { width: 360, height: 740 },
50
- SamsungGalaxyS20Ultra: { width: 412, height: 915 },
51
- iPadMini: { width: 768, height: 1024 },
52
- iPadAir: { width: 820, height: 1180 },
53
- iPadPro: { width: 1024, height: 1366 },
54
- SurfacePro7: { width: 912, height: 1368 },
55
- SurfaceDuo: { width: 540, height: 720 },
56
- GalaxyZFold5: { width: 344, height: 882 },
57
- AsusZenbookFold: { width: 853, height: 1280 },
58
- SamsungGalaxyA51A71: { width: 412, height: 914 },
59
- NestHub: { width: 1024, height: 600 },
60
- NestHubMax: { width: 1280, height: 800 },
61
- };
62
-
63
- export const resolveBrowserViewportPreset = (
64
- presetId: string,
65
- ): BrowserViewportSize | null => {
66
- const size =
67
- BROWSER_VIEWPORT_PRESET_DIMENSIONS[presetId as BrowserViewportPresetId];
68
- return size ?? null;
69
- };