intellitester 0.2.18 → 0.2.20

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.
@@ -2,7 +2,9 @@ import { loadCleanupHandlers, executeCleanup, saveFailedCleanup } from './chunk-
2
2
  import { z } from 'zod';
3
3
  import fs2 from 'fs/promises';
4
4
  import { parse } from 'yaml';
5
- import crypto2 from 'crypto';
5
+ import { NumberDictionary, uniqueNamesGenerator, adjectives, animals } from 'unique-names-generator';
6
+ import crypto4 from 'crypto';
7
+ import { parsePhoneNumber, isValidPhoneNumber } from 'libphonenumber-js';
6
8
  import path from 'path';
7
9
  import { spawn } from 'child_process';
8
10
  import { chromium, webkit, firefox } from 'playwright';
@@ -476,6 +478,285 @@ var isPipelineContent = (content) => {
476
478
  return false;
477
479
  }
478
480
  };
481
+ function generateRandomUsername() {
482
+ const numberDictionary = NumberDictionary.generate({ min: 0, max: 99 });
483
+ const username = uniqueNamesGenerator({
484
+ dictionaries: [adjectives, animals, numberDictionary],
485
+ separator: "",
486
+ style: "capital",
487
+ length: 3
488
+ });
489
+ if (username.length > 30) {
490
+ return username.slice(0, 30);
491
+ }
492
+ return username;
493
+ }
494
+
495
+ // src/core/randomPhoto.ts
496
+ function generateRandomPhoto(dimensions) {
497
+ let width = 500;
498
+ let height = 500;
499
+ if (dimensions) {
500
+ if (dimensions.includes("x")) {
501
+ const [w, h] = dimensions.split("x").map((d) => parseInt(d.trim(), 10));
502
+ if (!isNaN(w) && w > 0) width = w;
503
+ if (!isNaN(h) && h > 0) height = h;
504
+ } else {
505
+ const size = parseInt(dimensions.trim(), 10);
506
+ if (!isNaN(size) && size > 0) {
507
+ width = size;
508
+ height = size;
509
+ }
510
+ }
511
+ }
512
+ return `https://picsum.photos/${width}/${height}`;
513
+ }
514
+
515
+ // src/core/fillerText.ts
516
+ var LOREM_WORDS = [
517
+ "lorem",
518
+ "ipsum",
519
+ "dolor",
520
+ "sit",
521
+ "amet",
522
+ "consectetur",
523
+ "adipiscing",
524
+ "elit",
525
+ "sed",
526
+ "do",
527
+ "eiusmod",
528
+ "tempor",
529
+ "incididunt",
530
+ "ut",
531
+ "labore",
532
+ "et",
533
+ "dolore",
534
+ "magna",
535
+ "aliqua",
536
+ "enim",
537
+ "ad",
538
+ "minim",
539
+ "veniam",
540
+ "quis",
541
+ "nostrud",
542
+ "exercitation",
543
+ "ullamco",
544
+ "laboris",
545
+ "nisi",
546
+ "aliquip",
547
+ "ex",
548
+ "ea",
549
+ "commodo",
550
+ "consequat",
551
+ "duis",
552
+ "aute",
553
+ "irure",
554
+ "in",
555
+ "reprehenderit",
556
+ "voluptate",
557
+ "velit",
558
+ "esse",
559
+ "cillum",
560
+ "fugiat",
561
+ "nulla",
562
+ "pariatur",
563
+ "excepteur",
564
+ "sint",
565
+ "occaecat",
566
+ "cupidatat",
567
+ "non",
568
+ "proident",
569
+ "sunt",
570
+ "culpa",
571
+ "qui",
572
+ "officia",
573
+ "deserunt",
574
+ "mollit",
575
+ "anim",
576
+ "id",
577
+ "est",
578
+ "laborum",
579
+ "perspiciatis",
580
+ "unde",
581
+ "omnis",
582
+ "iste",
583
+ "natus",
584
+ "error",
585
+ "voluptatem",
586
+ "accusantium",
587
+ "doloremque",
588
+ "laudantium",
589
+ "totam",
590
+ "rem",
591
+ "aperiam",
592
+ "eaque",
593
+ "ipsa",
594
+ "quae",
595
+ "ab",
596
+ "illo",
597
+ "inventore",
598
+ "veritatis",
599
+ "quasi",
600
+ "architecto",
601
+ "beatae",
602
+ "vitae",
603
+ "dicta",
604
+ "explicabo",
605
+ "nemo",
606
+ "ipsam",
607
+ "quia",
608
+ "voluptas",
609
+ "aspernatur",
610
+ "aut",
611
+ "odit",
612
+ "fugit",
613
+ "consequuntur",
614
+ "magni",
615
+ "dolores",
616
+ "eos",
617
+ "ratione",
618
+ "sequi",
619
+ "nesciunt",
620
+ "neque",
621
+ "porro",
622
+ "quisquam",
623
+ "nihil",
624
+ "impedit",
625
+ "quo",
626
+ "minus"
627
+ ];
628
+ function generateFillerText(wordCount) {
629
+ let count = 50;
630
+ if (wordCount !== void 0) {
631
+ const parsed = typeof wordCount === "string" ? parseInt(wordCount.trim(), 10) : wordCount;
632
+ if (!isNaN(parsed) && parsed > 0) {
633
+ count = parsed;
634
+ }
635
+ }
636
+ const words = [];
637
+ if (count >= 2) {
638
+ words.push("Lorem", "ipsum");
639
+ count -= 2;
640
+ }
641
+ for (let i = 0; i < count; i++) {
642
+ const randomIndex = Math.floor(Math.random() * LOREM_WORDS.length);
643
+ words.push(LOREM_WORDS[randomIndex]);
644
+ }
645
+ let result = words.join(" ");
646
+ const resultWords = result.split(" ");
647
+ const sentenceWords = [];
648
+ let sentenceLength = 0;
649
+ const nextSentenceLength = () => 8 + Math.floor(Math.random() * 5);
650
+ let targetLength = nextSentenceLength();
651
+ for (let i = 0; i < resultWords.length; i++) {
652
+ let word = resultWords[i];
653
+ if (sentenceLength === 0) {
654
+ word = word.charAt(0).toUpperCase() + word.slice(1);
655
+ }
656
+ sentenceWords.push(word);
657
+ sentenceLength++;
658
+ if (sentenceLength >= targetLength && i < resultWords.length - 1) {
659
+ sentenceWords[sentenceWords.length - 1] += ".";
660
+ sentenceLength = 0;
661
+ targetLength = nextSentenceLength();
662
+ }
663
+ }
664
+ result = sentenceWords.join(" ");
665
+ if (!result.endsWith(".")) {
666
+ result += ".";
667
+ }
668
+ return result;
669
+ }
670
+ function generateRandomEmail(domain) {
671
+ const randomPart = crypto4.randomBytes(3).toString("hex");
672
+ const emailDomain = domain?.trim() || "test.local";
673
+ return `test-${randomPart}@${emailDomain}`;
674
+ }
675
+ var COUNTRY_FORMATS = {
676
+ US: {
677
+ areaCode: () => {
678
+ const areaCodes = ["201", "212", "213", "310", "312", "404", "415", "512", "617", "702", "713", "718", "805", "818", "917"];
679
+ return areaCodes[Math.floor(Math.random() * areaCodes.length)];
680
+ },
681
+ subscriber: () => String(Math.floor(Math.random() * 9e6) + 1e6).slice(0, 7)
682
+ },
683
+ GB: {
684
+ areaCode: () => {
685
+ const areaCodes = ["20", "121", "131", "141", "151", "161", "171", "181"];
686
+ return areaCodes[Math.floor(Math.random() * areaCodes.length)];
687
+ },
688
+ subscriber: () => String(Math.floor(Math.random() * 9e7) + 1e7).slice(0, 8)
689
+ },
690
+ DE: {
691
+ areaCode: () => {
692
+ const areaCodes = ["30", "40", "69", "89", "211", "221", "341", "351"];
693
+ return areaCodes[Math.floor(Math.random() * areaCodes.length)];
694
+ },
695
+ subscriber: () => String(Math.floor(Math.random() * 9e6) + 1e6).slice(0, 7)
696
+ },
697
+ FR: {
698
+ areaCode: () => {
699
+ const areaCodes = ["1", "2", "3", "4", "5"];
700
+ return areaCodes[Math.floor(Math.random() * areaCodes.length)];
701
+ },
702
+ subscriber: () => String(Math.floor(Math.random() * 9e7) + 1e7).slice(0, 8)
703
+ },
704
+ AU: {
705
+ areaCode: () => {
706
+ const areaCodes = ["2", "3", "7", "8"];
707
+ return areaCodes[Math.floor(Math.random() * areaCodes.length)];
708
+ },
709
+ subscriber: () => String(Math.floor(Math.random() * 9e7) + 1e7).slice(0, 8)
710
+ }
711
+ };
712
+ function generateRandomPhone(country = "US") {
713
+ const countryCode = country.toUpperCase();
714
+ const format = COUNTRY_FORMATS[countryCode] || COUNTRY_FORMATS["US"];
715
+ for (let i = 0; i < 10; i++) {
716
+ const areaCode2 = format.areaCode();
717
+ const subscriber2 = format.subscriber();
718
+ const nationalNumber = areaCode2 + subscriber2;
719
+ try {
720
+ const phoneNumber = parsePhoneNumber(nationalNumber, countryCode);
721
+ if (phoneNumber && isValidPhoneNumber(phoneNumber.number)) {
722
+ return phoneNumber.format("E.164");
723
+ }
724
+ } catch {
725
+ }
726
+ }
727
+ const fallbackFormat = COUNTRY_FORMATS[countryCode] || COUNTRY_FORMATS["US"];
728
+ const areaCode = fallbackFormat.areaCode();
729
+ const subscriber = fallbackFormat.subscriber();
730
+ const callingCodes = {
731
+ US: "1",
732
+ GB: "44",
733
+ DE: "49",
734
+ FR: "33",
735
+ AU: "61"
736
+ };
737
+ const callingCode = callingCodes[countryCode] || "1";
738
+ return `+${callingCode}${areaCode}${subscriber}`;
739
+ }
740
+ function interpolateVariables(value, variables) {
741
+ return value.replace(/\{\{(\w+)(?::([^}]+))?\}\}/g, (match, name, param) => {
742
+ switch (name) {
743
+ case "uuid":
744
+ return crypto4.randomUUID().split("-")[0];
745
+ case "randomUsername":
746
+ return generateRandomUsername();
747
+ case "randomPhoto":
748
+ return generateRandomPhoto(param);
749
+ case "fillerText":
750
+ return generateFillerText(param);
751
+ case "randomEmail":
752
+ return generateRandomEmail(param);
753
+ case "randomPhone":
754
+ return generateRandomPhone(param);
755
+ default:
756
+ return variables.get(name) ?? match;
757
+ }
758
+ });
759
+ }
479
760
 
480
761
  // src/integrations/email/inbucketClient.ts
481
762
  var InbucketClient = class {
@@ -1011,14 +1292,6 @@ async function startTrackingServer(options) {
1011
1292
 
1012
1293
  // src/executors/web/playwrightExecutor.ts
1013
1294
  var defaultScreenshotDir = path.join(process.cwd(), "artifacts", "screenshots");
1014
- function interpolateVariables(value, variables) {
1015
- return value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
1016
- if (varName === "uuid") {
1017
- return crypto2.randomUUID().split("-")[0];
1018
- }
1019
- return variables.get(varName) ?? match;
1020
- });
1021
- }
1022
1295
  var resolveUrl = (value, baseUrl) => {
1023
1296
  if (!baseUrl) return value;
1024
1297
  try {
@@ -1558,7 +1831,7 @@ var runWebTest = async (test, options = {}) => {
1558
1831
  const headless = !(options.headed ?? false);
1559
1832
  const screenshotDir = options.screenshotDir ?? defaultScreenshotDir;
1560
1833
  const defaultTimeout = options.defaultTimeoutMs ?? 3e4;
1561
- const sessionId = crypto2.randomUUID();
1834
+ const sessionId = crypto4.randomUUID();
1562
1835
  const trackingServer = new TrackingServer();
1563
1836
  await trackingServer.start();
1564
1837
  process.env.INTELLITESTER_SESSION_ID = sessionId;
@@ -1864,16 +2137,14 @@ var getBrowser2 = (browser) => {
1864
2137
  };
1865
2138
  function interpolateWorkflowVariables(value, currentVariables, testResults) {
1866
2139
  return value.replace(/\{\{([^}]+)\}\}/g, (match, path3) => {
1867
- if (path3.includes(".")) {
2140
+ if (path3.includes(".") && !path3.includes(":")) {
1868
2141
  const [testId, _varName] = path3.split(".", 2);
1869
2142
  testResults.find((t) => t.id === testId);
1870
2143
  console.warn(`Cross-test variable interpolation {{${path3}}} not yet fully implemented`);
1871
2144
  return match;
1872
2145
  }
1873
- if (path3 === "uuid") {
1874
- return crypto2.randomUUID().split("-")[0];
1875
- }
1876
- return currentVariables.get(path3) ?? match;
2146
+ const result = interpolateVariables(`{{${path3}}}`, currentVariables);
2147
+ return result;
1877
2148
  });
1878
2149
  }
1879
2150
  async function runTestInWorkflow(test, page, context, options, _workflowDir, workflowBaseUrl) {
@@ -1889,13 +2160,8 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
1889
2160
  return value;
1890
2161
  }
1891
2162
  };
1892
- const interpolateVariables2 = (value) => {
1893
- return value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
1894
- if (varName === "uuid") {
1895
- return crypto2.randomUUID().split("-")[0];
1896
- }
1897
- return context.variables.get(varName) ?? match;
1898
- });
2163
+ const interpolate = (value) => {
2164
+ return interpolateVariables(value, context.variables);
1899
2165
  };
1900
2166
  const resolveLocator2 = (locator) => {
1901
2167
  if (locator.testId) return page.getByTestId(locator.testId);
@@ -1918,7 +2184,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
1918
2184
  try {
1919
2185
  switch (action.type) {
1920
2186
  case "navigate": {
1921
- const interpolated = interpolateVariables2(action.value);
2187
+ const interpolated = interpolate(action.value);
1922
2188
  const baseUrl = test.config?.web?.baseUrl ?? workflowBaseUrl;
1923
2189
  const target = resolveUrl2(interpolated, baseUrl);
1924
2190
  if (debugMode) console.log(` [DEBUG] Navigating to: ${target}`);
@@ -1932,7 +2198,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
1932
2198
  break;
1933
2199
  }
1934
2200
  case "input": {
1935
- const interpolated = interpolateVariables2(action.value);
2201
+ const interpolated = interpolate(action.value);
1936
2202
  if (debugMode) console.log(` [DEBUG] Input: ${interpolated}`);
1937
2203
  const handle = resolveLocator2(action.target);
1938
2204
  await handle.fill(interpolated);
@@ -1951,7 +2217,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
1951
2217
  break;
1952
2218
  }
1953
2219
  case "select": {
1954
- const interpolated = interpolateVariables2(action.value);
2220
+ const interpolated = interpolate(action.value);
1955
2221
  if (debugMode) console.log(` [DEBUG] Selecting: ${interpolated}`);
1956
2222
  const handle = resolveLocator2(action.target);
1957
2223
  await handle.selectOption(interpolated);
@@ -1990,7 +2256,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
1990
2256
  const handle = resolveLocator2(action.target);
1991
2257
  await handle.waitFor({ state: "visible" });
1992
2258
  if (action.value) {
1993
- const interpolated = interpolateVariables2(action.value);
2259
+ const interpolated = interpolate(action.value);
1994
2260
  const text = (await handle.textContent())?.trim() ?? "";
1995
2261
  if (!text.includes(interpolated)) {
1996
2262
  throw new Error(
@@ -2031,7 +2297,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
2031
2297
  case "setVar": {
2032
2298
  let value;
2033
2299
  if (action.value) {
2034
- value = interpolateVariables2(action.value);
2300
+ value = interpolate(action.value);
2035
2301
  } else if (action.from === "response") {
2036
2302
  throw new Error("setVar from response not yet implemented");
2037
2303
  } else if (action.from === "element") {
@@ -2049,7 +2315,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
2049
2315
  if (!context.emailClient) {
2050
2316
  throw new Error("Email client not configured");
2051
2317
  }
2052
- const mailbox = interpolateVariables2(action.mailbox);
2318
+ const mailbox = interpolate(action.mailbox);
2053
2319
  context.lastEmail = await context.emailClient.waitForEmail(mailbox, {
2054
2320
  timeout: action.timeout,
2055
2321
  subjectContains: action.subjectContains
@@ -2094,7 +2360,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
2094
2360
  if (!context.emailClient) {
2095
2361
  throw new Error("Email client not configured");
2096
2362
  }
2097
- const mailbox = interpolateVariables2(action.mailbox);
2363
+ const mailbox = interpolate(action.mailbox);
2098
2364
  await context.emailClient.clearMailbox(mailbox);
2099
2365
  break;
2100
2366
  }
@@ -2314,7 +2580,7 @@ function inferCleanupConfig(config) {
2314
2580
  async function runWorkflowWithContext(workflow, workflowFilePath, options) {
2315
2581
  const { page, executionContext, skipCleanup = false, sessionId: providedSessionId, testStartTime: providedTestStartTime } = options;
2316
2582
  const workflowDir = path.dirname(workflowFilePath);
2317
- const sessionId = providedSessionId ?? crypto2.randomUUID();
2583
+ const sessionId = providedSessionId ?? crypto4.randomUUID();
2318
2584
  const testStartTime = providedTestStartTime ?? (/* @__PURE__ */ new Date()).toISOString();
2319
2585
  console.log(`
2320
2586
  Starting workflow: ${workflow.name}`);
@@ -2333,10 +2599,7 @@ Starting workflow: ${workflow.name}`);
2333
2599
  if (workflow.variables) {
2334
2600
  for (const [key, value] of Object.entries(workflow.variables)) {
2335
2601
  if (!executionContext.variables.has(key)) {
2336
- const interpolated = value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
2337
- if (varName === "uuid") return crypto2.randomUUID().split("-")[0];
2338
- return executionContext.variables.get(varName) ?? match;
2339
- });
2602
+ const interpolated = interpolateVariables(value, executionContext.variables);
2340
2603
  executionContext.variables.set(key, interpolated);
2341
2604
  }
2342
2605
  }
@@ -2366,12 +2629,7 @@ Starting workflow: ${workflow.name}`);
2366
2629
  }
2367
2630
  if (test.variables) {
2368
2631
  for (const [key, value] of Object.entries(test.variables)) {
2369
- const interpolated = value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
2370
- if (varName === "uuid") {
2371
- return crypto2.randomUUID().split("-")[0];
2372
- }
2373
- return executionContext.variables.get(varName) ?? match;
2374
- });
2632
+ const interpolated = interpolateVariables(value, executionContext.variables);
2375
2633
  executionContext.variables.set(key, interpolated);
2376
2634
  }
2377
2635
  }
@@ -2510,7 +2768,7 @@ ${"=".repeat(60)}`);
2510
2768
  }
2511
2769
  async function runWorkflow(workflow, workflowFilePath, options = {}) {
2512
2770
  const workflowDir = path.dirname(workflowFilePath);
2513
- const sessionId = crypto2.randomUUID();
2771
+ const sessionId = crypto4.randomUUID();
2514
2772
  const testStartTime = (/* @__PURE__ */ new Date()).toISOString();
2515
2773
  let trackingServer = null;
2516
2774
  try {
@@ -2567,10 +2825,7 @@ async function runWorkflow(workflow, workflowFilePath, options = {}) {
2567
2825
  };
2568
2826
  if (workflow.variables) {
2569
2827
  for (const [key, value] of Object.entries(workflow.variables)) {
2570
- const interpolated = value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
2571
- if (varName === "uuid") return crypto2.randomUUID().split("-")[0];
2572
- return executionContext.variables.get(varName) ?? match;
2573
- });
2828
+ const interpolated = interpolateVariables(value, executionContext.variables);
2574
2829
  executionContext.variables.set(key, interpolated);
2575
2830
  }
2576
2831
  }
@@ -2689,6 +2944,6 @@ Collected ${serverResources.length} server-tracked resources`);
2689
2944
  }
2690
2945
  }
2691
2946
 
2692
- export { ActionSchema, IntellitesterConfigSchema, LocatorSchema, TestConfigSchema, TestDefinitionSchema, cleanupConfigSchema, cleanupDiscoverSchema, collectMissingEnvVars, createAIProvider, createTestContext, isPipelineContent, isPipelineFile, isWorkflowContent, isWorkflowFile, killServer, loadIntellitesterConfig, loadPipelineDefinition, loadTestDefinition, loadWorkflowDefinition, parseIntellitesterConfig, parsePipelineDefinition, parseTestDefinition, parseWorkflowDefinition, previewConfigSchema, runWebTest, runWorkflow, runWorkflowWithContext, setupAppwriteTracking, startTrackingServer, startWebServer };
2693
- //# sourceMappingURL=chunk-EQJQS4RD.js.map
2694
- //# sourceMappingURL=chunk-EQJQS4RD.js.map
2947
+ export { ActionSchema, IntellitesterConfigSchema, LocatorSchema, TestConfigSchema, TestDefinitionSchema, cleanupConfigSchema, cleanupDiscoverSchema, collectMissingEnvVars, createAIProvider, createTestContext, generateFillerText, generateRandomEmail, generateRandomPhone, generateRandomPhoto, generateRandomUsername, interpolateVariables, isPipelineContent, isPipelineFile, isWorkflowContent, isWorkflowFile, killServer, loadIntellitesterConfig, loadPipelineDefinition, loadTestDefinition, loadWorkflowDefinition, parseIntellitesterConfig, parsePipelineDefinition, parseTestDefinition, parseWorkflowDefinition, previewConfigSchema, runWebTest, runWorkflow, runWorkflowWithContext, setupAppwriteTracking, startTrackingServer, startWebServer };
2948
+ //# sourceMappingURL=chunk-ICJK4WBA.js.map
2949
+ //# sourceMappingURL=chunk-ICJK4WBA.js.map