@electriccitizen/bolt 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +361 -0
  2. package/dist/adapters/ddev.d.ts +16 -0
  3. package/dist/adapters/ddev.js +75 -0
  4. package/dist/adapters/ddev.js.map +1 -0
  5. package/dist/adapters/index.d.ts +1 -0
  6. package/dist/adapters/index.js +2 -0
  7. package/dist/adapters/index.js.map +1 -0
  8. package/dist/cli.d.ts +2 -0
  9. package/dist/cli.js +167 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/commands/doctor.d.ts +4 -0
  12. package/dist/commands/doctor.js +263 -0
  13. package/dist/commands/doctor.js.map +1 -0
  14. package/dist/commands/init.d.ts +12 -0
  15. package/dist/commands/init.js +319 -0
  16. package/dist/commands/init.js.map +1 -0
  17. package/dist/commands/pr.d.ts +20 -0
  18. package/dist/commands/pr.js +282 -0
  19. package/dist/commands/pr.js.map +1 -0
  20. package/dist/commands/refresh.d.ts +22 -0
  21. package/dist/commands/refresh.js +375 -0
  22. package/dist/commands/refresh.js.map +1 -0
  23. package/dist/commands/suppress.d.ts +10 -0
  24. package/dist/commands/suppress.js +86 -0
  25. package/dist/commands/suppress.js.map +1 -0
  26. package/dist/commands/test.d.ts +5 -0
  27. package/dist/commands/test.js +106 -0
  28. package/dist/commands/test.js.map +1 -0
  29. package/dist/commands/update.d.ts +26 -0
  30. package/dist/commands/update.js +573 -0
  31. package/dist/commands/update.js.map +1 -0
  32. package/dist/config.d.ts +47 -0
  33. package/dist/config.js +187 -0
  34. package/dist/config.js.map +1 -0
  35. package/dist/formatters/index.d.ts +2 -0
  36. package/dist/formatters/index.js +3 -0
  37. package/dist/formatters/index.js.map +1 -0
  38. package/dist/formatters/json.d.ts +5 -0
  39. package/dist/formatters/json.js +7 -0
  40. package/dist/formatters/json.js.map +1 -0
  41. package/dist/formatters/markdown.d.ts +5 -0
  42. package/dist/formatters/markdown.js +144 -0
  43. package/dist/formatters/markdown.js.map +1 -0
  44. package/dist/formatters/text.d.ts +5 -0
  45. package/dist/formatters/text.js +123 -0
  46. package/dist/formatters/text.js.map +1 -0
  47. package/dist/plugins/accessibility.d.ts +5 -0
  48. package/dist/plugins/accessibility.js +116 -0
  49. package/dist/plugins/accessibility.js.map +1 -0
  50. package/dist/plugins/browser-smoke.d.ts +6 -0
  51. package/dist/plugins/browser-smoke.js +331 -0
  52. package/dist/plugins/browser-smoke.js.map +1 -0
  53. package/dist/plugins/field-interaction.d.ts +6 -0
  54. package/dist/plugins/field-interaction.js +570 -0
  55. package/dist/plugins/field-interaction.js.map +1 -0
  56. package/dist/plugins/index.d.ts +6 -0
  57. package/dist/plugins/index.js +28 -0
  58. package/dist/plugins/index.js.map +1 -0
  59. package/dist/plugins/linkit.d.ts +8 -0
  60. package/dist/plugins/linkit.js +170 -0
  61. package/dist/plugins/linkit.js.map +1 -0
  62. package/dist/plugins/media-browser.d.ts +6 -0
  63. package/dist/plugins/media-browser.js +257 -0
  64. package/dist/plugins/media-browser.js.map +1 -0
  65. package/dist/plugins/structural-smoke.d.ts +6 -0
  66. package/dist/plugins/structural-smoke.js +90 -0
  67. package/dist/plugins/structural-smoke.js.map +1 -0
  68. package/dist/plugins/visual-regression.d.ts +8 -0
  69. package/dist/plugins/visual-regression.js +214 -0
  70. package/dist/plugins/visual-regression.js.map +1 -0
  71. package/dist/plugins/wysiwyg.d.ts +8 -0
  72. package/dist/plugins/wysiwyg.js +221 -0
  73. package/dist/plugins/wysiwyg.js.map +1 -0
  74. package/dist/runner.d.ts +21 -0
  75. package/dist/runner.js +293 -0
  76. package/dist/runner.js.map +1 -0
  77. package/dist/suppression.d.ts +55 -0
  78. package/dist/suppression.js +223 -0
  79. package/dist/suppression.js.map +1 -0
  80. package/dist/types.d.ts +178 -0
  81. package/dist/types.js +5 -0
  82. package/dist/types.js.map +1 -0
  83. package/modules/bolt_inspect/bolt_inspect.info.yml +6 -0
  84. package/modules/bolt_inspect/bolt_inspect.services.yml +22 -0
  85. package/modules/bolt_inspect/composer.json +16 -0
  86. package/modules/bolt_inspect/drush.services.yml +10 -0
  87. package/modules/bolt_inspect/src/Drush/Commands/BoltInspectCommands.php +203 -0
  88. package/modules/bolt_inspect/src/Service/ContentGenerator.php +586 -0
  89. package/modules/bolt_inspect/src/Service/SiteProfiler.php +362 -0
  90. package/modules/bolt_inspect/src/Service/TestEntityTracker.php +98 -0
  91. package/package.json +46 -0
  92. package/scripts/setup.sh +34 -0
@@ -0,0 +1,570 @@
1
+ /**
2
+ * field-interaction plugin — creates content via the admin UI for each content type,
3
+ * fills required fields, submits, and verifies save success.
4
+ */
5
+ export const fieldInteractionPlugin = {
6
+ name: 'field-interaction',
7
+ description: 'Create content via admin UI, fill required fields, verify form submit',
8
+ readOnly: false,
9
+ needsGeneratedContent: false,
10
+ dependsOn: ['structural-smoke'],
11
+ canRun(profile) {
12
+ return profile.contentTypes.length > 0;
13
+ },
14
+ async run(ctx) {
15
+ const results = [];
16
+ const { siteUrl, browserContext, profile } = ctx;
17
+ for (const ct of profile.contentTypes) {
18
+ const start = Date.now();
19
+ let page;
20
+ try {
21
+ page = await browserContext.newPage();
22
+ const addUrl = `${siteUrl}/node/add/${ct.id}`;
23
+ const response = await page.goto(addUrl, {
24
+ waitUntil: 'networkidle',
25
+ timeout: 30_000,
26
+ });
27
+ if (!response || response.status() >= 400) {
28
+ results.push({
29
+ plugin: 'field-interaction',
30
+ test: `form:${ct.id}`,
31
+ status: 'fail',
32
+ severity: 'critical',
33
+ message: `${addUrl} — HTTP ${response?.status() ?? 0}, cannot access node add form`,
34
+ duration: Date.now() - start,
35
+ });
36
+ continue;
37
+ }
38
+ // Fill the title field.
39
+ const title = `Bolt field-interaction test: ${ct.label}`;
40
+ await fillTitle(page, title, ct);
41
+ // Fill required fields.
42
+ const requiredFields = ct.fields.filter((f) => f.required);
43
+ const fieldErrors = [];
44
+ for (const field of requiredFields) {
45
+ try {
46
+ await fillField(page, field, siteUrl);
47
+ }
48
+ catch (err) {
49
+ fieldErrors.push(`${field.name} (${field.type}): ${err instanceof Error ? err.message.split('\n')[0] : String(err)}`);
50
+ // Close any open dialogs that may be blocking the page.
51
+ await closeMediaDialog(page);
52
+ }
53
+ }
54
+ if (fieldErrors.length > 0) {
55
+ results.push({
56
+ plugin: 'field-interaction',
57
+ test: `form:${ct.id}`,
58
+ status: 'warn',
59
+ severity: 'minor',
60
+ message: `${addUrl} — Could not fill ${fieldErrors.length} field(s): ${fieldErrors.join('; ')}`,
61
+ duration: Date.now() - start,
62
+ });
63
+ }
64
+ // Set status to unpublished before saving.
65
+ try {
66
+ await setUnpublished(page);
67
+ }
68
+ catch {
69
+ // Status widget may not be accessible — continue anyway.
70
+ }
71
+ // Submit the form.
72
+ const saveButton = page.locator('#edit-submit, input[value="Save"], button:text("Save")').first();
73
+ await saveButton.click();
74
+ // Wait for navigation or page update after save.
75
+ await page.waitForLoadState('networkidle', { timeout: 15_000 }).catch(() => { });
76
+ await page.waitForTimeout(2000);
77
+ // Check for success or error.
78
+ const hasError = await page.locator('.messages--error, .messages.error').count();
79
+ const hasSuccess = await page.locator('.messages--status, .messages.status').count();
80
+ const currentUrl = page.url();
81
+ const duration = Date.now() - start;
82
+ if (hasError > 0) {
83
+ const errorText = await page
84
+ .locator('.messages--error, .messages.error')
85
+ .first()
86
+ .textContent()
87
+ .catch(() => 'Unknown error');
88
+ results.push({
89
+ plugin: 'field-interaction',
90
+ test: `form:${ct.id}`,
91
+ status: 'fail',
92
+ severity: 'major',
93
+ message: `${addUrl} — Form validation error: ${(errorText ?? '').trim().slice(0, 200)}`,
94
+ duration,
95
+ });
96
+ }
97
+ else if (hasSuccess > 0 || !currentUrl.includes('/node/add/')) {
98
+ // Success — clean up the node we just created.
99
+ await cleanupNode(page, currentUrl, siteUrl);
100
+ results.push({
101
+ plugin: 'field-interaction',
102
+ test: `form:${ct.id}`,
103
+ status: 'pass',
104
+ severity: 'info',
105
+ message: `${ct.label} — form submit + save OK`,
106
+ duration,
107
+ });
108
+ }
109
+ else {
110
+ results.push({
111
+ plugin: 'field-interaction',
112
+ test: `form:${ct.id}`,
113
+ status: 'fail',
114
+ severity: 'major',
115
+ message: `${addUrl} — Form submitted but no success/error message detected`,
116
+ duration,
117
+ });
118
+ }
119
+ }
120
+ catch (err) {
121
+ results.push({
122
+ plugin: 'field-interaction',
123
+ test: `form:${ct.id}`,
124
+ status: 'fail',
125
+ severity: 'critical',
126
+ message: `Form test failed for ${ct.label}: ${err instanceof Error ? err.message : String(err)}`,
127
+ duration: Date.now() - start,
128
+ });
129
+ }
130
+ finally {
131
+ if (page)
132
+ await page.close();
133
+ }
134
+ }
135
+ return results;
136
+ },
137
+ };
138
+ /**
139
+ * Fill the node title field — handles both standard and custom title widgets.
140
+ */
141
+ async function fillTitle(page, title, ct) {
142
+ // Standard title field.
143
+ const titleInput = page.locator('#edit-title-0-value');
144
+ if (await titleInput.count() > 0) {
145
+ await titleInput.fill(title);
146
+ return;
147
+ }
148
+ // Some content types use a custom title field (e.g., auto_entitylabel).
149
+ // Look for any visible text input near the top of the form.
150
+ const firstTextInput = page.locator('form.node-form input[type="text"]').first();
151
+ if (await firstTextInput.count() > 0) {
152
+ await firstTextInput.fill(title);
153
+ }
154
+ }
155
+ /**
156
+ * Fill a single field based on its type.
157
+ */
158
+ async function fillField(page, field, siteUrl) {
159
+ const fieldName = field.name;
160
+ switch (field.type) {
161
+ case 'string':
162
+ case 'string_long':
163
+ await fillTextInput(page, fieldName, `Test value for ${field.label}`);
164
+ break;
165
+ case 'text_long':
166
+ case 'text_with_summary':
167
+ await fillTextarea(page, fieldName);
168
+ break;
169
+ case 'boolean':
170
+ // Checkboxes — just ensure it's in a valid state (no action needed).
171
+ break;
172
+ case 'integer':
173
+ case 'decimal':
174
+ case 'float':
175
+ await fillNumberInput(page, fieldName, 42);
176
+ break;
177
+ case 'email':
178
+ await fillTextInput(page, fieldName, 'test@bolt-test.example.com');
179
+ break;
180
+ case 'link':
181
+ await fillLinkField(page, fieldName);
182
+ break;
183
+ case 'datetime':
184
+ await fillDateField(page, fieldName);
185
+ break;
186
+ case 'image':
187
+ await uploadImage(page, fieldName);
188
+ break;
189
+ case 'entity_reference': {
190
+ const handler = field.settings?.handler;
191
+ if (handler?.includes('taxonomy_term')) {
192
+ await fillTaxonomyReference(page, fieldName);
193
+ }
194
+ else if (handler?.includes('media')) {
195
+ await fillMediaReference(page, fieldName);
196
+ }
197
+ else if (handler?.includes('node')) {
198
+ await fillNodeReference(page, fieldName);
199
+ }
200
+ else {
201
+ await fillAutocompleteReference(page, fieldName);
202
+ }
203
+ break;
204
+ }
205
+ case 'entity_reference_revisions':
206
+ // Paragraph fields — these are complex widgets. Skip for now,
207
+ // structural-smoke already tests paragraph creation via Drush.
208
+ break;
209
+ case 'metatag':
210
+ // Metatag fields are collapsed by default and rarely required.
211
+ break;
212
+ case 'layout_section':
213
+ // Layout builder — skip, handled separately.
214
+ break;
215
+ default:
216
+ // Unknown field type — skip with no error.
217
+ break;
218
+ }
219
+ }
220
+ /**
221
+ * Fill a text input field.
222
+ */
223
+ async function fillTextInput(page, fieldName, value) {
224
+ // Try standard Drupal field ID pattern.
225
+ const cssId = fieldToCssId(fieldName);
226
+ const input = page.locator(`#${cssId}-0-value, [name="${fieldName}[0][value]"]`).first();
227
+ if (await input.count() > 0 && await input.isVisible()) {
228
+ await input.fill(value);
229
+ return;
230
+ }
231
+ // Try label-based lookup.
232
+ const byLabel = page.getByLabel(new RegExp(fieldName.replace(/^field_/, '').replace(/_/g, ' '), 'i')).first();
233
+ if (await byLabel.count() > 0 && await byLabel.isVisible()) {
234
+ await byLabel.fill(value);
235
+ }
236
+ }
237
+ /**
238
+ * Fill a textarea field (may be plain or CKEditor).
239
+ */
240
+ async function fillTextarea(page, fieldName) {
241
+ const cssId = fieldToCssId(fieldName);
242
+ // Check for CKEditor 5.
243
+ const ckEditor = page.locator(`#${cssId}-0-value + .ck-editor, #${cssId}-wrapper .ck-editor`).first();
244
+ if (await ckEditor.count() > 0) {
245
+ const editable = ckEditor.locator('.ck-editor__editable');
246
+ if (await editable.count() > 0) {
247
+ await editable.click();
248
+ await editable.fill('Bolt test content.');
249
+ return;
250
+ }
251
+ }
252
+ // Plain textarea.
253
+ const textarea = page.locator(`#${cssId}-0-value, textarea[name="${fieldName}[0][value]"], #${cssId}-wrapper textarea`).first();
254
+ if (await textarea.count() > 0 && await textarea.isVisible()) {
255
+ await textarea.fill('Bolt test content.');
256
+ }
257
+ }
258
+ /**
259
+ * Fill a number input.
260
+ */
261
+ async function fillNumberInput(page, fieldName, value) {
262
+ const cssId = fieldToCssId(fieldName);
263
+ const input = page.locator(`#${cssId}-0-value, [name="${fieldName}[0][value]"]`).first();
264
+ if (await input.count() > 0 && await input.isVisible()) {
265
+ await input.fill(String(value));
266
+ }
267
+ }
268
+ /**
269
+ * Fill a link field.
270
+ */
271
+ async function fillLinkField(page, fieldName) {
272
+ const cssId = fieldToCssId(fieldName);
273
+ const uriInput = page.locator(`#${cssId}-0-uri, [name="${fieldName}[0][uri]"]`).first();
274
+ if (await uriInput.count() > 0 && await uriInput.isVisible()) {
275
+ await uriInput.fill('https://example.com');
276
+ }
277
+ }
278
+ /**
279
+ * Fill a date field.
280
+ */
281
+ async function fillDateField(page, fieldName) {
282
+ const cssId = fieldToCssId(fieldName);
283
+ const dateInput = page.locator(`#${cssId}-0-value-date, [name="${fieldName}[0][value][date]"]`).first();
284
+ if (await dateInput.count() > 0 && await dateInput.isVisible()) {
285
+ await dateInput.fill('2026-01-15');
286
+ }
287
+ const timeInput = page.locator(`#${cssId}-0-value-time, [name="${fieldName}[0][value][time]"]`).first();
288
+ if (await timeInput.count() > 0 && await timeInput.isVisible()) {
289
+ await timeInput.fill('10:00:00');
290
+ }
291
+ }
292
+ /**
293
+ * Upload an image to a file/image field (handles focal_point widget too).
294
+ */
295
+ async function uploadImage(page, fieldName) {
296
+ const cssId = fieldToCssId(fieldName);
297
+ const fileInput = page.locator(`#${cssId}-0-upload, #${cssId}-wrapper input[type="file"], [name="files[${fieldName}_0]"]`).first();
298
+ if (await fileInput.count() > 0) {
299
+ // Create a minimal 1x1 PNG in memory.
300
+ const pngBuffer = createMinimalPng();
301
+ await fileInput.setInputFiles({
302
+ name: 'bolt-test.png',
303
+ mimeType: 'image/png',
304
+ buffer: pngBuffer,
305
+ });
306
+ // Wait for upload to complete (Drupal AJAX).
307
+ await page.waitForTimeout(3000);
308
+ // Fill alt text if required.
309
+ const altInput = page.locator(`#${cssId}-0-alt, [name="${fieldName}[0][alt]"]`).first();
310
+ if (await altInput.count() > 0 && await altInput.isVisible()) {
311
+ await altInput.fill('Bolt test image');
312
+ }
313
+ // Handle focal_point widget — set the hidden focal point value.
314
+ const focalInput = page.locator(`#${cssId}-0-focal-point, [name="${fieldName}[0][focal_point]"]`).first();
315
+ if (await focalInput.count() > 0) {
316
+ await focalInput.evaluate((el) => {
317
+ el.value = '50,50';
318
+ });
319
+ }
320
+ // Also try clicking the image preview to set focal point (some themes require it).
321
+ const focalPreview = page.locator(`#${cssId}-wrapper .focal-point-wrapper, .focal-point`).first();
322
+ if (await focalPreview.count() > 0 && await focalPreview.isVisible()) {
323
+ const box = await focalPreview.boundingBox();
324
+ if (box) {
325
+ // Click center of the image.
326
+ await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2);
327
+ await page.waitForTimeout(500);
328
+ }
329
+ }
330
+ }
331
+ }
332
+ /**
333
+ * Fill a taxonomy term entity reference (autocomplete, select, or tagify widget).
334
+ */
335
+ async function fillTaxonomyReference(page, fieldName) {
336
+ const cssId = fieldToCssId(fieldName);
337
+ // Try tagify widget first (used by contrib tagify module).
338
+ const tagifyInput = page.locator(`#${cssId}-wrapper .tagify__input, #${cssId}-wrapper tags .tagify__input`).first();
339
+ if (await tagifyInput.count() > 0 && await tagifyInput.isVisible()) {
340
+ await tagifyInput.click();
341
+ await tagifyInput.pressSequentially('a', { delay: 100 });
342
+ await page.waitForTimeout(1500);
343
+ // Pick the first suggestion from the tagify dropdown.
344
+ const tagifySuggestion = page.locator('.tagify__dropdown__item').first();
345
+ if (await tagifySuggestion.count() > 0) {
346
+ await tagifySuggestion.click();
347
+ await page.waitForTimeout(500);
348
+ }
349
+ return;
350
+ }
351
+ // Try select widget.
352
+ const select = page.locator(`#${cssId}, select[name="${fieldName}"]`).first();
353
+ if (await select.count() > 0 && await select.isVisible()) {
354
+ const tag = await select.evaluate((el) => el.tagName.toLowerCase());
355
+ if (tag === 'select') {
356
+ const options = await select.locator('option').all();
357
+ for (const opt of options) {
358
+ const val = await opt.getAttribute('value');
359
+ if (val && val !== '' && val !== '_none') {
360
+ await select.selectOption(val);
361
+ return;
362
+ }
363
+ }
364
+ }
365
+ }
366
+ // Try standard autocomplete input.
367
+ const autocomplete = page.locator(`#${cssId}-0-target-id, [name="${fieldName}[0][target_id]"]`).first();
368
+ if (await autocomplete.count() > 0 && await autocomplete.isVisible()) {
369
+ await autocomplete.fill('a');
370
+ await page.waitForTimeout(1000);
371
+ const suggestion = page.locator('.ui-autocomplete .ui-menu-item, .ui-autocomplete li').first();
372
+ if (await suggestion.count() > 0) {
373
+ await suggestion.click();
374
+ }
375
+ else {
376
+ await autocomplete.fill('');
377
+ }
378
+ }
379
+ }
380
+ /**
381
+ * Fill a media entity reference (media library widget).
382
+ */
383
+ async function fillMediaReference(page, fieldName) {
384
+ const cssId = fieldToCssId(fieldName);
385
+ // Look for "Add media" button (media library widget).
386
+ // Drupal renders this as a button with various possible selectors.
387
+ const addMediaBtn = page.locator([
388
+ `#${cssId}-media-library-open-button`,
389
+ `[data-drupal-selector="${cssId}-media-library-open-button"]`,
390
+ `[name="${fieldName}_open_button"]`,
391
+ `#${cssId}-wrapper input[value="Add media"]`,
392
+ `#${cssId}-wrapper button:has-text("Add media")`,
393
+ `.field--name-${fieldName.replace(/_/g, '-')} input[value="Add media"]`,
394
+ `.field--name-${fieldName.replace(/_/g, '-')} button:has-text("Add media")`,
395
+ ].join(', ')).first();
396
+ if (await addMediaBtn.count() > 0 && await addMediaBtn.isVisible()) {
397
+ await addMediaBtn.click();
398
+ // Wait for media library modal/dialog.
399
+ try {
400
+ await page.waitForSelector('.media-library-widget-modal, .ui-dialog, [id*="media-library"]', { timeout: 10_000 });
401
+ }
402
+ catch {
403
+ return;
404
+ }
405
+ // Wait for the dialog content to load.
406
+ await page.waitForTimeout(2000);
407
+ await page.waitForTimeout(1000);
408
+ // Try to select an existing media item.
409
+ const mediaItem = page.locator([
410
+ '.media-library-widget-modal .views-row input[type="checkbox"]',
411
+ '.media-library-item input[type="checkbox"]',
412
+ '.ui-dialog .views-row input[type="checkbox"]',
413
+ '.ui-dialog .media-library-item input[type="checkbox"]',
414
+ ].join(', ')).first();
415
+ if (await mediaItem.count() > 0 && await mediaItem.isVisible()) {
416
+ // Click the checkbox (not .check() which may not trigger JS events).
417
+ await mediaItem.click();
418
+ await page.waitForTimeout(1500);
419
+ // The "Insert selected" button may be in the dialog button pane or form actions.
420
+ // Try multiple selectors and use force:true to bypass overlay issues.
421
+ const insertBtn = page.locator('.ui-dialog-buttonpane button:has-text("Insert"), ' +
422
+ 'button.media-library-select').first();
423
+ try {
424
+ await insertBtn.waitFor({ state: 'visible', timeout: 5_000 });
425
+ await insertBtn.click({ timeout: 5_000 });
426
+ // Wait for modal to close.
427
+ await page.waitForTimeout(3000);
428
+ }
429
+ catch {
430
+ // Try force click as fallback.
431
+ try {
432
+ await insertBtn.click({ force: true, timeout: 3_000 });
433
+ await page.waitForTimeout(3000);
434
+ }
435
+ catch {
436
+ await closeMediaDialog(page);
437
+ }
438
+ }
439
+ }
440
+ else {
441
+ await closeMediaDialog(page);
442
+ }
443
+ }
444
+ }
445
+ /**
446
+ * Close any open media library dialog.
447
+ */
448
+ async function closeMediaDialog(page) {
449
+ const closeBtn = page.locator('.ui-dialog-titlebar-close').first();
450
+ if (await closeBtn.count() > 0 && await closeBtn.isVisible()) {
451
+ await closeBtn.click();
452
+ await page.waitForSelector('.ui-dialog.media-library-widget-modal', { state: 'hidden', timeout: 5_000 })
453
+ .catch(() => { });
454
+ await page.waitForTimeout(500);
455
+ }
456
+ }
457
+ /**
458
+ * Fill a node entity reference (autocomplete).
459
+ */
460
+ async function fillNodeReference(page, fieldName) {
461
+ await fillAutocompleteReference(page, fieldName);
462
+ }
463
+ /**
464
+ * Fill a generic autocomplete entity reference (handles tagify too).
465
+ */
466
+ async function fillAutocompleteReference(page, fieldName) {
467
+ const cssId = fieldToCssId(fieldName);
468
+ // Try tagify widget first.
469
+ const tagifyInput = page.locator(`#${cssId}-wrapper .tagify__input, #${cssId}-wrapper tags .tagify__input`).first();
470
+ if (await tagifyInput.count() > 0 && await tagifyInput.isVisible()) {
471
+ await tagifyInput.click();
472
+ await tagifyInput.pressSequentially('a', { delay: 100 });
473
+ await page.waitForTimeout(1500);
474
+ const tagifySuggestion = page.locator('.tagify__dropdown__item').first();
475
+ if (await tagifySuggestion.count() > 0) {
476
+ await tagifySuggestion.click();
477
+ await page.waitForTimeout(500);
478
+ }
479
+ return;
480
+ }
481
+ // Standard autocomplete.
482
+ const autocomplete = page.locator(`#${cssId}-0-target-id, [name="${fieldName}[0][target_id]"]`).first();
483
+ if (await autocomplete.count() > 0 && await autocomplete.isVisible()) {
484
+ await autocomplete.fill('a');
485
+ await page.waitForTimeout(1000);
486
+ const suggestion = page.locator('.ui-autocomplete .ui-menu-item, .ui-autocomplete li').first();
487
+ if (await suggestion.count() > 0) {
488
+ await suggestion.click();
489
+ }
490
+ }
491
+ }
492
+ /**
493
+ * Set the node status to unpublished.
494
+ */
495
+ async function setUnpublished(page) {
496
+ // Drupal's publish status is often in a details/sidebar element.
497
+ const statusCheckbox = page.locator('#edit-status-value, [name="status[value]"]').first();
498
+ if (await statusCheckbox.count() > 0 && await statusCheckbox.isVisible()) {
499
+ await statusCheckbox.uncheck();
500
+ return;
501
+ }
502
+ // May need to expand the "Promotion options" or "Publishing options" details.
503
+ const publishDetails = page.locator('details:has(#edit-status-value)').first();
504
+ if (await publishDetails.count() > 0) {
505
+ const summary = publishDetails.locator('summary').first();
506
+ if (await summary.count() > 0) {
507
+ await summary.click();
508
+ await page.waitForTimeout(300);
509
+ const checkbox = page.locator('#edit-status-value').first();
510
+ if (await checkbox.count() > 0) {
511
+ await checkbox.uncheck();
512
+ }
513
+ }
514
+ }
515
+ }
516
+ /**
517
+ * Clean up a just-created node by deleting it.
518
+ */
519
+ async function cleanupNode(page, currentUrl, siteUrl) {
520
+ try {
521
+ // Extract node ID from URL (e.g., /node/123 or /alias → check for edit tab).
522
+ const editUrl = currentUrl.includes('/node/')
523
+ ? currentUrl.replace(/\/?$/, '/delete')
524
+ : null;
525
+ if (editUrl) {
526
+ await page.goto(editUrl, { waitUntil: 'networkidle', timeout: 10_000 });
527
+ const deleteButton = page.locator('#edit-submit, input[value="Delete"], button:text("Delete")').first();
528
+ if (await deleteButton.count() > 0) {
529
+ await deleteButton.click();
530
+ await page.waitForTimeout(2000);
531
+ }
532
+ }
533
+ }
534
+ catch {
535
+ // Cleanup failure is non-fatal — node will be unpublished anyway.
536
+ }
537
+ }
538
+ /**
539
+ * Convert a Drupal field name to CSS ID prefix.
540
+ * e.g., field_meta_description → edit-field-meta-description
541
+ */
542
+ function fieldToCssId(fieldName) {
543
+ return 'edit-' + fieldName.replace(/_/g, '-');
544
+ }
545
+ /**
546
+ * Create a minimal valid 1×1 red PNG (67 bytes).
547
+ */
548
+ function createMinimalPng() {
549
+ // PNG signature + IHDR + IDAT + IEND for a 1x1 red pixel.
550
+ const png = Buffer.from([
551
+ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, // PNG signature
552
+ 0x00, 0x00, 0x00, 0x0d, // IHDR length
553
+ 0x49, 0x48, 0x44, 0x52, // IHDR
554
+ 0x00, 0x00, 0x00, 0x01, // width: 1
555
+ 0x00, 0x00, 0x00, 0x01, // height: 1
556
+ 0x08, 0x02, // bit depth: 8, color type: RGB
557
+ 0x00, 0x00, 0x00, // compression, filter, interlace
558
+ 0x90, 0x77, 0x53, 0xde, // CRC
559
+ 0x00, 0x00, 0x00, 0x0c, // IDAT length
560
+ 0x49, 0x44, 0x41, 0x54, // IDAT
561
+ 0x08, 0xd7, 0x63, 0xf8, 0xcf, 0xc0, 0x00, 0x00, // compressed data
562
+ 0x00, 0x02, 0x00, 0x01, // ...
563
+ 0xe2, 0x21, 0xbc, 0x33, // CRC
564
+ 0x00, 0x00, 0x00, 0x00, // IEND length
565
+ 0x49, 0x45, 0x4e, 0x44, // IEND
566
+ 0xae, 0x42, 0x60, 0x82, // CRC
567
+ ]);
568
+ return png;
569
+ }
570
+ //# sourceMappingURL=field-interaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-interaction.js","sourceRoot":"","sources":["../../src/plugins/field-interaction.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Plugin registry — built-in test plugins.
3
+ */
4
+ import type { TestPlugin } from '../types.js';
5
+ export declare function registerPlugin(plugin: TestPlugin): void;
6
+ export declare function getPlugins(): TestPlugin[];
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Plugin registry — built-in test plugins.
3
+ */
4
+ import { structuralSmokePlugin } from './structural-smoke.js';
5
+ import { browserSmokePlugin } from './browser-smoke.js';
6
+ import { accessibilityPlugin } from './accessibility.js';
7
+ import { visualRegressionPlugin } from './visual-regression.js';
8
+ import { fieldInteractionPlugin } from './field-interaction.js';
9
+ import { mediaBrowserPlugin } from './media-browser.js';
10
+ import { wysiwygPlugin } from './wysiwyg.js';
11
+ import { linkitPlugin } from './linkit.js';
12
+ const plugins = [
13
+ structuralSmokePlugin,
14
+ browserSmokePlugin,
15
+ accessibilityPlugin,
16
+ visualRegressionPlugin,
17
+ fieldInteractionPlugin,
18
+ mediaBrowserPlugin,
19
+ wysiwygPlugin,
20
+ linkitPlugin,
21
+ ];
22
+ export function registerPlugin(plugin) {
23
+ plugins.push(plugin);
24
+ }
25
+ export function getPlugins() {
26
+ return [...plugins];
27
+ }
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,OAAO,GAAiB;IAC5B,qBAAqB;IACrB,kBAAkB;IAClB,mBAAmB;IACnB,sBAAsB;IACtB,sBAAsB;IACtB,kBAAkB;IAClB,aAAa;IACb,YAAY;CACb,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,MAAkB;IAC/C,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * linkit plugin — tests the Linkit autocomplete integration with CKEditor 5.
3
+ *
4
+ * Verifies: link dialog opens, Linkit autocomplete field is present,
5
+ * typing triggers suggestions, selecting a suggestion populates the URL.
6
+ */
7
+ import type { TestPlugin } from '../types.js';
8
+ export declare const linkitPlugin: TestPlugin;