@memberjunction/react-test-harness 2.88.0 → 2.90.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 +98 -0
- package/dist/lib/component-linter.d.ts +2 -1
- package/dist/lib/component-linter.d.ts.map +1 -1
- package/dist/lib/component-linter.js +190 -317
- package/dist/lib/component-linter.js.map +1 -1
- package/dist/lib/component-runner.d.ts +11 -0
- package/dist/lib/component-runner.d.ts.map +1 -1
- package/dist/lib/component-runner.js +323 -73
- package/dist/lib/component-runner.js.map +1 -1
- package/dist/lib/test-harness.d.ts +31 -0
- package/dist/lib/test-harness.d.ts.map +1 -1
- package/dist/lib/test-harness.js +53 -0
- package/dist/lib/test-harness.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -526,6 +526,104 @@ interface FluentMatcher {
|
|
|
526
526
|
}
|
|
527
527
|
```
|
|
528
528
|
|
|
529
|
+
## Parallel Testing
|
|
530
|
+
|
|
531
|
+
### Important: Test Harness Instance Limitations
|
|
532
|
+
|
|
533
|
+
The ReactTestHarness uses a single browser page instance and is **NOT safe for parallel test execution** on the same instance. This is due to Playwright's internal limitations with `exposeFunction` and potential race conditions when multiple tests try to modify the same page context simultaneously.
|
|
534
|
+
|
|
535
|
+
### Sequential Testing (Single Instance)
|
|
536
|
+
|
|
537
|
+
For sequential test execution, you can safely reuse a single harness instance:
|
|
538
|
+
|
|
539
|
+
```typescript
|
|
540
|
+
const harness = new ReactTestHarness({ headless: true });
|
|
541
|
+
await harness.initialize();
|
|
542
|
+
|
|
543
|
+
// ✅ CORRECT - Sequential testing on same instance
|
|
544
|
+
for (const test of tests) {
|
|
545
|
+
const result = await harness.testComponent(test.code, test.props);
|
|
546
|
+
// Each test runs one after another, no conflicts
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
await harness.close();
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### Parallel Testing (Multiple Instances)
|
|
553
|
+
|
|
554
|
+
For parallel test execution, you **MUST** create separate ReactTestHarness instances:
|
|
555
|
+
|
|
556
|
+
```typescript
|
|
557
|
+
// ✅ CORRECT - Parallel testing with separate instances
|
|
558
|
+
const results = await Promise.all(tests.map(async (test) => {
|
|
559
|
+
const harness = new ReactTestHarness({ headless: true });
|
|
560
|
+
await harness.initialize();
|
|
561
|
+
|
|
562
|
+
try {
|
|
563
|
+
return await harness.testComponent(test.code, test.props);
|
|
564
|
+
} finally {
|
|
565
|
+
await harness.close(); // Clean up each instance
|
|
566
|
+
}
|
|
567
|
+
}));
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
### Common Mistake to Avoid
|
|
571
|
+
|
|
572
|
+
```typescript
|
|
573
|
+
// ❌ WRONG - DO NOT DO THIS
|
|
574
|
+
const harness = new ReactTestHarness({ headless: true });
|
|
575
|
+
await harness.initialize();
|
|
576
|
+
|
|
577
|
+
// This will cause conflicts and errors!
|
|
578
|
+
const results = await Promise.all(
|
|
579
|
+
tests.map(test => harness.testComponent(test.code, test.props))
|
|
580
|
+
);
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
This approach will fail with errors like:
|
|
584
|
+
- "Function '__mjGetEntityObject' has been already registered"
|
|
585
|
+
- "Cannot read properties of undefined (reading 'addBinding')"
|
|
586
|
+
|
|
587
|
+
### Performance Considerations
|
|
588
|
+
|
|
589
|
+
While creating multiple harness instances has some overhead (each launches its own browser context), the benefits of parallel execution typically outweigh this cost:
|
|
590
|
+
|
|
591
|
+
- **Sequential (1 instance)**: Lower memory usage, but tests run one by one
|
|
592
|
+
- **Parallel (N instances)**: Higher memory usage, but tests complete much faster
|
|
593
|
+
|
|
594
|
+
### Example: Test Runner with Configurable Parallelism
|
|
595
|
+
|
|
596
|
+
```typescript
|
|
597
|
+
class TestRunner {
|
|
598
|
+
async runTests(tests: TestCase[], parallel = false) {
|
|
599
|
+
if (parallel) {
|
|
600
|
+
// Create new instance for each test
|
|
601
|
+
return Promise.all(tests.map(async (test) => {
|
|
602
|
+
const harness = new ReactTestHarness({ headless: true });
|
|
603
|
+
await harness.initialize();
|
|
604
|
+
try {
|
|
605
|
+
return await harness.testComponent(test.code, test.props);
|
|
606
|
+
} finally {
|
|
607
|
+
await harness.close();
|
|
608
|
+
}
|
|
609
|
+
}));
|
|
610
|
+
} else {
|
|
611
|
+
// Reuse single instance for all tests
|
|
612
|
+
const harness = new ReactTestHarness({ headless: true });
|
|
613
|
+
await harness.initialize();
|
|
614
|
+
|
|
615
|
+
const results = [];
|
|
616
|
+
for (const test of tests) {
|
|
617
|
+
results.push(await harness.testComponent(test.code, test.props));
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
await harness.close();
|
|
621
|
+
return results;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
```
|
|
626
|
+
|
|
529
627
|
## Usage Examples for TypeScript Projects
|
|
530
628
|
|
|
531
629
|
### Creating a Reusable Test Utility
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ComponentSpec } from '@memberjunction/interactive-component-types';
|
|
1
2
|
export interface LintResult {
|
|
2
3
|
success: boolean;
|
|
3
4
|
violations: Violation[];
|
|
@@ -22,7 +23,7 @@ export interface FixSuggestion {
|
|
|
22
23
|
}
|
|
23
24
|
export declare class ComponentLinter {
|
|
24
25
|
private static universalComponentRules;
|
|
25
|
-
static lintComponent(code: string, componentName: string, componentSpec?:
|
|
26
|
+
static lintComponent(code: string, componentName: string, componentSpec?: ComponentSpec, isRootComponent?: boolean): Promise<LintResult>;
|
|
26
27
|
private static validateDataRequirements;
|
|
27
28
|
private static getFunctionName;
|
|
28
29
|
private static deduplicateViolations;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-linter.d.ts","sourceRoot":"","sources":["../../src/lib/component-linter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"component-linter.d.ts","sourceRoot":"","sources":["../../src/lib/component-linter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AAE5E,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACjD,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;AAaD,qBAAa,eAAe;IAE1B,OAAO,CAAC,MAAM,CAAC,uBAAuB,CA2pCpC;WAEkB,aAAa,CAC/B,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EACrB,aAAa,CAAC,EAAE,aAAa,EAC7B,eAAe,CAAC,EAAE,OAAO,GACxB,OAAO,CAAC,UAAU,CAAC;IAuEtB,OAAO,CAAC,MAAM,CAAC,wBAAwB;IAgQvC,OAAO,CAAC,MAAM,CAAC,eAAe;IA2B9B,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAyBpC,OAAO,CAAC,MAAM,CAAC,sBAAsB;CA6pBtC"}
|