@wordpress/e2e-test-utils-playwright 1.48.0 → 1.48.1

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 (188) hide show
  1. package/build/admin/create-new-post.js +31 -0
  2. package/build/admin/create-new-post.js.map +1 -0
  3. package/build/admin/edit-post.js +20 -0
  4. package/build/admin/edit-post.js.map +1 -0
  5. package/{src/admin/get-page-error.ts → build/admin/get-page-error.js} +9 -12
  6. package/build/admin/get-page-error.js.map +1 -0
  7. package/build/admin/index.js +40 -0
  8. package/build/admin/index.js.map +1 -0
  9. package/build/admin/visit-admin-page.js +32 -0
  10. package/build/admin/visit-admin-page.js.map +1 -0
  11. package/build/admin/visit-site-editor.js +45 -0
  12. package/build/admin/visit-site-editor.js.map +1 -0
  13. package/build/admin/wait-for-site-editor.js +41 -0
  14. package/build/admin/wait-for-site-editor.js.map +1 -0
  15. package/build/config.js +13 -0
  16. package/build/config.js.map +1 -0
  17. package/build/editor/click-block-options-menu-item.js +17 -0
  18. package/build/editor/click-block-options-menu-item.js.map +1 -0
  19. package/build/editor/click-block-toolbar-button.js +16 -0
  20. package/build/editor/click-block-toolbar-button.js.map +1 -0
  21. package/build/editor/get-blocks.js +45 -0
  22. package/build/editor/get-blocks.js.map +1 -0
  23. package/build/editor/get-edited-post-content.js +15 -0
  24. package/build/editor/get-edited-post-content.js.map +1 -0
  25. package/build/editor/index.js +75 -0
  26. package/build/editor/index.js.map +1 -0
  27. package/build/editor/insert-block.js +23 -0
  28. package/build/editor/insert-block.js.map +1 -0
  29. package/build/editor/open-document-settings-sidebar.js +27 -0
  30. package/build/editor/open-document-settings-sidebar.js.map +1 -0
  31. package/build/editor/preview.js +21 -0
  32. package/build/editor/preview.js.map +1 -0
  33. package/build/editor/publish-post.js +45 -0
  34. package/build/editor/publish-post.js.map +1 -0
  35. package/build/editor/save-draft.js +18 -0
  36. package/build/editor/save-draft.js.map +1 -0
  37. package/build/editor/select-blocks.js +28 -0
  38. package/build/editor/select-blocks.js.map +1 -0
  39. package/build/editor/set-content.js +17 -0
  40. package/build/editor/set-content.js.map +1 -0
  41. package/build/editor/set-is-fixed-toolbar.js +18 -0
  42. package/build/editor/set-is-fixed-toolbar.js.map +1 -0
  43. package/build/editor/set-preferences.js +21 -0
  44. package/build/editor/set-preferences.js.map +1 -0
  45. package/build/editor/show-block-toolbar.js +19 -0
  46. package/build/editor/show-block-toolbar.js.map +1 -0
  47. package/build/editor/site-editor.js +44 -0
  48. package/build/editor/site-editor.js.map +1 -0
  49. package/build/editor/switch-editor-tool.js +33 -0
  50. package/build/editor/switch-editor-tool.js.map +1 -0
  51. package/build/editor/switch-to-legacy-canvas.js +18 -0
  52. package/build/editor/switch-to-legacy-canvas.js.map +1 -0
  53. package/build/editor/transform-block-to.js +24 -0
  54. package/build/editor/transform-block-to.js.map +1 -0
  55. package/build/index.js +19 -0
  56. package/build/index.js.map +1 -0
  57. package/build/lighthouse/index.js +61 -0
  58. package/build/lighthouse/index.js.map +1 -0
  59. package/build/metrics/index.js +314 -0
  60. package/build/metrics/index.js.map +1 -0
  61. package/build/page-utils/drag-files.js +119 -0
  62. package/build/page-utils/drag-files.js.map +1 -0
  63. package/build/page-utils/emulate-network-conditions.js +71 -0
  64. package/build/page-utils/emulate-network-conditions.js.map +1 -0
  65. package/build/page-utils/index.js +37 -0
  66. package/build/page-utils/index.js.map +1 -0
  67. package/build/page-utils/is-current-url.js +21 -0
  68. package/build/page-utils/is-current-url.js.map +1 -0
  69. package/build/page-utils/keycodes.js +41 -0
  70. package/build/page-utils/keycodes.js.map +1 -0
  71. package/build/page-utils/press-keys.js +141 -0
  72. package/build/page-utils/press-keys.js.map +1 -0
  73. package/{src → build}/page-utils/set-browser-viewport.js +12 -14
  74. package/build/page-utils/set-browser-viewport.js.map +1 -0
  75. package/build/request-utils/blocks.js +40 -0
  76. package/build/request-utils/blocks.js.map +1 -0
  77. package/build/request-utils/comments.js +52 -0
  78. package/build/request-utils/comments.js.map +1 -0
  79. package/build/request-utils/gutenberg-experiments.js +47 -0
  80. package/build/request-utils/gutenberg-experiments.js.map +1 -0
  81. package/build/request-utils/index.js +196 -0
  82. package/build/request-utils/index.js.map +1 -0
  83. package/build/request-utils/login.js +21 -0
  84. package/build/request-utils/login.js.map +1 -0
  85. package/build/request-utils/media.js +106 -0
  86. package/build/request-utils/media.js.map +1 -0
  87. package/build/request-utils/menus.js +116 -0
  88. package/build/request-utils/menus.js.map +1 -0
  89. package/build/request-utils/pages.js +53 -0
  90. package/build/request-utils/pages.js.map +1 -0
  91. package/build/request-utils/patterns.js +27 -0
  92. package/build/request-utils/patterns.js.map +1 -0
  93. package/build/request-utils/plugins.js +85 -0
  94. package/build/request-utils/plugins.js.map +1 -0
  95. package/build/request-utils/posts.js +42 -0
  96. package/build/request-utils/posts.js.map +1 -0
  97. package/build/request-utils/preferences.js +54 -0
  98. package/build/request-utils/preferences.js.map +1 -0
  99. package/{src/request-utils/records.ts → build/request-utils/records.js} +10 -15
  100. package/build/request-utils/records.js.map +1 -0
  101. package/build/request-utils/rest.js +181 -0
  102. package/build/request-utils/rest.js.map +1 -0
  103. package/build/request-utils/site-settings.js +33 -0
  104. package/build/request-utils/site-settings.js.map +1 -0
  105. package/build/request-utils/templates.js +54 -0
  106. package/build/request-utils/templates.js.map +1 -0
  107. package/build/request-utils/themes.js +69 -0
  108. package/build/request-utils/themes.js.map +1 -0
  109. package/build/request-utils/users.js +81 -0
  110. package/build/request-utils/users.js.map +1 -0
  111. package/build/request-utils/widgets.js +61 -0
  112. package/build/request-utils/widgets.js.map +1 -0
  113. package/build/test.js +189 -0
  114. package/build/test.js.map +1 -0
  115. package/build/types.js +3 -0
  116. package/build/types.js.map +1 -0
  117. package/build-types/admin/index.d.ts.map +1 -1
  118. package/build-types/config.d.ts.map +1 -1
  119. package/build-types/editor/index.d.ts.map +1 -1
  120. package/build-types/lighthouse/index.d.ts.map +1 -1
  121. package/build-types/metrics/index.d.ts.map +1 -1
  122. package/build-types/page-utils/index.d.ts.map +1 -1
  123. package/build-types/page-utils/press-keys.d.ts +1 -1
  124. package/build-types/page-utils/set-browser-viewport.d.ts +22 -12
  125. package/build-types/page-utils/set-browser-viewport.d.ts.map +1 -1
  126. package/build-types/request-utils/index.d.ts +2 -2
  127. package/build-types/request-utils/index.d.ts.map +1 -1
  128. package/build-types/request-utils/pages.d.ts +1 -1
  129. package/build-types/request-utils/pages.d.ts.map +1 -1
  130. package/build-types/request-utils/widgets.d.ts +2 -2
  131. package/build-types/request-utils/widgets.d.ts.map +1 -1
  132. package/build-types/types.d.ts.map +1 -1
  133. package/package.json +8 -5
  134. package/src/admin/create-new-post.ts +0 -47
  135. package/src/admin/edit-post.ts +0 -24
  136. package/src/admin/index.ts +0 -52
  137. package/src/admin/visit-admin-page.ts +0 -43
  138. package/src/admin/visit-site-editor.ts +0 -62
  139. package/src/admin/wait-for-site-editor.ts +0 -52
  140. package/src/config.ts +0 -12
  141. package/src/editor/click-block-options-menu-item.ts +0 -18
  142. package/src/editor/click-block-toolbar-button.ts +0 -21
  143. package/src/editor/get-blocks.ts +0 -75
  144. package/src/editor/get-edited-post-content.ts +0 -19
  145. package/src/editor/index.ts +0 -95
  146. package/src/editor/insert-block.ts +0 -54
  147. package/src/editor/open-document-settings-sidebar.ts +0 -31
  148. package/src/editor/preview.ts +0 -32
  149. package/src/editor/publish-post.ts +0 -51
  150. package/src/editor/save-draft.ts +0 -20
  151. package/src/editor/select-blocks.ts +0 -48
  152. package/src/editor/set-content.ts +0 -24
  153. package/src/editor/set-is-fixed-toolbar.ts +0 -20
  154. package/src/editor/set-preferences.ts +0 -37
  155. package/src/editor/show-block-toolbar.ts +0 -20
  156. package/src/editor/site-editor.ts +0 -55
  157. package/src/editor/switch-editor-tool.ts +0 -34
  158. package/src/editor/switch-to-legacy-canvas.ts +0 -20
  159. package/src/editor/transform-block-to.ts +0 -34
  160. package/src/index.ts +0 -8
  161. package/src/lighthouse/index.ts +0 -75
  162. package/src/metrics/index.ts +0 -441
  163. package/src/page-utils/drag-files.ts +0 -173
  164. package/src/page-utils/emulate-network-conditions.ts +0 -101
  165. package/src/page-utils/index.ts +0 -54
  166. package/src/page-utils/is-current-url.ts +0 -20
  167. package/src/page-utils/keycodes.ts +0 -48
  168. package/src/page-utils/press-keys.ts +0 -195
  169. package/src/request-utils/blocks.ts +0 -58
  170. package/src/request-utils/comments.ts +0 -80
  171. package/src/request-utils/gutenberg-experiments.ts +0 -62
  172. package/src/request-utils/index.ts +0 -222
  173. package/src/request-utils/login.ts +0 -34
  174. package/src/request-utils/media.ts +0 -102
  175. package/src/request-utils/menus.ts +0 -145
  176. package/src/request-utils/pages.ts +0 -75
  177. package/src/request-utils/patterns.ts +0 -31
  178. package/src/request-utils/plugins.ts +0 -103
  179. package/src/request-utils/posts.ts +0 -69
  180. package/src/request-utils/preferences.ts +0 -63
  181. package/src/request-utils/rest.ts +0 -222
  182. package/src/request-utils/site-settings.ts +0 -58
  183. package/src/request-utils/templates.ts +0 -83
  184. package/src/request-utils/themes.ts +0 -110
  185. package/src/request-utils/users.ts +0 -125
  186. package/src/request-utils/widgets.js +0 -68
  187. package/src/test.ts +0 -204
  188. package/src/types.ts +0 -13
@@ -1,173 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { readFile } from 'fs/promises';
5
- import { basename } from 'path';
6
- import { getType } from 'mime';
7
-
8
- /**
9
- * Internal dependencies
10
- */
11
- import type { PageUtils } from './index';
12
- import type { Locator } from '@playwright/test';
13
-
14
- type FileObject = {
15
- name: string;
16
- mimeType?: string;
17
- buffer: Buffer;
18
- };
19
-
20
- type Options = {
21
- position?: { x: number; y: number };
22
- };
23
-
24
- /**
25
- * Simulate dragging files from outside the current page.
26
- *
27
- * @param this
28
- * @param files The files to be dragged.
29
- * @return The methods of the drag operation.
30
- */
31
- async function dragFiles(
32
- this: PageUtils,
33
- files: string | string[] | FileObject | FileObject[]
34
- ) {
35
- const filesList = Array.isArray( files ) ? files : [ files ];
36
- const fileObjects = await Promise.all(
37
- filesList.map( async ( filePathOrObject ) => {
38
- if ( typeof filePathOrObject !== 'string' ) {
39
- return {
40
- name: filePathOrObject.name,
41
- mimeType:
42
- filePathOrObject.mimeType ||
43
- getType( filePathOrObject.name ),
44
- base64: filePathOrObject.buffer.toString( 'base64' ),
45
- };
46
- }
47
- const base64 = await readFile( filePathOrObject, 'base64' );
48
- const name = basename( filePathOrObject );
49
- return {
50
- name,
51
- mimeType: getType( filePathOrObject ),
52
- base64,
53
- };
54
- } )
55
- );
56
-
57
- // CDP doesn't actually support dragging files, this is only a _good enough_
58
- // dummy data so that it will correctly send the relevant events.
59
- const dragData = {
60
- items: fileObjects.map( ( fileObject ) => ( {
61
- mimeType: fileObject.mimeType ?? 'File',
62
- data: fileObject.base64,
63
- } ) ),
64
- files: fileObjects.map( ( fileObject ) => fileObject.name ),
65
- // Copy = 1, Link = 2, Move = 16.
66
- dragOperationsMask: 1,
67
- };
68
-
69
- const cdpSession = await this.context.newCDPSession( this.page );
70
-
71
- const position = {
72
- x: 0,
73
- y: 0,
74
- };
75
-
76
- return {
77
- /**
78
- * Drag the files over an element (fires `dragenter` and `dragover` events).
79
- *
80
- * @param selectorOrLocator A selector or a locator to search for an element.
81
- * @param options The optional options.
82
- * @param options.position A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of the element.
83
- */
84
- dragOver: async (
85
- selectorOrLocator: string | Locator,
86
- options: Options = {}
87
- ) => {
88
- const locator =
89
- typeof selectorOrLocator === 'string'
90
- ? this.page.locator( selectorOrLocator )
91
- : selectorOrLocator;
92
- const boundingBox = await locator.boundingBox();
93
-
94
- if ( ! boundingBox ) {
95
- throw new Error(
96
- 'Cannot find the element or the element is not visible on the viewport.'
97
- );
98
- }
99
-
100
- position.x =
101
- boundingBox.x +
102
- ( options.position?.x ?? boundingBox.width / 2 );
103
- position.y =
104
- boundingBox.y +
105
- ( options.position?.y ?? boundingBox.height / 2 );
106
-
107
- await cdpSession.send( 'Input.dispatchDragEvent', {
108
- type: 'dragEnter',
109
- ...position,
110
- data: dragData,
111
- } );
112
- await cdpSession.send( 'Input.dispatchDragEvent', {
113
- type: 'dragOver',
114
- ...position,
115
- data: dragData,
116
- } );
117
- },
118
-
119
- /**
120
- * Drop the files at the current position.
121
- */
122
- drop: async () => {
123
- const topMostElement = await this.page.evaluateHandle(
124
- ( { x, y } ) => {
125
- const element = document.elementFromPoint( x, y );
126
- if ( element instanceof HTMLIFrameElement ) {
127
- const offsetBox = element.getBoundingClientRect();
128
- return element.contentDocument!.elementFromPoint(
129
- x - offsetBox.x,
130
- y - offsetBox.y
131
- );
132
- }
133
- return element;
134
- },
135
- position
136
- );
137
- const elementHandle = topMostElement.asElement();
138
-
139
- if ( ! elementHandle ) {
140
- throw new Error( 'Element not found.' );
141
- }
142
-
143
- const dataTransfer = await elementHandle.evaluateHandle(
144
- async ( _node, _fileObjects ) => {
145
- const dt = new DataTransfer();
146
- const fileInstances = await Promise.all(
147
- _fileObjects.map( async ( fileObject: any ) => {
148
- const blob = await fetch(
149
- `data:${ fileObject.mimeType };base64,${ fileObject.base64 }`
150
- ).then( ( res ) => res.blob() );
151
- return new File( [ blob ], fileObject.name, {
152
- type: fileObject.mimeType ?? undefined,
153
- } );
154
- } )
155
- );
156
-
157
- fileInstances.forEach( ( file ) => {
158
- dt.items.add( file );
159
- } );
160
-
161
- return dt;
162
- },
163
- fileObjects
164
- );
165
-
166
- await elementHandle.dispatchEvent( 'drop', { dataTransfer } );
167
-
168
- await cdpSession.detach();
169
- },
170
- };
171
- }
172
-
173
- export { dragFiles };
@@ -1,101 +0,0 @@
1
- /**
2
- * Internal dependencies
3
- */
4
- import type { PageUtils } from './';
5
-
6
- interface NetworkConditions {
7
- /**
8
- * True to emulate internet disconnection.
9
- */
10
- offline: boolean;
11
- /**
12
- * Minimum latency from request sent to response headers received (ms).
13
- */
14
- latency: number;
15
- /**
16
- * Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.
17
- */
18
- downloadThroughput: number;
19
- /**
20
- * Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.
21
- */
22
- uploadThroughput: number;
23
- }
24
-
25
- // Defaults from https://github.com/puppeteer/puppeteer/blob/401355610874beac23a51dcb75739a4bb4191a2b/packages/puppeteer-core/src/cdp/PredefinedNetworkConditions.ts.
26
- const PredefinedNetworkConditions: Record< string, NetworkConditions > = {
27
- // Generally aligned with DevTools
28
- // https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/front_end/core/sdk/NetworkManager.ts;l=398;drc=225e1240f522ca684473f541ae6dae6cd766dd33.
29
- 'Slow 3G': {
30
- offline: false,
31
- // ~500Kbps down
32
- downloadThroughput: ( ( 500 * 1000 ) / 8 ) * 0.8,
33
- // ~500Kbps up
34
- uploadThroughput: ( ( 500 * 1000 ) / 8 ) * 0.8,
35
- // 400ms RTT
36
- latency: 400 * 5,
37
- },
38
- 'Fast 3G': {
39
- offline: false,
40
- // ~1.6 Mbps down
41
- downloadThroughput: ( ( 1.6 * 1000 * 1000 ) / 8 ) * 0.9,
42
- // ~0.75 Mbps up
43
- uploadThroughput: ( ( 750 * 1000 ) / 8 ) * 0.9,
44
- // 150ms RTT
45
- latency: 150 * 3.75,
46
- },
47
- // alias to Fast 3G to align with Lighthouse (crbug.com/342406608)
48
- // and DevTools (crbug.com/342406608),
49
- 'Slow 4G': {
50
- offline: false,
51
- // ~1.6 Mbps down
52
- downloadThroughput: ( ( 1.6 * 1000 * 1000 ) / 8 ) * 0.9,
53
- // ~0.75 Mbps up
54
- uploadThroughput: ( ( 750 * 1000 ) / 8 ) * 0.9,
55
- // 150ms RTT
56
- latency: 150 * 3.75,
57
- },
58
- 'Fast 4G': {
59
- offline: false,
60
- // 9 Mbps down
61
- downloadThroughput: ( ( 9 * 1000 * 1000 ) / 8 ) * 0.9,
62
- // 1.5 Mbps up
63
- uploadThroughput: ( ( 1.5 * 1000 * 1000 ) / 8 ) * 0.9,
64
- // 60ms RTT
65
- latency: 60 * 2.75,
66
- },
67
- /**
68
- * Network conditions used for desktop in Lighthouse/PSI.
69
- *
70
- * 10,240 kb/s throughput with 40 ms TCP RTT.
71
- *
72
- * @see https://github.com/paulirish/lighthouse/blob/f0855904aaffaecf3089169449646960782d7e92/core/config/constants.js#L40-L49
73
- * @see https://docs.google.com/document/d/1-p4HSp42REEA5-jCBVB6PqQcVhI1nQIblBCNKhPJUXg/edit?tab=t.0#heading=h.jsap7yf4phk6
74
- */
75
- Broadband: {
76
- offline: false,
77
- downloadThroughput: ( 10240 * 1000 ) / 8,
78
- uploadThroughput: ( 10240 * 1000 ) / 8,
79
- latency: 40,
80
- },
81
- };
82
-
83
- export async function emulateNetworkConditions(
84
- this: PageUtils,
85
- condition: keyof typeof PredefinedNetworkConditions | NetworkConditions
86
- ) {
87
- if ( 'chromium' !== this.browserName ) {
88
- throw new Error(
89
- 'CDP sessions are only supported on Chromium-based browsers'
90
- );
91
- }
92
-
93
- const session = await this.page.context().newCDPSession( this.page );
94
- await session.send(
95
- 'Network.emulateNetworkConditions',
96
- 'string' === typeof condition
97
- ? PredefinedNetworkConditions[ condition ]
98
- : condition
99
- );
100
- await session.detach();
101
- }
@@ -1,54 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import type {
5
- Browser,
6
- Page,
7
- BrowserContext,
8
- PlaywrightWorkerOptions,
9
- } from '@playwright/test';
10
-
11
- /**
12
- * Internal dependencies
13
- */
14
- import { dragFiles } from './drag-files';
15
- import { isCurrentURL } from './is-current-url';
16
- import { setClipboardData, pressKeys } from './press-keys';
17
- import { setBrowserViewport } from './set-browser-viewport';
18
- import { emulateNetworkConditions } from './emulate-network-conditions';
19
-
20
- type PageUtilConstructorParams = {
21
- page: Page;
22
- browserName: PlaywrightWorkerOptions[ 'browserName' ];
23
- };
24
-
25
- class PageUtils {
26
- browser: Browser;
27
- page: Page;
28
- context: BrowserContext;
29
- browserName: PlaywrightWorkerOptions[ 'browserName' ];
30
-
31
- constructor( { page, browserName }: PageUtilConstructorParams ) {
32
- this.page = page;
33
- this.context = page.context();
34
- this.browser = this.context.browser()!;
35
- this.browserName = browserName;
36
- }
37
-
38
- /** @borrows dragFiles as this.dragFiles */
39
- dragFiles: typeof dragFiles = dragFiles.bind( this );
40
- /** @borrows isCurrentURL as this.isCurrentURL */
41
- isCurrentURL: typeof isCurrentURL = isCurrentURL.bind( this );
42
- /** @borrows pressKeys as this.pressKeys */
43
- pressKeys: typeof pressKeys = pressKeys.bind( this );
44
- /** @borrows setBrowserViewport as this.setBrowserViewport */
45
- setBrowserViewport: typeof setBrowserViewport =
46
- setBrowserViewport.bind( this );
47
- /** @borrows setClipboardData as this.setClipboardData */
48
- setClipboardData: typeof setClipboardData = setClipboardData.bind( this );
49
- /** @borrows emulateNetworkConditions as this.emulateNetworkConditions */
50
- emulateNetworkConditions: typeof emulateNetworkConditions =
51
- emulateNetworkConditions.bind( this );
52
- }
53
-
54
- export { PageUtils };
@@ -1,20 +0,0 @@
1
- /**
2
- * Internal dependencies
3
- */
4
- import { WP_BASE_URL } from '../config';
5
- import type { PageUtils } from './';
6
-
7
- /**
8
- * Checks if current path of the URL matches the provided path.
9
- *
10
- * @param this
11
- * @param path String to be serialized as pathname.
12
- *
13
- * @return Boolean represents whether current URL is or not a WordPress path.
14
- */
15
- export function isCurrentURL( this: PageUtils, path: string ) {
16
- const currentURL = new URL( this.page.url() );
17
- const expectedURL = new URL( path, WP_BASE_URL );
18
-
19
- return expectedURL.pathname === currentURL.pathname;
20
- }
@@ -1,48 +0,0 @@
1
- /**
2
- * This filed is partially copied from @wordpress/keycodes to keep the package
3
- * (internal-)dependencies free.
4
- */
5
-
6
- /**
7
- * Keycode for ALT key.
8
- */
9
- export const ALT = 'alt';
10
-
11
- /**
12
- * Keycode for CTRL key.
13
- */
14
- export const CTRL = 'ctrl';
15
-
16
- /**
17
- * Keycode for COMMAND key.
18
- */
19
- export const COMMAND = 'meta';
20
-
21
- /**
22
- * Keycode for SHIFT key.
23
- */
24
- export const SHIFT = 'shift';
25
-
26
- /**
27
- * Object that contains functions that return the available modifier
28
- * depending on platform.
29
- */
30
- export const modifiers: Record<
31
- string,
32
- ( _isApple: () => boolean ) => string[]
33
- > = {
34
- primary: ( _isApple ) => ( _isApple() ? [ COMMAND ] : [ CTRL ] ),
35
- primaryShift: ( _isApple ) =>
36
- _isApple() ? [ SHIFT, COMMAND ] : [ CTRL, SHIFT ],
37
- primaryAlt: ( _isApple ) =>
38
- _isApple() ? [ ALT, COMMAND ] : [ CTRL, ALT ],
39
- secondary: ( _isApple ) =>
40
- _isApple() ? [ SHIFT, ALT, COMMAND ] : [ CTRL, SHIFT, ALT ],
41
- access: ( _isApple ) => ( _isApple() ? [ CTRL, ALT ] : [ SHIFT, ALT ] ),
42
- ctrl: () => [ CTRL ],
43
- alt: () => [ ALT ],
44
- ctrlShift: () => [ CTRL, SHIFT ],
45
- shift: () => [ SHIFT ],
46
- shiftAlt: () => [ SHIFT, ALT ],
47
- undefined: () => [],
48
- };
@@ -1,195 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { capitalCase } from 'change-case';
5
- import type { Page } from '@playwright/test';
6
-
7
- /**
8
- * Internal dependencies
9
- */
10
- import type { PageUtils } from './';
11
- import { modifiers as baseModifiers, SHIFT, ALT, CTRL } from './keycodes';
12
-
13
- let clipboardDataHolder: {
14
- 'text/plain': string;
15
- 'text/html': string;
16
- 'rich-text': string;
17
- } = {
18
- 'text/plain': '',
19
- 'text/html': '',
20
- 'rich-text': '',
21
- };
22
-
23
- /**
24
- * Sets the clipboard data that can be pasted with
25
- * `pressKeys( 'primary+v' )`.
26
- *
27
- * @param clipboardData
28
- * @param clipboardData.plainText
29
- * @param clipboardData.html
30
- */
31
- export function setClipboardData(
32
- this: PageUtils,
33
- { plainText = '', html = '' }
34
- ) {
35
- clipboardDataHolder = {
36
- 'text/plain': plainText,
37
- 'text/html': html,
38
- 'rich-text': '',
39
- };
40
- }
41
-
42
- async function emulateClipboard( page: Page, type: 'copy' | 'cut' | 'paste' ) {
43
- const output = await page.evaluate(
44
- ( [ _type, _clipboardData ] ) => {
45
- const canvasDoc =
46
- // @ts-ignore
47
- document.activeElement?.contentDocument ?? document;
48
- const event = new ClipboardEvent( _type, {
49
- bubbles: true,
50
- cancelable: true,
51
- clipboardData: new DataTransfer(),
52
- } );
53
-
54
- if ( ! event.clipboardData ) {
55
- throw new Error( 'ClipboardEvent.clipboardData is null' );
56
- }
57
-
58
- if ( _type === 'paste' ) {
59
- event.clipboardData.setData(
60
- 'text/plain',
61
- _clipboardData[ 'text/plain' ]
62
- );
63
- event.clipboardData.setData(
64
- 'text/html',
65
- _clipboardData[ 'text/html' ]
66
- );
67
- event.clipboardData.setData(
68
- 'rich-text',
69
- _clipboardData[ 'rich-text' ]
70
- );
71
- } else {
72
- const selection = canvasDoc.defaultView.getSelection()!;
73
- const plainText = selection.toString();
74
- let html = plainText;
75
- if ( selection.rangeCount ) {
76
- const range = selection.getRangeAt( 0 );
77
- const fragment = range.cloneContents();
78
- html = Array.from( fragment.childNodes )
79
- .map(
80
- ( node ) =>
81
- ( node as Element ).outerHTML ??
82
- ( node as Element ).nodeValue
83
- )
84
- .join( '' );
85
- }
86
- event.clipboardData.setData( 'text/plain', plainText );
87
- event.clipboardData.setData( 'text/html', html );
88
- }
89
-
90
- canvasDoc.activeElement.dispatchEvent( event );
91
-
92
- if ( _type === 'paste' ) {
93
- return event.defaultPrevented;
94
- }
95
-
96
- return {
97
- 'text/plain': event.clipboardData.getData( 'text/plain' ),
98
- 'text/html': event.clipboardData.getData( 'text/html' ),
99
- 'rich-text': event.clipboardData.getData( 'rich-text' ),
100
- };
101
- },
102
- [ type, clipboardDataHolder ] as const
103
- );
104
-
105
- if ( typeof output === 'object' ) {
106
- clipboardDataHolder = output;
107
- }
108
-
109
- if ( output === false ) {
110
- // Emulate paste by typing the clipboard content, which works across all
111
- // elements and documents (keyboard.type does uses the nested active
112
- // element automatically).
113
- await page.keyboard.type( clipboardDataHolder[ 'text/plain' ] );
114
- }
115
- }
116
-
117
- const isAppleOS = () => process.platform === 'darwin';
118
-
119
- const isWebkit = ( page: Page ) =>
120
- page.context().browser()!.browserType().name() === 'webkit';
121
-
122
- const browserCache = new WeakMap();
123
- const getHasNaturalTabNavigation = async ( page: Page ) => {
124
- if ( ! isAppleOS() || ! isWebkit( page ) ) {
125
- return true;
126
- }
127
- if ( browserCache.has( page.context().browser()! ) ) {
128
- return browserCache.get( page.context().browser()! );
129
- }
130
- const testPage = await page.context().newPage();
131
- await testPage.setContent( `<button>1</button><button>2</button>` );
132
- await testPage.getByText( '1' ).focus();
133
- await testPage.keyboard.press( 'Tab' );
134
- const featureDetected = await testPage
135
- .getByText( '2' )
136
- .evaluate( ( node ) => node === document.activeElement );
137
- browserCache.set( page.context().browser()!, featureDetected );
138
- await testPage.close();
139
- return featureDetected;
140
- };
141
-
142
- type Options = {
143
- times?: number;
144
- delay?: number;
145
- };
146
-
147
- const modifiers = {
148
- ...baseModifiers,
149
- shiftAlt: ( _isApple: () => boolean ) =>
150
- _isApple() ? [ SHIFT, ALT ] : [ SHIFT, CTRL ],
151
- };
152
-
153
- export async function pressKeys(
154
- this: PageUtils,
155
- key: string,
156
- { times, ...pressOptions }: Options = {}
157
- ) {
158
- const hasNaturalTabNavigation = await getHasNaturalTabNavigation(
159
- this.page
160
- );
161
-
162
- let command: () => Promise< void >;
163
-
164
- if ( key.toLowerCase() === 'primary+c' ) {
165
- command = () => emulateClipboard( this.page, 'copy' );
166
- } else if ( key.toLowerCase() === 'primary+x' ) {
167
- command = () => emulateClipboard( this.page, 'cut' );
168
- } else if ( key.toLowerCase() === 'primary+v' ) {
169
- command = () => emulateClipboard( this.page, 'paste' );
170
- } else {
171
- const keys = key.split( '+' ).flatMap( ( keyCode ) => {
172
- if ( Object.prototype.hasOwnProperty.call( modifiers, keyCode ) ) {
173
- return modifiers[ keyCode as keyof typeof modifiers ](
174
- isAppleOS
175
- ).map( ( modifier ) =>
176
- modifier === CTRL ? 'Control' : capitalCase( modifier )
177
- );
178
- } else if ( keyCode === 'Tab' && ! hasNaturalTabNavigation ) {
179
- return [ 'Alt', 'Tab' ];
180
- }
181
- return keyCode;
182
- } );
183
- const normalizedKeys = keys.join( '+' );
184
- command = () => this.page.keyboard.press( normalizedKeys );
185
- }
186
-
187
- times = times ?? 1;
188
- for ( let i = 0; i < times; i += 1 ) {
189
- await command();
190
-
191
- if ( times > 1 && pressOptions.delay ) {
192
- await this.page.waitForTimeout( pressOptions.delay );
193
- }
194
- }
195
- }
@@ -1,58 +0,0 @@
1
- /**
2
- * Internal dependencies
3
- */
4
- import type { RequestUtils } from './index';
5
-
6
- type CreateBlockPayload = {
7
- date?: string;
8
- date_gmt?: string;
9
- slug?: string;
10
- title: string;
11
- status: 'publish' | 'future' | 'draft' | 'pending' | 'private';
12
- content?: string;
13
- meta?: unknown;
14
- wp_pattern_category?: number[];
15
- };
16
-
17
- /**
18
- * Delete all blocks using REST API.
19
- *
20
- * @see https://developer.wordpress.org/rest-api/reference/blocks/#list-editor-blocks
21
- * @param this
22
- */
23
- export async function deleteAllBlocks( this: RequestUtils ) {
24
- // List all blocks.
25
- // https://developer.wordpress.org/rest-api/reference/blocks/#list-editor-blocks
26
- const blocks = await this.rest( {
27
- path: '/wp/v2/blocks',
28
- params: {
29
- per_page: 100,
30
- // All possible statuses.
31
- status: 'publish,future,draft,pending,private,trash',
32
- },
33
- } );
34
-
35
- // Delete blocks.
36
- // https://developer.wordpress.org/rest-api/reference/blocks/#delete-a-editor-block
37
- // "/wp/v2/posts" not yet supports batch requests.
38
- await this.batchRest(
39
- blocks.map( ( block: { id: number } ) => ( {
40
- method: 'DELETE',
41
- path: `/wp/v2/blocks/${ block.id }?force=true`,
42
- } ) )
43
- );
44
- }
45
-
46
- /**
47
- * Creates a new block using the REST API.
48
- *
49
- * @see https://developer.wordpress.org/rest-api/reference/blocks/#create-a-editor-block.
50
- * @param this
51
- * @param payload Block payload.
52
- */
53
- export async function createBlock(
54
- this: RequestUtils,
55
- payload: CreateBlockPayload
56
- ) {
57
- return this.createRecord( 'blocks', { ...payload } );
58
- }