@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 @@
1
+ {"version":3,"file":"accessibility.js","sourceRoot":"","sources":["../../src/plugins/accessibility.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * browser-smoke plugin — visits representative URLs with Playwright,
3
+ * checks for HTTP errors, JS console errors, and broken images.
4
+ */
5
+ import type { TestPlugin } from '../types.js';
6
+ export declare const browserSmokePlugin: TestPlugin;
@@ -0,0 +1,331 @@
1
+ /**
2
+ * browser-smoke plugin — visits representative URLs with Playwright,
3
+ * checks for HTTP errors, JS console errors, and broken images.
4
+ */
5
+ import { mkdirSync } from 'fs';
6
+ import { join } from 'path';
7
+ export const browserSmokePlugin = {
8
+ name: 'browser-smoke',
9
+ description: 'Visit representative URLs, check for JS errors, broken images, HTTP errors',
10
+ readOnly: true,
11
+ needsGeneratedContent: false,
12
+ canRun(profile) {
13
+ return profile.representativeUrls.length > 0;
14
+ },
15
+ async run(ctx) {
16
+ const results = [];
17
+ const { siteUrl, browserContext, profile, options } = ctx;
18
+ for (const rep of profile.representativeUrls) {
19
+ const start = Date.now();
20
+ const fullUrl = rep.url.startsWith('http') ? rep.url : siteUrl + rep.url;
21
+ const consoleErrors = [];
22
+ let httpStatus = 0;
23
+ let page;
24
+ try {
25
+ page = await browserContext.newPage();
26
+ // Collect JS console errors.
27
+ page.on('console', (msg) => {
28
+ if (msg.type() === 'error') {
29
+ consoleErrors.push(msg.text());
30
+ }
31
+ });
32
+ // Collect uncaught JS exceptions (TypeError, ReferenceError, etc.).
33
+ const uncaughtErrors = [];
34
+ page.on('pageerror', (error) => {
35
+ uncaughtErrors.push(error.message);
36
+ });
37
+ // Navigate.
38
+ const response = await page.goto(fullUrl, {
39
+ waitUntil: 'networkidle',
40
+ timeout: 30_000,
41
+ });
42
+ httpStatus = response?.status() ?? 0;
43
+ // Wait for any AJAX to settle.
44
+ try {
45
+ await page.waitForFunction(() => !window.jQuery || window.jQuery.active === 0, { timeout: 5_000 });
46
+ }
47
+ catch {
48
+ // jQuery may not be present or AJAX may not settle — non-fatal.
49
+ }
50
+ // Check for broken images — include context so you can find them on the page.
51
+ const brokenImages = await page.evaluate(() => {
52
+ const images = Array.from(document.querySelectorAll('img'));
53
+ return images
54
+ .filter((img) => img.complete && img.naturalWidth === 0 && img.src && !img.src.startsWith('data:'))
55
+ .map((img) => {
56
+ // Build a location hint: alt text, closest identifiable parent, CSS classes.
57
+ const alt = img.alt || null;
58
+ const classes = img.className || null;
59
+ // Walk up to find a meaningful parent (field, block, region, paragraph).
60
+ const parent = img.closest('[class*="field--"], [class*="block-"], [class*="paragraph--"], [class*="region-"], [class*="node--"]');
61
+ const parentClass = parent
62
+ ? Array.from(parent.classList).find(c => /^(field--|block-|paragraph--|region-|node--)/.test(c)) ?? parent.classList[0]
63
+ : null;
64
+ const closestLink = img.closest('a');
65
+ const linkText = closestLink?.textContent?.trim().slice(0, 50) || null;
66
+ const parts = [];
67
+ if (alt)
68
+ parts.push(`alt="${alt}"`);
69
+ if (linkText)
70
+ parts.push(`near "${linkText}"`);
71
+ if (parentClass)
72
+ parts.push(`in .${parentClass}`);
73
+ if (classes)
74
+ parts.push(`class="${classes}"`);
75
+ return {
76
+ src: img.src,
77
+ context: parts.length > 0 ? parts.join(', ') : 'no identifying attributes',
78
+ };
79
+ });
80
+ });
81
+ const duration = Date.now() - start;
82
+ // Build result.
83
+ const issues = [];
84
+ if (httpStatus >= 400) {
85
+ issues.push(`HTTP ${httpStatus}`);
86
+ }
87
+ // Filter out noisy/irrelevant console errors.
88
+ const significantErrors = consoleErrors.filter((e) => !isIgnorableConsoleError(e));
89
+ if (significantErrors.length > 0) {
90
+ issues.push(`${significantErrors.length} JS error(s): ${significantErrors[0].slice(0, 150)}`);
91
+ }
92
+ // Uncaught exceptions (TypeError, ReferenceError, SyntaxError, etc.).
93
+ const significantUncaught = uncaughtErrors.filter((e) => !isIgnorableConsoleError(e));
94
+ if (significantUncaught.length > 0) {
95
+ issues.push(`${significantUncaught.length} uncaught JS exception(s): ${significantUncaught[0].slice(0, 150)}`);
96
+ }
97
+ if (brokenImages.length > 0) {
98
+ const details = brokenImages
99
+ .map((img) => `${img.src} (${img.context})`)
100
+ .join('; ');
101
+ issues.push(`${brokenImages.length} broken image(s): ${details}`);
102
+ }
103
+ // Check for on-screen PHP errors, warnings, and Drupal error messages.
104
+ const pageErrors = await page.evaluate(() => {
105
+ const phpErrors = [];
106
+ const drupalErrors = [];
107
+ // Scan text nodes for PHP error patterns.
108
+ const bodyText = document.body?.innerText || '';
109
+ const phpPatterns = [
110
+ /(?:Fatal error|Parse error|Syntax error):.*?(?:in \/\S+|$)/gim,
111
+ /(?:Warning|Notice|Deprecated):.*?(?:in \/\S+|$)/gim,
112
+ /Recoverable fatal error:.*?(?:in \/\S+|$)/gim,
113
+ /The website encountered an unexpected error/gi,
114
+ /Uncaught PHP Exception/gi,
115
+ /PDOException:/gi,
116
+ ];
117
+ for (const pattern of phpPatterns) {
118
+ const matches = bodyText.match(pattern);
119
+ if (matches) {
120
+ phpErrors.push(...matches.map(m => m.trim().slice(0, 200)));
121
+ }
122
+ }
123
+ // Check for Drupal error message banners.
124
+ const errorMsgs = document.querySelectorAll('.messages--error, .messages.error, [data-drupal-messages] .messages--error');
125
+ for (const el of errorMsgs) {
126
+ const text = el.innerText?.trim().slice(0, 200);
127
+ if (text)
128
+ drupalErrors.push(text);
129
+ }
130
+ return { phpErrors, drupalErrors };
131
+ });
132
+ if (pageErrors.phpErrors.length > 0) {
133
+ issues.push(`${pageErrors.phpErrors.length} PHP error(s): ${pageErrors.phpErrors[0]}`);
134
+ }
135
+ if (pageErrors.drupalErrors.length > 0) {
136
+ issues.push(`${pageErrors.drupalErrors.length} Drupal error(s): ${pageErrors.drupalErrors[0]}`);
137
+ }
138
+ // For view pages, check that the view rendered content (not empty).
139
+ if (rep.source === 'view') {
140
+ const viewStatus = await page.evaluate(() => {
141
+ const viewWrapper = document.querySelector('[class*="view-"][class*="view-id-"]');
142
+ const viewContent = document.querySelector('.view-content, .views-row, .views-table');
143
+ const emptyMessage = document.querySelector('.view-empty');
144
+ return {
145
+ hasWrapper: !!viewWrapper,
146
+ hasContent: !!viewContent,
147
+ isEmpty: !!emptyMessage,
148
+ };
149
+ });
150
+ if (!viewStatus.hasContent) {
151
+ if (viewStatus.isEmpty) {
152
+ issues.push('View rendered but has no results (empty view)');
153
+ }
154
+ else if (viewStatus.hasWrapper) {
155
+ // View wrapper exists but no content rows — likely just no data.
156
+ issues.push('View rendered with no results and no empty text configured');
157
+ }
158
+ else if (httpStatus < 400) {
159
+ // Page loaded OK but no view markup at all — view may be
160
+ // embedded or using non-standard markup.
161
+ issues.push('View markup not found on page — may use non-standard template or have no data');
162
+ }
163
+ else {
164
+ // 4xx/5xx — already flagged by HTTP status, skip redundant message.
165
+ }
166
+ }
167
+ }
168
+ if (issues.length > 0) {
169
+ // Capture screenshot on failure.
170
+ let screenshot;
171
+ if (options.screenshots) {
172
+ mkdirSync(options.screenshots, { recursive: true });
173
+ const filename = `browser-smoke-${slugify(rep.label)}-${Date.now()}.png`;
174
+ screenshot = join(options.screenshots, filename);
175
+ await page.screenshot({ path: screenshot, fullPage: true });
176
+ }
177
+ const severity = httpStatus >= 500 ? 'critical'
178
+ : pageErrors.phpErrors.length > 0 ? 'critical'
179
+ : significantUncaught.length > 0 ? 'major'
180
+ : httpStatus >= 400 ? 'major'
181
+ : significantErrors.length > 0 ? 'major'
182
+ : pageErrors.drupalErrors.length > 0 ? 'major'
183
+ : 'minor';
184
+ results.push({
185
+ plugin: 'browser-smoke',
186
+ test: `visit:${rep.label}`,
187
+ status: 'fail',
188
+ severity,
189
+ message: `${fullUrl} — ${issues.join('; ')}`,
190
+ screenshot,
191
+ duration,
192
+ });
193
+ }
194
+ else {
195
+ results.push({
196
+ plugin: 'browser-smoke',
197
+ test: `visit:${rep.label}`,
198
+ status: 'pass',
199
+ severity: 'info',
200
+ message: `${rep.label} — HTTP ${httpStatus}, no errors`,
201
+ duration,
202
+ });
203
+ }
204
+ }
205
+ catch (err) {
206
+ const duration = Date.now() - start;
207
+ results.push({
208
+ plugin: 'browser-smoke',
209
+ test: `visit:${rep.label}`,
210
+ status: 'fail',
211
+ severity: 'critical',
212
+ message: `Navigation failed for ${rep.label}: ${err instanceof Error ? err.message : String(err)}`,
213
+ duration,
214
+ });
215
+ }
216
+ finally {
217
+ if (page) {
218
+ await page.close();
219
+ }
220
+ }
221
+ }
222
+ // Mobile viewport pass — catch JS errors triggered by responsive code paths.
223
+ const MOBILE_WIDTH = 375;
224
+ const MOBILE_HEIGHT = 812;
225
+ for (const rep of profile.representativeUrls) {
226
+ const start = Date.now();
227
+ const fullUrl = rep.url.startsWith('http') ? rep.url : siteUrl + rep.url;
228
+ const mobileConsoleErrors = [];
229
+ const mobileUncaughtErrors = [];
230
+ let page;
231
+ try {
232
+ page = await browserContext.newPage();
233
+ await page.setViewportSize({ width: MOBILE_WIDTH, height: MOBILE_HEIGHT });
234
+ page.on('console', (msg) => {
235
+ if (msg.type() === 'error') {
236
+ mobileConsoleErrors.push(msg.text());
237
+ }
238
+ });
239
+ page.on('pageerror', (error) => {
240
+ mobileUncaughtErrors.push(error.message);
241
+ });
242
+ await page.goto(fullUrl, { waitUntil: 'networkidle', timeout: 30_000 });
243
+ // Wait for any AJAX/responsive JS to settle.
244
+ try {
245
+ await page.waitForFunction(() => !window.jQuery || window.jQuery.active === 0, { timeout: 5_000 });
246
+ }
247
+ catch {
248
+ // Non-fatal.
249
+ }
250
+ const duration = Date.now() - start;
251
+ const significantConsole = mobileConsoleErrors.filter((e) => !isIgnorableConsoleError(e));
252
+ const significantUncaught = mobileUncaughtErrors.filter((e) => !isIgnorableConsoleError(e));
253
+ const issues = [];
254
+ if (significantConsole.length > 0) {
255
+ issues.push(`${significantConsole.length} JS error(s): ${significantConsole[0].slice(0, 150)}`);
256
+ }
257
+ if (significantUncaught.length > 0) {
258
+ issues.push(`${significantUncaught.length} uncaught JS exception(s): ${significantUncaught[0].slice(0, 150)}`);
259
+ }
260
+ if (issues.length > 0) {
261
+ let screenshot;
262
+ if (options.screenshots) {
263
+ mkdirSync(options.screenshots, { recursive: true });
264
+ const filename = `browser-smoke-mobile-${slugify(rep.label)}-${Date.now()}.png`;
265
+ screenshot = join(options.screenshots, filename);
266
+ await page.screenshot({ path: screenshot, fullPage: true });
267
+ }
268
+ results.push({
269
+ plugin: 'browser-smoke',
270
+ test: `visit-mobile:${rep.label}`,
271
+ status: 'fail',
272
+ severity: significantUncaught.length > 0 ? 'major' : 'major',
273
+ message: `${fullUrl} (mobile ${MOBILE_WIDTH}px) — ${issues.join('; ')}`,
274
+ screenshot,
275
+ duration,
276
+ });
277
+ }
278
+ else {
279
+ results.push({
280
+ plugin: 'browser-smoke',
281
+ test: `visit-mobile:${rep.label}`,
282
+ status: 'pass',
283
+ severity: 'info',
284
+ message: `${rep.label} — mobile ${MOBILE_WIDTH}px, no JS errors`,
285
+ duration,
286
+ });
287
+ }
288
+ }
289
+ catch (err) {
290
+ const duration = Date.now() - start;
291
+ results.push({
292
+ plugin: 'browser-smoke',
293
+ test: `visit-mobile:${rep.label}`,
294
+ status: 'fail',
295
+ severity: 'critical',
296
+ message: `Mobile navigation failed for ${rep.label}: ${err instanceof Error ? err.message : String(err)}`,
297
+ duration,
298
+ });
299
+ }
300
+ finally {
301
+ if (page) {
302
+ await page.close();
303
+ }
304
+ }
305
+ }
306
+ return results;
307
+ },
308
+ };
309
+ /**
310
+ * Filter out console errors that are browser noise, not application bugs.
311
+ */
312
+ function isIgnorableConsoleError(msg) {
313
+ const ignorable = [
314
+ 'favicon.ico',
315
+ 'net::ERR_',
316
+ 'DevTools',
317
+ 'third-party cookie',
318
+ 'Permissions-Policy',
319
+ 'download the React DevTools',
320
+ 'the server responded with a status of 404',
321
+ 'ERR_BLOCKED_BY_CLIENT', // Ad blockers
322
+ ];
323
+ return ignorable.some((pattern) => msg.includes(pattern));
324
+ }
325
+ function slugify(str) {
326
+ return str
327
+ .toLowerCase()
328
+ .replace(/[^a-z0-9]+/g, '-')
329
+ .replace(/^-|-$/g, '');
330
+ }
331
+ //# sourceMappingURL=browser-smoke.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-smoke.js","sourceRoot":"","sources":["../../src/plugins/browser-smoke.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
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
+ import type { TestPlugin } from '../types.js';
6
+ export declare const fieldInteractionPlugin: TestPlugin;