intellitester 0.2.19 → 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,12 +2,13 @@ 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';
9
11
  import prompts from 'prompts';
10
- import { NumberDictionary, uniqueNamesGenerator, adjectives, animals } from 'unique-names-generator';
11
12
  import { Client, Users, TablesDB, Storage, Teams } from 'node-appwrite';
12
13
  import { Anthropic } from '@llamaindex/anthropic';
13
14
  import { OpenAI } from '@llamaindex/openai';
@@ -491,6 +492,272 @@ function generateRandomUsername() {
491
492
  return username;
492
493
  }
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
+ }
760
+
494
761
  // src/integrations/email/inbucketClient.ts
495
762
  var InbucketClient = class {
496
763
  constructor(config) {
@@ -1025,17 +1292,6 @@ async function startTrackingServer(options) {
1025
1292
 
1026
1293
  // src/executors/web/playwrightExecutor.ts
1027
1294
  var defaultScreenshotDir = path.join(process.cwd(), "artifacts", "screenshots");
1028
- function interpolateVariables(value, variables) {
1029
- return value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
1030
- if (varName === "uuid") {
1031
- return crypto2.randomUUID().split("-")[0];
1032
- }
1033
- if (varName === "randomUsername") {
1034
- return generateRandomUsername();
1035
- }
1036
- return variables.get(varName) ?? match;
1037
- });
1038
- }
1039
1295
  var resolveUrl = (value, baseUrl) => {
1040
1296
  if (!baseUrl) return value;
1041
1297
  try {
@@ -1575,7 +1831,7 @@ var runWebTest = async (test, options = {}) => {
1575
1831
  const headless = !(options.headed ?? false);
1576
1832
  const screenshotDir = options.screenshotDir ?? defaultScreenshotDir;
1577
1833
  const defaultTimeout = options.defaultTimeoutMs ?? 3e4;
1578
- const sessionId = crypto2.randomUUID();
1834
+ const sessionId = crypto4.randomUUID();
1579
1835
  const trackingServer = new TrackingServer();
1580
1836
  await trackingServer.start();
1581
1837
  process.env.INTELLITESTER_SESSION_ID = sessionId;
@@ -1881,19 +2137,14 @@ var getBrowser2 = (browser) => {
1881
2137
  };
1882
2138
  function interpolateWorkflowVariables(value, currentVariables, testResults) {
1883
2139
  return value.replace(/\{\{([^}]+)\}\}/g, (match, path3) => {
1884
- if (path3.includes(".")) {
2140
+ if (path3.includes(".") && !path3.includes(":")) {
1885
2141
  const [testId, _varName] = path3.split(".", 2);
1886
2142
  testResults.find((t) => t.id === testId);
1887
2143
  console.warn(`Cross-test variable interpolation {{${path3}}} not yet fully implemented`);
1888
2144
  return match;
1889
2145
  }
1890
- if (path3 === "uuid") {
1891
- return crypto2.randomUUID().split("-")[0];
1892
- }
1893
- if (path3 === "randomUsername") {
1894
- return generateRandomUsername();
1895
- }
1896
- return currentVariables.get(path3) ?? match;
2146
+ const result = interpolateVariables(`{{${path3}}}`, currentVariables);
2147
+ return result;
1897
2148
  });
1898
2149
  }
1899
2150
  async function runTestInWorkflow(test, page, context, options, _workflowDir, workflowBaseUrl) {
@@ -1909,16 +2160,8 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
1909
2160
  return value;
1910
2161
  }
1911
2162
  };
1912
- const interpolateVariables2 = (value) => {
1913
- return value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
1914
- if (varName === "uuid") {
1915
- return crypto2.randomUUID().split("-")[0];
1916
- }
1917
- if (varName === "randomUsername") {
1918
- return generateRandomUsername();
1919
- }
1920
- return context.variables.get(varName) ?? match;
1921
- });
2163
+ const interpolate = (value) => {
2164
+ return interpolateVariables(value, context.variables);
1922
2165
  };
1923
2166
  const resolveLocator2 = (locator) => {
1924
2167
  if (locator.testId) return page.getByTestId(locator.testId);
@@ -1941,7 +2184,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
1941
2184
  try {
1942
2185
  switch (action.type) {
1943
2186
  case "navigate": {
1944
- const interpolated = interpolateVariables2(action.value);
2187
+ const interpolated = interpolate(action.value);
1945
2188
  const baseUrl = test.config?.web?.baseUrl ?? workflowBaseUrl;
1946
2189
  const target = resolveUrl2(interpolated, baseUrl);
1947
2190
  if (debugMode) console.log(` [DEBUG] Navigating to: ${target}`);
@@ -1955,7 +2198,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
1955
2198
  break;
1956
2199
  }
1957
2200
  case "input": {
1958
- const interpolated = interpolateVariables2(action.value);
2201
+ const interpolated = interpolate(action.value);
1959
2202
  if (debugMode) console.log(` [DEBUG] Input: ${interpolated}`);
1960
2203
  const handle = resolveLocator2(action.target);
1961
2204
  await handle.fill(interpolated);
@@ -1974,7 +2217,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
1974
2217
  break;
1975
2218
  }
1976
2219
  case "select": {
1977
- const interpolated = interpolateVariables2(action.value);
2220
+ const interpolated = interpolate(action.value);
1978
2221
  if (debugMode) console.log(` [DEBUG] Selecting: ${interpolated}`);
1979
2222
  const handle = resolveLocator2(action.target);
1980
2223
  await handle.selectOption(interpolated);
@@ -2013,7 +2256,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
2013
2256
  const handle = resolveLocator2(action.target);
2014
2257
  await handle.waitFor({ state: "visible" });
2015
2258
  if (action.value) {
2016
- const interpolated = interpolateVariables2(action.value);
2259
+ const interpolated = interpolate(action.value);
2017
2260
  const text = (await handle.textContent())?.trim() ?? "";
2018
2261
  if (!text.includes(interpolated)) {
2019
2262
  throw new Error(
@@ -2054,7 +2297,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
2054
2297
  case "setVar": {
2055
2298
  let value;
2056
2299
  if (action.value) {
2057
- value = interpolateVariables2(action.value);
2300
+ value = interpolate(action.value);
2058
2301
  } else if (action.from === "response") {
2059
2302
  throw new Error("setVar from response not yet implemented");
2060
2303
  } else if (action.from === "element") {
@@ -2072,7 +2315,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
2072
2315
  if (!context.emailClient) {
2073
2316
  throw new Error("Email client not configured");
2074
2317
  }
2075
- const mailbox = interpolateVariables2(action.mailbox);
2318
+ const mailbox = interpolate(action.mailbox);
2076
2319
  context.lastEmail = await context.emailClient.waitForEmail(mailbox, {
2077
2320
  timeout: action.timeout,
2078
2321
  subjectContains: action.subjectContains
@@ -2117,7 +2360,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
2117
2360
  if (!context.emailClient) {
2118
2361
  throw new Error("Email client not configured");
2119
2362
  }
2120
- const mailbox = interpolateVariables2(action.mailbox);
2363
+ const mailbox = interpolate(action.mailbox);
2121
2364
  await context.emailClient.clearMailbox(mailbox);
2122
2365
  break;
2123
2366
  }
@@ -2337,7 +2580,7 @@ function inferCleanupConfig(config) {
2337
2580
  async function runWorkflowWithContext(workflow, workflowFilePath, options) {
2338
2581
  const { page, executionContext, skipCleanup = false, sessionId: providedSessionId, testStartTime: providedTestStartTime } = options;
2339
2582
  const workflowDir = path.dirname(workflowFilePath);
2340
- const sessionId = providedSessionId ?? crypto2.randomUUID();
2583
+ const sessionId = providedSessionId ?? crypto4.randomUUID();
2341
2584
  const testStartTime = providedTestStartTime ?? (/* @__PURE__ */ new Date()).toISOString();
2342
2585
  console.log(`
2343
2586
  Starting workflow: ${workflow.name}`);
@@ -2356,11 +2599,7 @@ Starting workflow: ${workflow.name}`);
2356
2599
  if (workflow.variables) {
2357
2600
  for (const [key, value] of Object.entries(workflow.variables)) {
2358
2601
  if (!executionContext.variables.has(key)) {
2359
- const interpolated = value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
2360
- if (varName === "uuid") return crypto2.randomUUID().split("-")[0];
2361
- if (varName === "randomUsername") return generateRandomUsername();
2362
- return executionContext.variables.get(varName) ?? match;
2363
- });
2602
+ const interpolated = interpolateVariables(value, executionContext.variables);
2364
2603
  executionContext.variables.set(key, interpolated);
2365
2604
  }
2366
2605
  }
@@ -2390,15 +2629,7 @@ Starting workflow: ${workflow.name}`);
2390
2629
  }
2391
2630
  if (test.variables) {
2392
2631
  for (const [key, value] of Object.entries(test.variables)) {
2393
- const interpolated = value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
2394
- if (varName === "uuid") {
2395
- return crypto2.randomUUID().split("-")[0];
2396
- }
2397
- if (varName === "randomUsername") {
2398
- return generateRandomUsername();
2399
- }
2400
- return executionContext.variables.get(varName) ?? match;
2401
- });
2632
+ const interpolated = interpolateVariables(value, executionContext.variables);
2402
2633
  executionContext.variables.set(key, interpolated);
2403
2634
  }
2404
2635
  }
@@ -2537,7 +2768,7 @@ ${"=".repeat(60)}`);
2537
2768
  }
2538
2769
  async function runWorkflow(workflow, workflowFilePath, options = {}) {
2539
2770
  const workflowDir = path.dirname(workflowFilePath);
2540
- const sessionId = crypto2.randomUUID();
2771
+ const sessionId = crypto4.randomUUID();
2541
2772
  const testStartTime = (/* @__PURE__ */ new Date()).toISOString();
2542
2773
  let trackingServer = null;
2543
2774
  try {
@@ -2594,11 +2825,7 @@ async function runWorkflow(workflow, workflowFilePath, options = {}) {
2594
2825
  };
2595
2826
  if (workflow.variables) {
2596
2827
  for (const [key, value] of Object.entries(workflow.variables)) {
2597
- const interpolated = value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
2598
- if (varName === "uuid") return crypto2.randomUUID().split("-")[0];
2599
- if (varName === "randomUsername") return generateRandomUsername();
2600
- return executionContext.variables.get(varName) ?? match;
2601
- });
2828
+ const interpolated = interpolateVariables(value, executionContext.variables);
2602
2829
  executionContext.variables.set(key, interpolated);
2603
2830
  }
2604
2831
  }
@@ -2717,6 +2944,6 @@ Collected ${serverResources.length} server-tracked resources`);
2717
2944
  }
2718
2945
  }
2719
2946
 
2720
- export { ActionSchema, IntellitesterConfigSchema, LocatorSchema, TestConfigSchema, TestDefinitionSchema, cleanupConfigSchema, cleanupDiscoverSchema, collectMissingEnvVars, createAIProvider, createTestContext, generateRandomUsername, isPipelineContent, isPipelineFile, isWorkflowContent, isWorkflowFile, killServer, loadIntellitesterConfig, loadPipelineDefinition, loadTestDefinition, loadWorkflowDefinition, parseIntellitesterConfig, parsePipelineDefinition, parseTestDefinition, parseWorkflowDefinition, previewConfigSchema, runWebTest, runWorkflow, runWorkflowWithContext, setupAppwriteTracking, startTrackingServer, startWebServer };
2721
- //# sourceMappingURL=chunk-LKSREGQS.js.map
2722
- //# sourceMappingURL=chunk-LKSREGQS.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