@memberjunction/react-test-harness 2.71.0 → 2.73.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.
package/README.md CHANGED
@@ -680,6 +680,14 @@ const result = await harness.evaluateInPage(() => {
680
680
  const screenshot = await harness.screenshot('./output.png');
681
681
  ```
682
682
 
683
+ ## Limitations
684
+
685
+ Due to the architecture of the test harness (Node.js controlling a browser via Playwright), there are some important limitations to be aware of. See [docs/limitations.md](./docs/limitations.md) for details on:
686
+
687
+ - Serialization requirements between Node.js and browser
688
+ - BaseEntity method access limitations
689
+ - Differences between test and production environments
690
+
683
691
  ## Best Practices
684
692
 
685
693
  1. **Always close the harness** after tests to free resources:
package/dist/index.d.ts CHANGED
@@ -2,4 +2,5 @@ export { ReactTestHarness, TestHarnessOptions } from './lib/test-harness';
2
2
  export { BrowserManager, BrowserContextOptions } from './lib/browser-context';
3
3
  export { ComponentRunner, ComponentExecutionOptions, ComponentExecutionResult, ComponentSpec } from './lib/component-runner';
4
4
  export { AssertionHelpers } from './lib/assertion-helpers';
5
+ export { ComponentLinter, LintResult, Violation, FixSuggestion, ComponentType } from './lib/component-linter';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC7H,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC7H,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AssertionHelpers = exports.ComponentRunner = exports.BrowserManager = exports.ReactTestHarness = void 0;
3
+ exports.ComponentLinter = exports.AssertionHelpers = exports.ComponentRunner = exports.BrowserManager = exports.ReactTestHarness = void 0;
4
4
  var test_harness_1 = require("./lib/test-harness");
5
5
  Object.defineProperty(exports, "ReactTestHarness", { enumerable: true, get: function () { return test_harness_1.ReactTestHarness; } });
6
6
  var browser_context_1 = require("./lib/browser-context");
@@ -9,4 +9,6 @@ var component_runner_1 = require("./lib/component-runner");
9
9
  Object.defineProperty(exports, "ComponentRunner", { enumerable: true, get: function () { return component_runner_1.ComponentRunner; } });
10
10
  var assertion_helpers_1 = require("./lib/assertion-helpers");
11
11
  Object.defineProperty(exports, "AssertionHelpers", { enumerable: true, get: function () { return assertion_helpers_1.AssertionHelpers; } });
12
+ var component_linter_1 = require("./lib/component-linter");
13
+ Object.defineProperty(exports, "ComponentLinter", { enumerable: true, get: function () { return component_linter_1.ComponentLinter; } });
12
14
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mDAA0E;AAAjE,gHAAA,gBAAgB,OAAA;AACzB,yDAA8E;AAArE,iHAAA,cAAc,OAAA;AACvB,2DAA6H;AAApH,mHAAA,eAAe,OAAA;AACxB,6DAA2D;AAAlD,qHAAA,gBAAgB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mDAA0E;AAAjE,gHAAA,gBAAgB,OAAA;AACzB,yDAA8E;AAArE,iHAAA,cAAc,OAAA;AACvB,2DAA6H;AAApH,mHAAA,eAAe,OAAA;AACxB,6DAA2D;AAAlD,qHAAA,gBAAgB,OAAA;AACzB,2DAA8G;AAArG,mHAAA,eAAe,OAAA"}
@@ -0,0 +1,26 @@
1
+ export interface LintResult {
2
+ success: boolean;
3
+ violations: Violation[];
4
+ suggestions: FixSuggestion[];
5
+ }
6
+ export interface Violation {
7
+ rule: string;
8
+ severity: 'error' | 'warning';
9
+ line: number;
10
+ column: number;
11
+ message: string;
12
+ code?: string;
13
+ }
14
+ export interface FixSuggestion {
15
+ violation: string;
16
+ suggestion: string;
17
+ example?: string;
18
+ }
19
+ export type ComponentType = 'root' | 'child';
20
+ export declare class ComponentLinter {
21
+ private static childComponentRules;
22
+ private static rootComponentRules;
23
+ static lintComponent(code: string, componentType: ComponentType, componentName: string): Promise<LintResult>;
24
+ private static generateFixSuggestions;
25
+ }
26
+ //# sourceMappingURL=component-linter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-linter.d.ts","sourceRoot":"","sources":["../../src/lib/component-linter.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,WAAW,EAAE,aAAa,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC;AAO7C,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAyLhC;IAEF,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAgK/B;WAEkB,aAAa,CAC/B,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,aAAa,EAC5B,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,UAAU,CAAC;IA4CtB,OAAO,CAAC,MAAM,CAAC,sBAAsB;CAuEtC"}
@@ -0,0 +1,429 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.ComponentLinter = void 0;
30
+ const parser = __importStar(require("@babel/parser"));
31
+ const traverse_1 = __importDefault(require("@babel/traverse"));
32
+ const t = __importStar(require("@babel/types"));
33
+ class ComponentLinter {
34
+ static async lintComponent(code, componentType, componentName) {
35
+ try {
36
+ const ast = parser.parse(code, {
37
+ sourceType: 'module',
38
+ plugins: ['jsx', 'typescript'],
39
+ errorRecovery: true
40
+ });
41
+ const rules = componentType === 'root'
42
+ ? this.rootComponentRules
43
+ : this.childComponentRules;
44
+ const violations = [];
45
+ // Run each rule
46
+ for (const rule of rules) {
47
+ const ruleViolations = rule.test(ast, componentName);
48
+ violations.push(...ruleViolations);
49
+ }
50
+ // Generate fix suggestions
51
+ const suggestions = this.generateFixSuggestions(violations, componentType);
52
+ return {
53
+ success: violations.filter(v => v.severity === 'error').length === 0,
54
+ violations,
55
+ suggestions
56
+ };
57
+ }
58
+ catch (error) {
59
+ // If parsing fails, return a parse error
60
+ return {
61
+ success: false,
62
+ violations: [{
63
+ rule: 'parse-error',
64
+ severity: 'error',
65
+ line: 0,
66
+ column: 0,
67
+ message: `Failed to parse component: ${error instanceof Error ? error.message : 'Unknown error'}`
68
+ }],
69
+ suggestions: []
70
+ };
71
+ }
72
+ }
73
+ static generateFixSuggestions(violations, componentType) {
74
+ const suggestions = [];
75
+ for (const violation of violations) {
76
+ switch (violation.rule) {
77
+ case 'no-use-state':
78
+ suggestions.push({
79
+ violation: violation.rule,
80
+ suggestion: 'Remove useState and accept the value as a prop from the parent component',
81
+ example: 'Replace: const [value, setValue] = useState(initialValue);\nWith: Accept "value" and "onValueChange" as props'
82
+ });
83
+ break;
84
+ case 'no-data-fetching':
85
+ suggestions.push({
86
+ violation: violation.rule,
87
+ suggestion: 'Move data fetching to the root component and pass data as props',
88
+ example: 'Remove utilities.rv.RunView() calls and accept the data as props instead'
89
+ });
90
+ break;
91
+ case 'no-async-effects':
92
+ suggestions.push({
93
+ violation: violation.rule,
94
+ suggestion: 'Remove async operations from useEffect. Let the root component handle data loading',
95
+ example: 'Remove the useEffect with async operations and accept loading/error states as props'
96
+ });
97
+ break;
98
+ case 'must-use-update-state':
99
+ suggestions.push({
100
+ violation: violation.rule,
101
+ suggestion: 'Add an updateState function that syncs with callbacks',
102
+ example: `const updateState = (updates) => {
103
+ const newState = { ...state, ...updates };
104
+ setState(newState);
105
+ if (callbacks?.UpdateUserState) {
106
+ callbacks.UpdateUserState(newState);
107
+ }
108
+ };`
109
+ });
110
+ break;
111
+ case 'sync-user-state':
112
+ suggestions.push({
113
+ violation: violation.rule,
114
+ suggestion: 'Call callbacks?.UpdateUserState in your updateState function',
115
+ example: 'Add: if (callbacks?.UpdateUserState) callbacks.UpdateUserState(newState);'
116
+ });
117
+ break;
118
+ case 'spread-user-state':
119
+ suggestions.push({
120
+ violation: violation.rule,
121
+ suggestion: 'Include ...userState in your initial state',
122
+ example: 'const [state, setState] = useState({ /* your fields */, ...userState });'
123
+ });
124
+ break;
125
+ case 'no-child-implementation':
126
+ suggestions.push({
127
+ violation: violation.rule,
128
+ suggestion: 'Remove child component implementations. Only the root component function should be in this file',
129
+ example: 'Move child component functions to separate generation requests'
130
+ });
131
+ break;
132
+ }
133
+ }
134
+ return suggestions;
135
+ }
136
+ }
137
+ exports.ComponentLinter = ComponentLinter;
138
+ ComponentLinter.childComponentRules = [
139
+ // State Management Rules
140
+ {
141
+ name: 'no-use-state',
142
+ test: (ast, componentName) => {
143
+ const violations = [];
144
+ (0, traverse_1.default)(ast, {
145
+ CallExpression(path) {
146
+ const callee = path.node.callee;
147
+ // Check for React.useState or just useState
148
+ if ((t.isIdentifier(callee) && callee.name === 'useState') ||
149
+ (t.isMemberExpression(callee) &&
150
+ t.isIdentifier(callee.object) && callee.object.name === 'React' &&
151
+ t.isIdentifier(callee.property) && callee.property.name === 'useState')) {
152
+ violations.push({
153
+ rule: 'no-use-state',
154
+ severity: 'error',
155
+ line: path.node.loc?.start.line || 0,
156
+ column: path.node.loc?.start.column || 0,
157
+ message: `Child component "${componentName}" uses useState at line ${path.node.loc?.start.line}. Child components must be purely controlled - receive state via props instead.`,
158
+ code: path.toString()
159
+ });
160
+ }
161
+ }
162
+ });
163
+ return violations;
164
+ }
165
+ },
166
+ {
167
+ name: 'no-use-reducer',
168
+ test: (ast, componentName) => {
169
+ const violations = [];
170
+ (0, traverse_1.default)(ast, {
171
+ CallExpression(path) {
172
+ const callee = path.node.callee;
173
+ if ((t.isIdentifier(callee) && callee.name === 'useReducer') ||
174
+ (t.isMemberExpression(callee) &&
175
+ t.isIdentifier(callee.object) && callee.object.name === 'React' &&
176
+ t.isIdentifier(callee.property) && callee.property.name === 'useReducer')) {
177
+ violations.push({
178
+ rule: 'no-use-reducer',
179
+ severity: 'error',
180
+ line: path.node.loc?.start.line || 0,
181
+ column: path.node.loc?.start.column || 0,
182
+ message: `Child component "${componentName}" uses useReducer at line ${path.node.loc?.start.line}. Child components must be purely controlled.`,
183
+ code: path.toString()
184
+ });
185
+ }
186
+ }
187
+ });
188
+ return violations;
189
+ }
190
+ },
191
+ {
192
+ name: 'no-data-fetching',
193
+ test: (ast, componentName) => {
194
+ const violations = [];
195
+ (0, traverse_1.default)(ast, {
196
+ MemberExpression(path) {
197
+ const object = path.node.object;
198
+ const property = path.node.property;
199
+ // Check for utilities.rv.RunView or utilities.rv.RunQuery
200
+ if (t.isMemberExpression(object) &&
201
+ t.isIdentifier(object.object) && object.object.name === 'utilities' &&
202
+ t.isIdentifier(object.property) && object.property.name === 'rv' &&
203
+ t.isIdentifier(property) &&
204
+ (property.name === 'RunView' || property.name === 'RunQuery' || property.name === 'RunViews')) {
205
+ violations.push({
206
+ rule: 'no-data-fetching',
207
+ severity: 'error',
208
+ line: path.node.loc?.start.line || 0,
209
+ column: path.node.loc?.start.column || 0,
210
+ message: `Child component "${componentName}" fetches data at line ${path.node.loc?.start.line}. Only root components should load data.`,
211
+ code: path.toString()
212
+ });
213
+ }
214
+ // Check for utilities.md operations
215
+ if (t.isMemberExpression(object) &&
216
+ t.isIdentifier(object.object) && object.object.name === 'utilities' &&
217
+ t.isIdentifier(object.property) && object.property.name === 'md') {
218
+ violations.push({
219
+ rule: 'no-data-fetching',
220
+ severity: 'error',
221
+ line: path.node.loc?.start.line || 0,
222
+ column: path.node.loc?.start.column || 0,
223
+ message: `Child component "${componentName}" accesses entity operations at line ${path.node.loc?.start.line}. Only root components should manage entities.`,
224
+ code: path.toString()
225
+ });
226
+ }
227
+ }
228
+ });
229
+ return violations;
230
+ }
231
+ },
232
+ {
233
+ name: 'no-async-effects',
234
+ test: (ast, componentName) => {
235
+ const violations = [];
236
+ (0, traverse_1.default)(ast, {
237
+ CallExpression(path) {
238
+ const callee = path.node.callee;
239
+ // Check for useEffect
240
+ if ((t.isIdentifier(callee) && callee.name === 'useEffect') ||
241
+ (t.isMemberExpression(callee) &&
242
+ t.isIdentifier(callee.object) && callee.object.name === 'React' &&
243
+ t.isIdentifier(callee.property) && callee.property.name === 'useEffect')) {
244
+ // Check if the effect function contains async operations
245
+ const effectFn = path.node.arguments[0];
246
+ if (t.isArrowFunctionExpression(effectFn) || t.isFunctionExpression(effectFn)) {
247
+ let hasAsync = false;
248
+ // Check if the effect function itself is async
249
+ if (effectFn.async) {
250
+ hasAsync = true;
251
+ }
252
+ // Traverse the effect function body to look for async patterns
253
+ (0, traverse_1.default)(effectFn, {
254
+ CallExpression(innerPath) {
255
+ const innerCallee = innerPath.node.callee;
256
+ // Check for async patterns
257
+ if ((t.isIdentifier(innerCallee) && innerCallee.name === 'fetch') ||
258
+ (t.isMemberExpression(innerCallee) &&
259
+ t.isIdentifier(innerCallee.property) &&
260
+ (innerCallee.property.name === 'then' || innerCallee.property.name === 'catch'))) {
261
+ hasAsync = true;
262
+ }
263
+ },
264
+ AwaitExpression() {
265
+ hasAsync = true;
266
+ },
267
+ FunctionDeclaration(innerPath) {
268
+ if (innerPath.node.async)
269
+ hasAsync = true;
270
+ },
271
+ ArrowFunctionExpression(innerPath) {
272
+ if (innerPath.node.async)
273
+ hasAsync = true;
274
+ }
275
+ }, path.scope, path.state, path.parentPath);
276
+ if (hasAsync) {
277
+ violations.push({
278
+ rule: 'no-async-effects',
279
+ severity: 'error',
280
+ line: path.node.loc?.start.line || 0,
281
+ column: path.node.loc?.start.column || 0,
282
+ message: `Child component "${componentName}" has async operations in useEffect at line ${path.node.loc?.start.line}. Data should be loaded by the root component and passed as props.`,
283
+ code: path.toString().substring(0, 100) + '...'
284
+ });
285
+ }
286
+ }
287
+ }
288
+ }
289
+ });
290
+ return violations;
291
+ }
292
+ }
293
+ ];
294
+ ComponentLinter.rootComponentRules = [
295
+ {
296
+ name: 'must-use-update-state',
297
+ test: (ast, componentName) => {
298
+ const violations = [];
299
+ let hasUpdateState = false;
300
+ (0, traverse_1.default)(ast, {
301
+ VariableDeclarator(path) {
302
+ if (t.isIdentifier(path.node.id) && path.node.id.name === 'updateState') {
303
+ hasUpdateState = true;
304
+ }
305
+ },
306
+ FunctionDeclaration(path) {
307
+ if (path.node.id && path.node.id.name === 'updateState') {
308
+ hasUpdateState = true;
309
+ }
310
+ }
311
+ });
312
+ if (!hasUpdateState) {
313
+ violations.push({
314
+ rule: 'must-use-update-state',
315
+ severity: 'error',
316
+ line: 1,
317
+ column: 0,
318
+ message: `Root component "${componentName}" must have an updateState function that syncs with callbacks.UpdateUserState.`,
319
+ });
320
+ }
321
+ return violations;
322
+ }
323
+ },
324
+ {
325
+ name: 'sync-user-state',
326
+ test: (ast, componentName) => {
327
+ const violations = [];
328
+ let hasUserStateSync = false;
329
+ (0, traverse_1.default)(ast, {
330
+ CallExpression(path) {
331
+ const callee = path.node.callee;
332
+ // Look for callbacks?.UpdateUserState or callbacks.UpdateUserState
333
+ if (t.isMemberExpression(callee)) {
334
+ // Check for callbacks.UpdateUserState
335
+ if (t.isIdentifier(callee.object) && callee.object.name === 'callbacks' &&
336
+ t.isIdentifier(callee.property) && callee.property.name === 'UpdateUserState') {
337
+ hasUserStateSync = true;
338
+ }
339
+ }
340
+ // Check for callbacks?.UpdateUserState (optional chaining)
341
+ else if (t.isOptionalMemberExpression(callee)) {
342
+ if (t.isIdentifier(callee.object) && callee.object.name === 'callbacks' &&
343
+ t.isIdentifier(callee.property) && callee.property.name === 'UpdateUserState') {
344
+ hasUserStateSync = true;
345
+ }
346
+ }
347
+ }
348
+ });
349
+ if (!hasUserStateSync) {
350
+ violations.push({
351
+ rule: 'sync-user-state',
352
+ severity: 'error',
353
+ line: 1,
354
+ column: 0,
355
+ message: `Root component "${componentName}" must call callbacks?.UpdateUserState to sync state changes.`,
356
+ });
357
+ }
358
+ return violations;
359
+ }
360
+ },
361
+ {
362
+ name: 'spread-user-state',
363
+ test: (ast, componentName) => {
364
+ const violations = [];
365
+ let hasUserStateSpread = false;
366
+ (0, traverse_1.default)(ast, {
367
+ CallExpression(path) {
368
+ const callee = path.node.callee;
369
+ // Check for useState call
370
+ if ((t.isIdentifier(callee) && callee.name === 'useState') ||
371
+ (t.isMemberExpression(callee) &&
372
+ t.isIdentifier(callee.object) && callee.object.name === 'React' &&
373
+ t.isIdentifier(callee.property) && callee.property.name === 'useState')) {
374
+ // Check if initial state includes ...userState
375
+ const initialState = path.node.arguments[0];
376
+ if (t.isObjectExpression(initialState)) {
377
+ for (const prop of initialState.properties) {
378
+ if (t.isSpreadElement(prop) && t.isIdentifier(prop.argument) && prop.argument.name === 'userState') {
379
+ hasUserStateSpread = true;
380
+ break;
381
+ }
382
+ }
383
+ }
384
+ }
385
+ }
386
+ });
387
+ if (!hasUserStateSpread) {
388
+ violations.push({
389
+ rule: 'spread-user-state',
390
+ severity: 'error',
391
+ line: 1,
392
+ column: 0,
393
+ message: `Root component "${componentName}" must spread ...userState in initial state to preserve user preferences.`,
394
+ });
395
+ }
396
+ return violations;
397
+ }
398
+ },
399
+ {
400
+ name: 'no-child-implementation',
401
+ test: (ast, componentName) => {
402
+ const violations = [];
403
+ const rootFunctionName = componentName;
404
+ const declaredFunctions = [];
405
+ // First pass: collect all function declarations
406
+ (0, traverse_1.default)(ast, {
407
+ FunctionDeclaration(path) {
408
+ if (path.node.id) {
409
+ declaredFunctions.push(path.node.id.name);
410
+ }
411
+ }
412
+ });
413
+ // If there are multiple function declarations and they look like components
414
+ // (start with capital letter), it's likely implementing children
415
+ const componentFunctions = declaredFunctions.filter(name => name !== rootFunctionName && /^[A-Z]/.test(name));
416
+ if (componentFunctions.length > 0) {
417
+ violations.push({
418
+ rule: 'no-child-implementation',
419
+ severity: 'error',
420
+ line: 1,
421
+ column: 0,
422
+ message: `Root component file contains child component implementations: ${componentFunctions.join(', ')}. Root should only reference child components, not implement them.`,
423
+ });
424
+ }
425
+ return violations;
426
+ }
427
+ }
428
+ ];
429
+ //# sourceMappingURL=component-linter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-linter.js","sourceRoot":"","sources":["../../src/lib/component-linter.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { BrowserManager } from './browser-context';
3
+ import { ComponentType, FixSuggestion } from './component-linter';
3
4
  export interface ComponentExecutionOptions {
4
5
  componentSpec: ComponentSpec;
5
6
  props?: Record<string, any>;
@@ -18,20 +19,83 @@ export interface ComponentExecutionResult {
18
19
  success: boolean;
19
20
  html: string;
20
21
  errors: string[];
22
+ warnings: string[];
23
+ criticalWarnings: string[];
21
24
  console: {
22
25
  type: string;
23
26
  text: string;
24
27
  }[];
25
28
  screenshot?: Buffer;
26
29
  executionTime: number;
30
+ renderCount?: number;
31
+ lintViolations?: string[];
32
+ fixSuggestions?: FixSuggestion[];
27
33
  }
28
34
  export declare class ComponentRunner {
29
35
  private browserManager;
30
36
  private compiler;
31
37
  private registry;
32
38
  private runtimeContext;
39
+ private static readonly CRITICAL_WARNING_PATTERNS;
40
+ private static readonly MAX_RENDER_COUNT;
33
41
  constructor(browserManager: BrowserManager);
42
+ /**
43
+ * Lint component code before execution
44
+ */
45
+ lintComponent(componentCode: string, componentName: string, componentType: ComponentType): Promise<{
46
+ violations: string[];
47
+ suggestions: FixSuggestion[];
48
+ hasErrors: boolean;
49
+ }>;
34
50
  executeComponent(options: ComponentExecutionOptions): Promise<ComponentExecutionResult>;
35
51
  private createHTMLTemplate;
52
+ /**
53
+ * Checks if a console message is a warning
54
+ */
55
+ private isWarning;
56
+ /**
57
+ * Checks if a warning is critical and should fail the test
58
+ */
59
+ private isCriticalWarning;
60
+ /**
61
+ * Sets up console logging with warning detection
62
+ */
63
+ private setupConsoleLogging;
64
+ /**
65
+ * Sets up error handling for the page
66
+ */
67
+ private setupErrorHandling;
68
+ /**
69
+ * Injects render tracking code into the page
70
+ */
71
+ private injectRenderTracking;
72
+ /**
73
+ * Waits for component to render and checks for timeouts
74
+ */
75
+ private waitForRender;
76
+ /**
77
+ * Gets the render count from the page
78
+ */
79
+ private getRenderCount;
80
+ /**
81
+ * Determines if the component execution was successful
82
+ */
83
+ private determineSuccess;
84
+ /**
85
+ * Expose MemberJunction utilities to the browser context
86
+ */
87
+ private exposeMJUtilities;
88
+ /**
89
+ * Analyze component errors to identify failed components
90
+ * @param errors Array of error messages
91
+ * @returns Array of component names that failed
92
+ */
93
+ static analyzeComponentErrors(errors: string[]): string[];
94
+ /**
95
+ * Get detailed error analysis
96
+ * @param errors Array of error messages
97
+ * @returns Detailed failure information
98
+ */
99
+ static getDetailedErrorAnalysis(errors: string[]): import("@memberjunction/react-runtime").FailedComponentInfo[];
36
100
  }
37
101
  //# sourceMappingURL=component-runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"component-runner.d.ts","sourceRoot":"","sources":["../../src/lib/component-runner.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AASnD,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,GAAG,kBAAkB,GAAG,aAAa,CAAC;CAChE;AAED,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,aAAa,EAAE,CAAC;IAClC,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,eAAe;IAKd,OAAO,CAAC,cAAc;IAJlC,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,cAAc,CAAiB;gBAEnB,cAAc,EAAE,cAAc;IAQ5C,gBAAgB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAgE7F,OAAO,CAAC,kBAAkB;CA8X3B"}
1
+ {"version":3,"file":"component-runner.d.ts","sourceRoot":"","sources":["../../src/lib/component-runner.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAanD,OAAO,EAAmB,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnF,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,GAAG,kBAAkB,GAAG,aAAa,CAAC;CAChE;AAED,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,aAAa,EAAE,CAAC;IAClC,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;CAClC;AAED,qBAAa,eAAe;IAoBd,OAAO,CAAC,cAAc;IAnBlC,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,cAAc,CAAiB;IAGvC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAS/C;IAGF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAQ;gBAE5B,cAAc,EAAE,cAAc;IAQlD;;OAEG;IACG,aAAa,CACjB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,aAAa,EAAE,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAiBhF,gBAAgB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAwE7F,OAAO,CAAC,kBAAkB;IA8a1B;;OAEG;IACH,OAAO,CAAC,SAAS;IAIjB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAsB3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAM1B;;OAEG;YACW,oBAAoB;IAMlC;;OAEG;YACW,aAAa;IA0B3B;;OAEG;YACW,cAAc;IAI5B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAoBxB;;OAEG;YACW,iBAAiB;IAgE/B;;;;OAIG;IACH,MAAM,CAAC,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;IAIzD;;;;OAIG;IACH,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE;CAGjD"}