intellitester 0.2.19 → 0.2.21

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.
@@ -4,12 +4,13 @@ var chunkARJYJVRM_cjs = require('./chunk-ARJYJVRM.cjs');
4
4
  var zod = require('zod');
5
5
  var fs2 = require('fs/promises');
6
6
  var yaml = require('yaml');
7
- var crypto2 = require('crypto');
7
+ var uniqueNamesGenerator = require('unique-names-generator');
8
+ var crypto4 = require('crypto');
9
+ var libphonenumberJs = require('libphonenumber-js');
8
10
  var path = require('path');
9
11
  var child_process = require('child_process');
10
12
  var playwright = require('playwright');
11
13
  var prompts = require('prompts');
12
- var uniqueNamesGenerator = require('unique-names-generator');
13
14
  var nodeAppwrite = require('node-appwrite');
14
15
  var anthropic = require('@llamaindex/anthropic');
15
16
  var openai = require('@llamaindex/openai');
@@ -19,7 +20,7 @@ var http = require('http');
19
20
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
20
21
 
21
22
  var fs2__default = /*#__PURE__*/_interopDefault(fs2);
22
- var crypto2__default = /*#__PURE__*/_interopDefault(crypto2);
23
+ var crypto4__default = /*#__PURE__*/_interopDefault(crypto4);
23
24
  var path__default = /*#__PURE__*/_interopDefault(path);
24
25
  var prompts__default = /*#__PURE__*/_interopDefault(prompts);
25
26
 
@@ -137,7 +138,17 @@ var appwriteVerifyEmailActionSchema = zod.z.object({
137
138
  var debugActionSchema = zod.z.object({
138
139
  type: zod.z.literal("debug")
139
140
  }).describe("Pause execution and open Playwright Inspector for debugging");
140
- var ActionSchema = zod.z.discriminatedUnion("type", [
141
+ var waitForSelectorActionSchema = zod.z.object({
142
+ type: zod.z.literal("waitForSelector"),
143
+ target: LocatorSchema,
144
+ state: zod.z.enum(["enabled", "disabled", "visible", "hidden", "attached", "detached"]).describe("Element state to wait for"),
145
+ timeout: zod.z.number().int().positive().optional().describe("Time to wait in milliseconds")
146
+ }).describe("Wait for an element to reach a specific state");
147
+ var failActionSchema = zod.z.object({
148
+ type: zod.z.literal("fail"),
149
+ message: nonEmptyString.describe("Error message to display when test fails")
150
+ }).describe("Explicitly fail the test with a custom message");
151
+ var BaseActionSchema = zod.z.discriminatedUnion("type", [
141
152
  navigateActionSchema,
142
153
  tapActionSchema,
143
154
  inputActionSchema,
@@ -158,8 +169,20 @@ var ActionSchema = zod.z.discriminatedUnion("type", [
158
169
  emailExtractLinkActionSchema,
159
170
  emailClearActionSchema,
160
171
  appwriteVerifyEmailActionSchema,
161
- debugActionSchema
172
+ debugActionSchema,
173
+ waitForSelectorActionSchema,
174
+ failActionSchema
162
175
  ]);
176
+ var conditionalActionSchema = zod.z.object({
177
+ type: zod.z.literal("conditional"),
178
+ condition: zod.z.object({
179
+ type: zod.z.enum(["exists", "notExists", "visible", "hidden"]),
180
+ target: LocatorSchema
181
+ }).describe("Condition to check"),
182
+ then: zod.z.array(BaseActionSchema).describe("Steps to execute if condition is true"),
183
+ else: zod.z.array(BaseActionSchema).optional().describe("Steps to execute if condition is false")
184
+ }).describe("Execute steps conditionally based on element state");
185
+ var ActionSchema = zod.z.union([BaseActionSchema, conditionalActionSchema]);
163
186
  var defaultsSchema = zod.z.object({
164
187
  timeout: zod.z.number().int().positive().optional().describe("Default timeout in milliseconds for all actions"),
165
188
  screenshots: zod.z.enum(["on-failure", "always", "never"]).optional().describe("When to capture screenshots during test execution")
@@ -500,6 +523,272 @@ function generateRandomUsername() {
500
523
  return username;
501
524
  }
502
525
 
526
+ // src/core/randomPhoto.ts
527
+ function generateRandomPhoto(dimensions) {
528
+ let width = 500;
529
+ let height = 500;
530
+ if (dimensions) {
531
+ if (dimensions.includes("x")) {
532
+ const [w, h] = dimensions.split("x").map((d) => parseInt(d.trim(), 10));
533
+ if (!isNaN(w) && w > 0) width = w;
534
+ if (!isNaN(h) && h > 0) height = h;
535
+ } else {
536
+ const size = parseInt(dimensions.trim(), 10);
537
+ if (!isNaN(size) && size > 0) {
538
+ width = size;
539
+ height = size;
540
+ }
541
+ }
542
+ }
543
+ return `https://picsum.photos/${width}/${height}`;
544
+ }
545
+
546
+ // src/core/fillerText.ts
547
+ var LOREM_WORDS = [
548
+ "lorem",
549
+ "ipsum",
550
+ "dolor",
551
+ "sit",
552
+ "amet",
553
+ "consectetur",
554
+ "adipiscing",
555
+ "elit",
556
+ "sed",
557
+ "do",
558
+ "eiusmod",
559
+ "tempor",
560
+ "incididunt",
561
+ "ut",
562
+ "labore",
563
+ "et",
564
+ "dolore",
565
+ "magna",
566
+ "aliqua",
567
+ "enim",
568
+ "ad",
569
+ "minim",
570
+ "veniam",
571
+ "quis",
572
+ "nostrud",
573
+ "exercitation",
574
+ "ullamco",
575
+ "laboris",
576
+ "nisi",
577
+ "aliquip",
578
+ "ex",
579
+ "ea",
580
+ "commodo",
581
+ "consequat",
582
+ "duis",
583
+ "aute",
584
+ "irure",
585
+ "in",
586
+ "reprehenderit",
587
+ "voluptate",
588
+ "velit",
589
+ "esse",
590
+ "cillum",
591
+ "fugiat",
592
+ "nulla",
593
+ "pariatur",
594
+ "excepteur",
595
+ "sint",
596
+ "occaecat",
597
+ "cupidatat",
598
+ "non",
599
+ "proident",
600
+ "sunt",
601
+ "culpa",
602
+ "qui",
603
+ "officia",
604
+ "deserunt",
605
+ "mollit",
606
+ "anim",
607
+ "id",
608
+ "est",
609
+ "laborum",
610
+ "perspiciatis",
611
+ "unde",
612
+ "omnis",
613
+ "iste",
614
+ "natus",
615
+ "error",
616
+ "voluptatem",
617
+ "accusantium",
618
+ "doloremque",
619
+ "laudantium",
620
+ "totam",
621
+ "rem",
622
+ "aperiam",
623
+ "eaque",
624
+ "ipsa",
625
+ "quae",
626
+ "ab",
627
+ "illo",
628
+ "inventore",
629
+ "veritatis",
630
+ "quasi",
631
+ "architecto",
632
+ "beatae",
633
+ "vitae",
634
+ "dicta",
635
+ "explicabo",
636
+ "nemo",
637
+ "ipsam",
638
+ "quia",
639
+ "voluptas",
640
+ "aspernatur",
641
+ "aut",
642
+ "odit",
643
+ "fugit",
644
+ "consequuntur",
645
+ "magni",
646
+ "dolores",
647
+ "eos",
648
+ "ratione",
649
+ "sequi",
650
+ "nesciunt",
651
+ "neque",
652
+ "porro",
653
+ "quisquam",
654
+ "nihil",
655
+ "impedit",
656
+ "quo",
657
+ "minus"
658
+ ];
659
+ function generateFillerText(wordCount) {
660
+ let count = 50;
661
+ if (wordCount !== void 0) {
662
+ const parsed = typeof wordCount === "string" ? parseInt(wordCount.trim(), 10) : wordCount;
663
+ if (!isNaN(parsed) && parsed > 0) {
664
+ count = parsed;
665
+ }
666
+ }
667
+ const words = [];
668
+ if (count >= 2) {
669
+ words.push("Lorem", "ipsum");
670
+ count -= 2;
671
+ }
672
+ for (let i = 0; i < count; i++) {
673
+ const randomIndex = Math.floor(Math.random() * LOREM_WORDS.length);
674
+ words.push(LOREM_WORDS[randomIndex]);
675
+ }
676
+ let result = words.join(" ");
677
+ const resultWords = result.split(" ");
678
+ const sentenceWords = [];
679
+ let sentenceLength = 0;
680
+ const nextSentenceLength = () => 8 + Math.floor(Math.random() * 5);
681
+ let targetLength = nextSentenceLength();
682
+ for (let i = 0; i < resultWords.length; i++) {
683
+ let word = resultWords[i];
684
+ if (sentenceLength === 0) {
685
+ word = word.charAt(0).toUpperCase() + word.slice(1);
686
+ }
687
+ sentenceWords.push(word);
688
+ sentenceLength++;
689
+ if (sentenceLength >= targetLength && i < resultWords.length - 1) {
690
+ sentenceWords[sentenceWords.length - 1] += ".";
691
+ sentenceLength = 0;
692
+ targetLength = nextSentenceLength();
693
+ }
694
+ }
695
+ result = sentenceWords.join(" ");
696
+ if (!result.endsWith(".")) {
697
+ result += ".";
698
+ }
699
+ return result;
700
+ }
701
+ function generateRandomEmail(domain) {
702
+ const randomPart = crypto4__default.default.randomBytes(3).toString("hex");
703
+ const emailDomain = domain?.trim() || "test.local";
704
+ return `test-${randomPart}@${emailDomain}`;
705
+ }
706
+ var COUNTRY_FORMATS = {
707
+ US: {
708
+ areaCode: () => {
709
+ const areaCodes = ["201", "212", "213", "310", "312", "404", "415", "512", "617", "702", "713", "718", "805", "818", "917"];
710
+ return areaCodes[Math.floor(Math.random() * areaCodes.length)];
711
+ },
712
+ subscriber: () => String(Math.floor(Math.random() * 9e6) + 1e6).slice(0, 7)
713
+ },
714
+ GB: {
715
+ areaCode: () => {
716
+ const areaCodes = ["20", "121", "131", "141", "151", "161", "171", "181"];
717
+ return areaCodes[Math.floor(Math.random() * areaCodes.length)];
718
+ },
719
+ subscriber: () => String(Math.floor(Math.random() * 9e7) + 1e7).slice(0, 8)
720
+ },
721
+ DE: {
722
+ areaCode: () => {
723
+ const areaCodes = ["30", "40", "69", "89", "211", "221", "341", "351"];
724
+ return areaCodes[Math.floor(Math.random() * areaCodes.length)];
725
+ },
726
+ subscriber: () => String(Math.floor(Math.random() * 9e6) + 1e6).slice(0, 7)
727
+ },
728
+ FR: {
729
+ areaCode: () => {
730
+ const areaCodes = ["1", "2", "3", "4", "5"];
731
+ return areaCodes[Math.floor(Math.random() * areaCodes.length)];
732
+ },
733
+ subscriber: () => String(Math.floor(Math.random() * 9e7) + 1e7).slice(0, 8)
734
+ },
735
+ AU: {
736
+ areaCode: () => {
737
+ const areaCodes = ["2", "3", "7", "8"];
738
+ return areaCodes[Math.floor(Math.random() * areaCodes.length)];
739
+ },
740
+ subscriber: () => String(Math.floor(Math.random() * 9e7) + 1e7).slice(0, 8)
741
+ }
742
+ };
743
+ function generateRandomPhone(country = "US") {
744
+ const countryCode = country.toUpperCase();
745
+ const format = COUNTRY_FORMATS[countryCode] || COUNTRY_FORMATS["US"];
746
+ for (let i = 0; i < 10; i++) {
747
+ const areaCode2 = format.areaCode();
748
+ const subscriber2 = format.subscriber();
749
+ const nationalNumber = areaCode2 + subscriber2;
750
+ try {
751
+ const phoneNumber = libphonenumberJs.parsePhoneNumber(nationalNumber, countryCode);
752
+ if (phoneNumber && libphonenumberJs.isValidPhoneNumber(phoneNumber.number)) {
753
+ return phoneNumber.format("E.164");
754
+ }
755
+ } catch {
756
+ }
757
+ }
758
+ const fallbackFormat = COUNTRY_FORMATS[countryCode] || COUNTRY_FORMATS["US"];
759
+ const areaCode = fallbackFormat.areaCode();
760
+ const subscriber = fallbackFormat.subscriber();
761
+ const callingCodes = {
762
+ US: "1",
763
+ GB: "44",
764
+ DE: "49",
765
+ FR: "33",
766
+ AU: "61"
767
+ };
768
+ const callingCode = callingCodes[countryCode] || "1";
769
+ return `+${callingCode}${areaCode}${subscriber}`;
770
+ }
771
+ function interpolateVariables(value, variables) {
772
+ return value.replace(/\{\{(\w+)(?::([^}]+))?\}\}/g, (match, name, param) => {
773
+ switch (name) {
774
+ case "uuid":
775
+ return crypto4__default.default.randomUUID().split("-")[0];
776
+ case "randomUsername":
777
+ return generateRandomUsername();
778
+ case "randomPhoto":
779
+ return generateRandomPhoto(param);
780
+ case "fillerText":
781
+ return generateFillerText(param);
782
+ case "randomEmail":
783
+ return generateRandomEmail(param);
784
+ case "randomPhone":
785
+ return generateRandomPhone(param);
786
+ default:
787
+ return variables.get(name) ?? match;
788
+ }
789
+ });
790
+ }
791
+
503
792
  // src/integrations/email/inbucketClient.ts
504
793
  var InbucketClient = class {
505
794
  constructor(config) {
@@ -1034,17 +1323,6 @@ async function startTrackingServer(options) {
1034
1323
 
1035
1324
  // src/executors/web/playwrightExecutor.ts
1036
1325
  var defaultScreenshotDir = path__default.default.join(process.cwd(), "artifacts", "screenshots");
1037
- function interpolateVariables(value, variables) {
1038
- return value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
1039
- if (varName === "uuid") {
1040
- return crypto2__default.default.randomUUID().split("-")[0];
1041
- }
1042
- if (varName === "randomUsername") {
1043
- return generateRandomUsername();
1044
- }
1045
- return variables.get(varName) ?? match;
1046
- });
1047
- }
1048
1326
  var resolveUrl = (value, baseUrl) => {
1049
1327
  if (!baseUrl) return value;
1050
1328
  try {
@@ -1105,6 +1383,14 @@ var runWait = async (page, action) => {
1105
1383
  }
1106
1384
  await page.waitForTimeout(action.timeout ?? 1e3);
1107
1385
  };
1386
+ var waitForCondition = async (checkFn, timeout, errorMessage) => {
1387
+ const start = Date.now();
1388
+ while (Date.now() - start < timeout) {
1389
+ if (await checkFn()) return;
1390
+ await new Promise((r) => setTimeout(r, 100));
1391
+ }
1392
+ throw new Error(errorMessage);
1393
+ };
1108
1394
  var runScroll = async (page, action) => {
1109
1395
  if (action.target) {
1110
1396
  const handle = resolveLocator(page, action.target);
@@ -1540,6 +1826,91 @@ async function executeActionWithRetry(page, action, index, options) {
1540
1826
  await page.pause();
1541
1827
  break;
1542
1828
  }
1829
+ case "waitForSelector": {
1830
+ const wsAction = action;
1831
+ const handle = resolveLocator(page, wsAction.target);
1832
+ const timeout = wsAction.timeout ?? 3e4;
1833
+ if (debugMode) {
1834
+ console.log(`[DEBUG] Waiting for element to be ${wsAction.state}:`, wsAction.target);
1835
+ }
1836
+ switch (wsAction.state) {
1837
+ case "visible":
1838
+ case "hidden":
1839
+ case "attached":
1840
+ case "detached":
1841
+ await handle.waitFor({ state: wsAction.state, timeout });
1842
+ break;
1843
+ case "enabled":
1844
+ await waitForCondition(
1845
+ () => handle.isEnabled(),
1846
+ timeout,
1847
+ `Element did not become enabled within ${timeout}ms`
1848
+ );
1849
+ break;
1850
+ case "disabled":
1851
+ await waitForCondition(
1852
+ () => handle.isDisabled(),
1853
+ timeout,
1854
+ `Element did not become disabled within ${timeout}ms`
1855
+ );
1856
+ break;
1857
+ }
1858
+ break;
1859
+ }
1860
+ case "conditional": {
1861
+ const condAction = action;
1862
+ const handle = resolveLocator(page, condAction.condition.target);
1863
+ let conditionMet = false;
1864
+ if (debugMode) {
1865
+ console.log(`[DEBUG] Checking condition ${condAction.condition.type}:`, condAction.condition.target);
1866
+ }
1867
+ try {
1868
+ switch (condAction.condition.type) {
1869
+ case "exists":
1870
+ await handle.waitFor({ state: "attached", timeout: 500 });
1871
+ conditionMet = true;
1872
+ break;
1873
+ case "notExists":
1874
+ try {
1875
+ await handle.waitFor({ state: "detached", timeout: 500 });
1876
+ conditionMet = true;
1877
+ } catch {
1878
+ conditionMet = false;
1879
+ }
1880
+ break;
1881
+ case "visible":
1882
+ conditionMet = await handle.isVisible();
1883
+ break;
1884
+ case "hidden":
1885
+ conditionMet = !await handle.isVisible();
1886
+ break;
1887
+ }
1888
+ } catch {
1889
+ conditionMet = condAction.condition.type === "notExists";
1890
+ }
1891
+ if (debugMode) {
1892
+ console.log(`[DEBUG] Condition result: ${conditionMet}`);
1893
+ }
1894
+ const stepsToRun = conditionMet ? condAction.then : condAction.else ?? [];
1895
+ for (const [nestedIdx, nestedAction] of stepsToRun.entries()) {
1896
+ if (debugMode) {
1897
+ console.log(`[DEBUG] Executing nested step ${nestedIdx + 1}: ${nestedAction.type}`);
1898
+ }
1899
+ await executeActionWithRetry(page, nestedAction, index, {
1900
+ baseUrl,
1901
+ context,
1902
+ screenshotDir,
1903
+ debugMode,
1904
+ interactive,
1905
+ aiConfig
1906
+ });
1907
+ }
1908
+ break;
1909
+ }
1910
+ case "fail": {
1911
+ const failAction = action;
1912
+ throw new Error(failAction.message);
1913
+ }
1543
1914
  default:
1544
1915
  throw new Error(`Unsupported action type: ${action.type}`);
1545
1916
  }
@@ -1584,7 +1955,7 @@ var runWebTest = async (test, options = {}) => {
1584
1955
  const headless = !(options.headed ?? false);
1585
1956
  const screenshotDir = options.screenshotDir ?? defaultScreenshotDir;
1586
1957
  const defaultTimeout = options.defaultTimeoutMs ?? 3e4;
1587
- const sessionId = crypto2__default.default.randomUUID();
1958
+ const sessionId = crypto4__default.default.randomUUID();
1588
1959
  const trackingServer = new TrackingServer();
1589
1960
  await trackingServer.start();
1590
1961
  process.env.INTELLITESTER_SESSION_ID = sessionId;
@@ -1890,19 +2261,14 @@ var getBrowser2 = (browser) => {
1890
2261
  };
1891
2262
  function interpolateWorkflowVariables(value, currentVariables, testResults) {
1892
2263
  return value.replace(/\{\{([^}]+)\}\}/g, (match, path3) => {
1893
- if (path3.includes(".")) {
2264
+ if (path3.includes(".") && !path3.includes(":")) {
1894
2265
  const [testId, _varName] = path3.split(".", 2);
1895
2266
  testResults.find((t) => t.id === testId);
1896
2267
  console.warn(`Cross-test variable interpolation {{${path3}}} not yet fully implemented`);
1897
2268
  return match;
1898
2269
  }
1899
- if (path3 === "uuid") {
1900
- return crypto2__default.default.randomUUID().split("-")[0];
1901
- }
1902
- if (path3 === "randomUsername") {
1903
- return generateRandomUsername();
1904
- }
1905
- return currentVariables.get(path3) ?? match;
2270
+ const result = interpolateVariables(`{{${path3}}}`, currentVariables);
2271
+ return result;
1906
2272
  });
1907
2273
  }
1908
2274
  async function runTestInWorkflow(test, page, context, options, _workflowDir, workflowBaseUrl) {
@@ -1918,16 +2284,8 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
1918
2284
  return value;
1919
2285
  }
1920
2286
  };
1921
- const interpolateVariables2 = (value) => {
1922
- return value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
1923
- if (varName === "uuid") {
1924
- return crypto2__default.default.randomUUID().split("-")[0];
1925
- }
1926
- if (varName === "randomUsername") {
1927
- return generateRandomUsername();
1928
- }
1929
- return context.variables.get(varName) ?? match;
1930
- });
2287
+ const interpolate = (value) => {
2288
+ return interpolateVariables(value, context.variables);
1931
2289
  };
1932
2290
  const resolveLocator2 = (locator) => {
1933
2291
  if (locator.testId) return page.getByTestId(locator.testId);
@@ -1950,7 +2308,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
1950
2308
  try {
1951
2309
  switch (action.type) {
1952
2310
  case "navigate": {
1953
- const interpolated = interpolateVariables2(action.value);
2311
+ const interpolated = interpolate(action.value);
1954
2312
  const baseUrl = test.config?.web?.baseUrl ?? workflowBaseUrl;
1955
2313
  const target = resolveUrl2(interpolated, baseUrl);
1956
2314
  if (debugMode) console.log(` [DEBUG] Navigating to: ${target}`);
@@ -1964,7 +2322,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
1964
2322
  break;
1965
2323
  }
1966
2324
  case "input": {
1967
- const interpolated = interpolateVariables2(action.value);
2325
+ const interpolated = interpolate(action.value);
1968
2326
  if (debugMode) console.log(` [DEBUG] Input: ${interpolated}`);
1969
2327
  const handle = resolveLocator2(action.target);
1970
2328
  await handle.fill(interpolated);
@@ -1983,7 +2341,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
1983
2341
  break;
1984
2342
  }
1985
2343
  case "select": {
1986
- const interpolated = interpolateVariables2(action.value);
2344
+ const interpolated = interpolate(action.value);
1987
2345
  if (debugMode) console.log(` [DEBUG] Selecting: ${interpolated}`);
1988
2346
  const handle = resolveLocator2(action.target);
1989
2347
  await handle.selectOption(interpolated);
@@ -2022,7 +2380,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
2022
2380
  const handle = resolveLocator2(action.target);
2023
2381
  await handle.waitFor({ state: "visible" });
2024
2382
  if (action.value) {
2025
- const interpolated = interpolateVariables2(action.value);
2383
+ const interpolated = interpolate(action.value);
2026
2384
  const text = (await handle.textContent())?.trim() ?? "";
2027
2385
  if (!text.includes(interpolated)) {
2028
2386
  throw new Error(
@@ -2063,7 +2421,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
2063
2421
  case "setVar": {
2064
2422
  let value;
2065
2423
  if (action.value) {
2066
- value = interpolateVariables2(action.value);
2424
+ value = interpolate(action.value);
2067
2425
  } else if (action.from === "response") {
2068
2426
  throw new Error("setVar from response not yet implemented");
2069
2427
  } else if (action.from === "element") {
@@ -2081,7 +2439,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
2081
2439
  if (!context.emailClient) {
2082
2440
  throw new Error("Email client not configured");
2083
2441
  }
2084
- const mailbox = interpolateVariables2(action.mailbox);
2442
+ const mailbox = interpolate(action.mailbox);
2085
2443
  context.lastEmail = await context.emailClient.waitForEmail(mailbox, {
2086
2444
  timeout: action.timeout,
2087
2445
  subjectContains: action.subjectContains
@@ -2126,7 +2484,7 @@ async function runTestInWorkflow(test, page, context, options, _workflowDir, wor
2126
2484
  if (!context.emailClient) {
2127
2485
  throw new Error("Email client not configured");
2128
2486
  }
2129
- const mailbox = interpolateVariables2(action.mailbox);
2487
+ const mailbox = interpolate(action.mailbox);
2130
2488
  await context.emailClient.clearMailbox(mailbox);
2131
2489
  break;
2132
2490
  }
@@ -2346,7 +2704,7 @@ function inferCleanupConfig(config) {
2346
2704
  async function runWorkflowWithContext(workflow, workflowFilePath, options) {
2347
2705
  const { page, executionContext, skipCleanup = false, sessionId: providedSessionId, testStartTime: providedTestStartTime } = options;
2348
2706
  const workflowDir = path__default.default.dirname(workflowFilePath);
2349
- const sessionId = providedSessionId ?? crypto2__default.default.randomUUID();
2707
+ const sessionId = providedSessionId ?? crypto4__default.default.randomUUID();
2350
2708
  const testStartTime = providedTestStartTime ?? (/* @__PURE__ */ new Date()).toISOString();
2351
2709
  console.log(`
2352
2710
  Starting workflow: ${workflow.name}`);
@@ -2365,11 +2723,7 @@ Starting workflow: ${workflow.name}`);
2365
2723
  if (workflow.variables) {
2366
2724
  for (const [key, value] of Object.entries(workflow.variables)) {
2367
2725
  if (!executionContext.variables.has(key)) {
2368
- const interpolated = value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
2369
- if (varName === "uuid") return crypto2__default.default.randomUUID().split("-")[0];
2370
- if (varName === "randomUsername") return generateRandomUsername();
2371
- return executionContext.variables.get(varName) ?? match;
2372
- });
2726
+ const interpolated = interpolateVariables(value, executionContext.variables);
2373
2727
  executionContext.variables.set(key, interpolated);
2374
2728
  }
2375
2729
  }
@@ -2399,15 +2753,7 @@ Starting workflow: ${workflow.name}`);
2399
2753
  }
2400
2754
  if (test.variables) {
2401
2755
  for (const [key, value] of Object.entries(test.variables)) {
2402
- const interpolated = value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
2403
- if (varName === "uuid") {
2404
- return crypto2__default.default.randomUUID().split("-")[0];
2405
- }
2406
- if (varName === "randomUsername") {
2407
- return generateRandomUsername();
2408
- }
2409
- return executionContext.variables.get(varName) ?? match;
2410
- });
2756
+ const interpolated = interpolateVariables(value, executionContext.variables);
2411
2757
  executionContext.variables.set(key, interpolated);
2412
2758
  }
2413
2759
  }
@@ -2546,7 +2892,7 @@ ${"=".repeat(60)}`);
2546
2892
  }
2547
2893
  async function runWorkflow(workflow, workflowFilePath, options = {}) {
2548
2894
  const workflowDir = path__default.default.dirname(workflowFilePath);
2549
- const sessionId = crypto2__default.default.randomUUID();
2895
+ const sessionId = crypto4__default.default.randomUUID();
2550
2896
  const testStartTime = (/* @__PURE__ */ new Date()).toISOString();
2551
2897
  let trackingServer = null;
2552
2898
  try {
@@ -2603,11 +2949,7 @@ async function runWorkflow(workflow, workflowFilePath, options = {}) {
2603
2949
  };
2604
2950
  if (workflow.variables) {
2605
2951
  for (const [key, value] of Object.entries(workflow.variables)) {
2606
- const interpolated = value.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
2607
- if (varName === "uuid") return crypto2__default.default.randomUUID().split("-")[0];
2608
- if (varName === "randomUsername") return generateRandomUsername();
2609
- return executionContext.variables.get(varName) ?? match;
2610
- });
2952
+ const interpolated = interpolateVariables(value, executionContext.variables);
2611
2953
  executionContext.variables.set(key, interpolated);
2612
2954
  }
2613
2955
  }
@@ -2736,7 +3078,12 @@ exports.cleanupDiscoverSchema = cleanupDiscoverSchema;
2736
3078
  exports.collectMissingEnvVars = collectMissingEnvVars;
2737
3079
  exports.createAIProvider = createAIProvider;
2738
3080
  exports.createTestContext = createTestContext;
3081
+ exports.generateFillerText = generateFillerText;
3082
+ exports.generateRandomEmail = generateRandomEmail;
3083
+ exports.generateRandomPhone = generateRandomPhone;
3084
+ exports.generateRandomPhoto = generateRandomPhoto;
2739
3085
  exports.generateRandomUsername = generateRandomUsername;
3086
+ exports.interpolateVariables = interpolateVariables;
2740
3087
  exports.isPipelineContent = isPipelineContent;
2741
3088
  exports.isPipelineFile = isPipelineFile;
2742
3089
  exports.isWorkflowContent = isWorkflowContent;
@@ -2757,5 +3104,5 @@ exports.runWorkflowWithContext = runWorkflowWithContext;
2757
3104
  exports.setupAppwriteTracking = setupAppwriteTracking;
2758
3105
  exports.startTrackingServer = startTrackingServer;
2759
3106
  exports.startWebServer = startWebServer;
2760
- //# sourceMappingURL=chunk-LFCMPHWU.cjs.map
2761
- //# sourceMappingURL=chunk-LFCMPHWU.cjs.map
3107
+ //# sourceMappingURL=chunk-PP666GZQ.cjs.map
3108
+ //# sourceMappingURL=chunk-PP666GZQ.cjs.map