diff --git a/lib/k6-testing/0.2.0/index.js b/lib/k6-testing/0.2.0/index.js new file mode 100644 index 0000000..cb04f9b --- /dev/null +++ b/lib/k6-testing/0.2.0/index.js @@ -0,0 +1,9 @@ +import ue from"k6/execution";function b(t,e,r){if(!t){if(r)throw new O(e);ue.test.abort(e)}}var O=class extends Error{constructor(e){super(e),this.name="AssertionFailedError"}};function de(){return typeof Deno<"u"?Deno.env.toObject():__ENV}var N=de(),x={hasValue(t){return N[t]!==void 0},boolean(t){let e=N[t]?.toLowerCase();if(e===void 0)throw new Error(`Environment variable ${t} is not set`);return e!=="false"},enum(t,e){let r=N[t]?.toLowerCase();if(r===void 0)throw new Error(`Environment variable ${t} is not set`);if(!e.includes(r))throw new Error(`Invalid value for ${t}. Must be one of: ${e.join(", ")}`);return r},number(t){let e=N[t];if(!e)throw new Error(`Environment variable ${t} is not set`);let r=Number(e);if(Number.isNaN(r)||!Number.isFinite(r))throw new Error(`Environment variable ${t} must be a valid number, got: ${e}`);if(r<0)throw new Error(`Environment variable ${t} must be a non-negative number, got: ${e}`);return r}};var L={timeout:5e3,interval:100},ge={...L,soft:!1,colorize:!0,display:"pretty",assertFn:b},R=class t{static load(e={}){let r=t.loadFromEnv();return{...ge,...e,...r}}static loadFromEnv(){let e={};return x.hasValue("K6_TESTING_COLORIZE")&&(e.colorize=x.boolean("K6_TESTING_COLORIZE")),x.hasValue("K6_TESTING_DISPLAY")&&(e.display=x.enum("K6_TESTING_DISPLAY",["inline","pretty"])),x.hasValue("K6_TESTING_TIMEOUT")&&(e.timeout=x.number("K6_TESTING_TIMEOUT")),x.hasValue("K6_TESTING_INTERVAL")&&(e.interval=x.number("K6_TESTING_INTERVAL")),e}};function v(t){if(!t||t.length<=1)return;let e=t[1],r=e.filePath,o=e.fileName,n=e.lineNumber,a=e.columnNumber,i=`${r}:${n}:${a}`;return{filePath:r,fileName:o,lineNumber:n,columnNumber:a,at:i}}function w(t){if(!t)return[];let e=t.split(` +`),r=[];for(let o=0;o",i=n.slice(u)):c>=0?(a=n.slice(0,c).trim()||"",i=n.slice(c+1,n.lastIndexOf(")")).trim()):i=n;let g=i.lastIndexOf("(");g>=0&&(i=i.slice(0,g)),i.startsWith("file://")&&(i=i.slice(7));let d=i.lastIndexOf(":");if(d===-1)continue;let y=i.lastIndexOf(":",d-1);if(y===-1)continue;let re=i.slice(0,y),ce=re.split("/").pop()??"",le=i.slice(y+1,d),pe=i.slice(d+1);r.push({functionName:a,filePath:re,fileName:ce,lineNumber:parseInt(le,10),columnNumber:parseInt(pe,10)})}return r}var ne={reset:"\x1B[0m",black:"\x1B[30m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",white:"\x1B[37m",brightBlack:"\x1B[90m",brightRed:"\x1B[91m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightBlue:"\x1B[94m",brightMagenta:"\x1B[95m",brightCyan:"\x1B[96m",brightWhite:"\x1B[97m",darkGrey:"\x1B[90m"};function h(t,e){return`${ne[e]}${t}${ne.reset}`}var s=class{static renderers=new Map;static config={colorize:!0,display:"pretty"};static register(e,r){this.renderers.set(e,r)}static getRenderer(e){return this.renderers.get(e)||new S}static configure(e){this.config={...this.config,...e}}static getConfig(){return this.config}},C=class{getReceivedPlaceholder(){return"received"}getExpectedPlaceholder(){return"expected"}renderErrorLine(e,r){let o=(n,a)=>r.colorize?h(n,a):n;return o("expect(","darkGrey")+o(this.getReceivedPlaceholder(),"red")+o(").","darkGrey")+o(this.getMatcherName(),"white")+this.renderMatcherArgs(o)}renderMatcherArgs(e){return e("()","darkGrey")}render(e,r){let o=(a,i)=>r.colorize?h(a,i):a,n=[{label:"Error",value:this.renderErrorLine(e,r),group:1},{label:"At",value:o(e.executionContext.at||"unknown location","darkGrey"),group:1},...this.getSpecificLines(e,o),{label:"Filename",value:o(e.executionContext.fileName,"darkGrey"),group:99},{label:"Line",value:o(e.executionContext.lineNumber.toString(),"darkGrey"),group:99}];return k.getFormatter(r.display).renderLines(n)}},f=class extends C{getSpecificLines(e,r){return[{label:"Received",value:r(e.received,"red"),group:2}]}},p=class extends C{getSpecificLines(e,r){return[{label:"Expected",value:r(e.expected,"green"),group:2},{label:"Received",value:r(e.received,"red"),group:2}]}renderMatcherArgs(e){return e("(","darkGrey")+e(this.getExpectedPlaceholder(),"green")+e(")","darkGrey")}},S=class{render(e,r){let o=(a,i)=>r.colorize?h(a,i):a,n=[{label:"Error",value:this.renderErrorLine(e,r),group:1},{label:"At",value:o(e.executionContext.at||"unknown location","darkGrey"),group:1},{label:"Expected",value:o(e.expected,"green"),group:2},{label:"Received",value:o(e.received,"red"),group:2},{label:"Filename",value:o(e.executionContext.fileName,"darkGrey"),group:3},{label:"Line",value:o(e.executionContext.lineNumber.toString(),"darkGrey"),group:3}];return k.getFormatter(r.display).renderLines(n)}renderErrorLine(e,r){let o=(n,a)=>r.colorize?h(n,a):n;return o("expect(","darkGrey")+o("received","red")+o(").","darkGrey")+o(`${e.matcherName}`,"white")+o("(","darkGrey")+o("expected","green")+o(")","darkGrey")}},I=class{renderLines(e){let r=Math.max(...e.filter(o=>!o.raw).map(({label:o})=>(o+":").length));return` + +`+e.map(({label:o,value:n,raw:a},i)=>{let c;if(a)c=n;else{let g=o+":";c=" ".repeat(r-g.length)+g+" "+n}let u=e[i+1];return u&&e[i].group!==u.group?c+` +`:c}).join(` +`)+` + +`}},B=class{renderLines(e){return e.map(({label:r,value:o})=>{let n=typeof o=="string"&&o.includes(" ")?`"${o}"`:o;return`${r.toLowerCase().replace(/\s+/g,"_")}=${n}`}).join(" ")}},k=class{static formatters=new Map([["pretty",new I],["inline",new B]]);static getFormatter(e){let r=this.formatters.get(e);if(!r)throw new Error(`Unknown display format: ${e}`);return r}};function J(t,e){let r=e.assertFn??b;s.configure({colorize:e.colorize,display:e.display}),s.register("toBe",new S),s.register("toBeCloseTo",new M),s.register("toBeDefined",new T),s.register("toBeFalsy",new G),s.register("toBeGreaterThan",new P),s.register("toBeGreaterThanOrEqual",new _),s.register("toBeInstanceOf",new A),s.register("toBeLessThan",new F),s.register("toBeLessThanOrEqual",new D),s.register("toBeNaN",new $),s.register("toBeNull",new V),s.register("toBeTruthy",new H),s.register("toBeUndefined",new j),s.register("toEqual",new q),s.register("toHaveLength",new U);let o={usedAssert:r,isSoft:e.soft};return{toBe(n){l("toBe",()=>Object.is(t,n),n,t,o)},toBeCloseTo(n,a=2){let i=Math.pow(10,-a)*Math.max(Math.abs(t),Math.abs(n)),c=Math.abs(t-n);l("toBeCloseTo",()=>ct!==void 0,"defined",JSON.stringify(t),o)},toBeFalsy(){l("toBeFalsy",()=>!t,"falsy",JSON.stringify(t),o)},toBeGreaterThan(n){l("toBeGreaterThan",()=>t>n,n,t,o)},toBeGreaterThanOrEqual(n){l("toBeGreaterThanOrEqual",()=>t>=n,n,t,o)},toBeInstanceOf(n){l("toBeInstanceOf",()=>t instanceof n,n.name,t.constructor.name,o)},toBeLessThan(n){l("toBeLessThan",()=>tt<=n,n,t,o)},toBeNaN(){l("toBeNaN",()=>isNaN(t),"NaN",JSON.stringify(t),o)},toBeNull(){l("toBeNull",()=>t===null,"null",JSON.stringify(t),o)},toBeTruthy(){l("toBeTruthy",()=>!!t,"truthy",JSON.stringify(t),o)},toBeUndefined(){l("toBeUndefined",()=>t===void 0,"undefined",JSON.stringify(t),o)},toEqual(n){l("toEqual",()=>oe(t,n),JSON.stringify(n),JSON.stringify(t),o)},toHaveLength(n){l("toHaveLength",()=>t.length===n,n.toString(),t.length.toString(),o)}}}function l(t,e,r,o,{usedAssert:n,isSoft:a,matcherSpecific:i={}}){let c=fe(t,r,o,i);n(e(),s.getRenderer(t).render(c,s.getConfig()),a)}function fe(t,e,r,o={}){let n=w(new Error().stack),a=v(n);if(!a)throw new Error("k6 failed to capture execution context");return{executionContext:a,matcherName:t,expected:typeof e=="string"?e:JSON.stringify(e),received:JSON.stringify(r),matcherSpecific:o}}var M=class extends p{getMatcherName(){return"toBeCloseTo"}getSpecificLines(e,r){let o=e.matcherSpecific;return[{label:"Expected precision",value:r(o.precision.toString(),"green"),group:3},{label:"Expected difference",value:"< "+r(`${o.expectedDifference}`,"green"),group:3},{label:"Received difference",value:r(o.difference.toString(),"red"),group:3}]}renderMatcherArgs(e){return e("(","darkGrey")+e("expected","green")+e(", ","darkGrey")+e("precision","white")+e(")","darkGrey")}},T=class extends f{getMatcherName(){return"toBeDefined"}},G=class extends f{getMatcherName(){return"toBeFalsy"}},P=class extends p{getMatcherName(){return"toBeGreaterThan"}getSpecificLines(e,r){return[{label:"Expected",value:"> "+r(e.expected,"green"),group:3},{label:"Received",value:r(e.received,"red"),group:3}]}},_=class extends p{getMatcherName(){return"toBeGreaterThanOrEqual"}getSpecificLines(e,r){return[{label:"Expected",value:">= "+r(e.expected,"green"),group:3},{label:"Received",value:r(e.received,"red"),group:3}]}},A=class extends p{getMatcherName(){return"toBeInstanceOf"}getSpecificLines(e,r){return[{label:"Expected constructor",value:r(e.expected,"green"),group:3},{label:"Received constructor",value:r(e.received,"red"),group:3}]}},F=class extends p{getMatcherName(){return"toBeLessThan"}getSpecificLines(e,r){return[{label:"Expected",value:"< "+r(e.expected,"green"),group:3},{label:"Received",value:r(e.received,"red"),group:3}]}},D=class extends p{getMatcherName(){return"toBeLessThanOrEqual"}getSpecificLines(e,r){return[{label:"Expected",value:"<= "+r(e.expected,"green"),group:3},{label:"Received",value:r(e.received,"red"),group:3}]}},$=class extends f{getMatcherName(){return"toBeNaN"}},V=class extends f{getMatcherName(){return"toBeNull"}},H=class extends f{getMatcherName(){return"toBeTruthy"}},j=class extends f{getMatcherName(){return"toBeUndefined"}},q=class extends p{getMatcherName(){return"toEqual"}getSpecificLines(e,r){return[{label:"Expected",value:r(e.expected,"green"),group:3},{label:"Received",value:r(e.received,"red"),group:3}]}},U=class extends p{getMatcherName(){return"toHaveLength"}getSpecificLines(e,r){return[{label:"Expected length",value:r(e.expected,"green"),group:3},{label:"Received length",value:r(e.received,"red"),group:3},{label:"Received array",value:r(e.matcherSpecific?.receivedArray,"red"),group:3}]}};function oe(t,e){if(t===e)return!0;if(t===null||e===null||typeof t!="object"||typeof e!="object")return!1;let r=Object.keys(t),o=Object.keys(e);return r.length!==o.length?!1:r.every(n=>o.includes(n)&&oe(t[n],e[n]))}function te(t,e){let r=e.assertFn??b,o=e.soft??!1,n={timeout:e.timeout,interval:e.interval};s.configure({colorize:e.colorize,display:e.display}),s.register("toBeChecked",new K),s.register("toBeDisabled",new W),s.register("toBeEditable",new Y),s.register("toBeEnabled",new Z),s.register("toBeHidden",new Q),s.register("toBeVisible",new X),s.register("toHaveValue",new z);let a={locator:t,retryConfig:n,usedAssert:r,isSoft:o};return{async toBeChecked(i=n){await E("toBeChecked",async()=>await t.isChecked(),"checked","unchecked",{...a,options:i})},async toBeDisabled(i=n){await E("toBeDisabled",async()=>await t.isDisabled(),"disabled","enabled",{...a,options:i})},async toBeEditable(i=n){await E("toBeEditable",async()=>await t.isEditable(),"editable","uneditable",{...a,options:i})},async toBeEnabled(i=n){await E("toBeEnabled",async()=>await t.isEnabled(),"enabled","disabled",{...a,options:i})},async toBeHidden(i=n){await E("toBeHidden",async()=>await t.isHidden(),"hidden","visible",{...a,options:i})},async toBeVisible(i=n){await E("toBeVisible",async()=>await t.isVisible(),"visible","hidden",{...a,options:i})},async toHaveValue(i,c=n){let u=w(new Error().stack),g=v(u);if(!g)throw new Error("k6 failed to capture execution context");let d={executionContext:g,matcherName:"toHaveValue",expected:i,received:"unknown"};try{await ie(async()=>{let y=await t.inputValue();r(i===y,s.getRenderer("toHaveValue").render(d,s.getConfig()),o)},{...n,...c})}catch{r(!1,s.getRenderer("toHaveValue").render(d,s.getConfig()),o)}}}}function xe(t,e,r,o={}){let n=w(new Error().stack),a=v(n);if(!a)throw new Error("k6 failed to capture execution context");return{executionContext:a,matcherName:t,expected:e,received:r,...o}}async function E(t,e,r,o,{locator:n,retryConfig:a,usedAssert:i,isSoft:c,options:u={}}){let g=xe(t,r,o,{matcherSpecific:{locator:n,timeout:u.timeout}});try{await ie(async()=>{let d=await e();if(!d)throw new Error("matcher failed");i(d,s.getRenderer(t).render(g,s.getConfig()),c)},{...a,...u})}catch{i(!1,s.getRenderer(t).render(g,s.getConfig()),c)}}var m=class extends f{getMatcherName(){return`toBe${this.state[0].toUpperCase()}${this.state.slice(1)}`}getReceivedPlaceholder(){return"locator"}getSpecificLines(e,r){return[{label:"Expected",value:this.state,group:3},{label:"Received",value:this.oppositeState,group:3},{label:"Call log",value:"",group:3},{label:"",value:r(` - expect.toBe${this.state[0].toUpperCase()}${this.state.slice(1)} with timeout ${e.matcherSpecific?.timeout}ms`,"darkGrey"),group:3,raw:!0},{label:"",value:r(" - waiting for locator","darkGrey"),group:3,raw:!0}]}},K=class extends m{state="checked";oppositeState="unchecked"},W=class extends m{state="disabled";oppositeState="enabled"},Y=class extends m{state="editable";oppositeState="uneditable"},Z=class extends m{state="enabled";oppositeState="disabled"},Q=class extends m{state="hidden";oppositeState="visible"},X=class extends m{state="visible";oppositeState="hidden"},z=class extends p{getMatcherName(){return"toHaveValue"}getSpecificLines(e,r){return[{label:"Expected",value:r(e.expected,"green"),group:3},{label:"Received",value:r(e.received,"red"),group:3},{label:"Call log",value:"",group:3},{label:"",value:r(` - expect.toHaveValue with timeout ${e.matcherSpecific?.timeout}ms`,"darkGrey"),group:3,raw:!0},{label:"",value:r(" - waiting for locator","darkGrey"),group:3,raw:!0}]}};async function ie(t,e={}){let r=e.timeout??L.timeout,o=e.interval??L.interval,n=e._now??(()=>Date.now()),a=e._sleep??(c=>new Promise(u=>setTimeout(u,c))),i=n();for(;n()-ie.every(n=>n in o);return t!=null&&typeof t=="object"&&r(t)}export{h as colorize,me as expect}; +//# sourceMappingURL=index.js.map diff --git a/lib/k6-testing/0.2.0/index.js.map b/lib/k6-testing/0.2.0/index.js.map new file mode 100644 index 0000000..a932573 --- /dev/null +++ b/lib/k6-testing/0.2.0/index.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../assert.ts", "../environment.ts", "../config.ts", "../execution.ts", "../stacktrace.ts", "../colors.ts", "../render.ts", "../expectNonRetrying.ts", "../expectRetrying.ts", "../expect.ts"], + "sourcesContent": ["// NOTE (@oleiade): This is a shim for the k6/execution module, meaning that\n// imports of k6-execution-shim will be replaced with k6/execution in the\n// output bundle file.\n//\n// This allows us to avoid relying on the k6/execution module in the Deno runtime,\n// which is not compatible with the k6 runtime. Instead replacing it with a mock\n// implementation that does not abort the test. While making sure that we do replace\n// it with the real k6/execution module when bundling for the k6 runtime.\n//\n// It allows us to use the `deno test` command and unit tests in the Deno runtime. While\n// still being able to use the `k6 run` command and tests in the k6 runtime.\nimport exec from \"k6-execution-shim\";\n\n/**\n * assert is a function that checks a condition and fails the test if the condition is false.\n *\n * As a default, a failing assertion will immediately abort the whole test, exit with code 108, and\n * display an error message. If you want to continue the test after a failing assertion, you can pass\n * `true` as the third argument to `assert`.\n *\n * @param condition condition to assert the truthyness of\n * @param message the message to display if the condition is false\n * @param soft if true, the assertion will mark the test as failed without interrupting the execution\n */\nexport function assert(condition: boolean, message: string, soft?: boolean) {\n if (condition) return;\n\n if (soft) {\n throw new AssertionFailedError(message);\n } else {\n // This will the k6-execution-shim module's abort method in the Deno runtime.\n // It will instead be replaced with the k6/execution module's abort method\n // in the output bundle file produced by esbuild specifically for the k6 runtime.\n exec.test.abort(message);\n }\n}\n\n/**\n * This indicates that an assertion failed.\n *\n * It is used to express a soft assertion's failure, as throwing will not abort the\n * test, and will instead fail the iteration.\n */\nexport class AssertionFailedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AssertionFailedError\";\n }\n}\n", "// In the k6 runtime, the __ENV object is available and contains the environment variables.\nexport declare const __ENV: Record;\n\n/**\n * Environment interface that matches the shape of k6's __ENV object.\n */\nexport interface Environment {\n [key: string]: string | undefined;\n}\n\nfunction getEnvironment(): Environment {\n // When running in Deno\n if (typeof Deno !== \"undefined\") {\n return Deno.env.toObject();\n }\n\n // When running in k6\n return __ENV;\n}\n\n// Export a singleton instance of the environment object\nexport const env: Environment = getEnvironment();\n\n/**\n * Environment variable parser\n */\nexport const envParser = {\n /**\n * Check if an environment variable is set\n */\n hasValue(key: string): boolean {\n return env[key] !== undefined;\n },\n\n /**\n * Parse a boolean environment variable\n * \"false\" (case insensitive) -> false\n * anything else -> true\n * @throws if value is undefined\n */\n boolean(key: string): boolean {\n const value = env[key]?.toLowerCase();\n if (value === undefined) {\n throw new Error(`Environment variable ${key} is not set`);\n }\n return value !== \"false\";\n },\n\n /**\n * Parse an environment variable that should match specific values\n * @throws if value is undefined or doesn't match allowed values\n */\n enum(key: string, allowedValues: T[]): T {\n const value = env[key]?.toLowerCase() as T;\n if (value === undefined) {\n throw new Error(`Environment variable ${key} is not set`);\n }\n if (!allowedValues.includes(value)) {\n throw new Error(\n `Invalid value for ${key}. Must be one of: ${allowedValues.join(\", \")}`,\n );\n }\n return value;\n },\n\n /**\n * Parses an environment variable as a non-negative number.\n * @param name The name of the environment variable\n * @throws Error if the value is not a valid non-negative number\n * @returns The parsed number value\n */\n number(name: string): number {\n const value = env[name];\n if (!value) {\n throw new Error(`Environment variable ${name} is not set`);\n }\n\n const parsed = Number(value);\n if (Number.isNaN(parsed) || !Number.isFinite(parsed)) {\n throw new Error(\n `Environment variable ${name} must be a valid number, got: ${value}`,\n );\n }\n\n if (parsed < 0) {\n throw new Error(\n `Environment variable ${name} must be a non-negative number, got: ${value}`,\n );\n }\n\n return parsed;\n },\n};\n", "import { assert } from \"./assert.ts\";\nimport { envParser } from \"./environment.ts\";\n\n/**\n * Options that can be set for the expect function.\n */\nexport interface ExpectConfig extends RenderConfig, RetryConfig {\n /**\n * Setting this option to true will make the assertions performed by expect\n * to be always soft, meaning that they will not fail the test if the assertion\n * is not met.\n */\n soft: boolean;\n\n /**\n * Optional custom assertion function to be used instead of the default assert function.\n *\n * This function should have the same signature as the assert function.\n */\n assertFn?: (...args: Parameters) => void;\n}\n\n/**\n * The configuration for the retry behavior.\n */\nexport interface RetryConfig {\n /**\n * Maximum amount of time to retry in milliseconds.\n * @default 5000\n */\n timeout?: number;\n\n /**\n * Time between retries in milliseconds.\n * @default 100\n */\n interval?: number;\n}\n\nexport const DEFAULT_RETRY_OPTIONS: Required = {\n // 5 seconds default timeout\n timeout: 5000,\n // 100ms between retries\n interval: 100,\n};\n\n/**\n * The configuration for the renderer.\n */\nexport interface RenderConfig {\n /**\n * Setting this option to false will disable the colorization of the output of the\n * expect function. The default is true.\n */\n colorize: boolean;\n\n /**\n * Expectations can be displayed in two different ways: inline or pretty.\n * The default is pretty.\n *\n * When displayed inline, the expectation will be displayed in a single line, to\n * make it easier to interpret the output when written to logs.\n *\n * When displayed pretty, the expectation will be displayed in a more human-readable\n * format, with each part of the expectation in a separate line.\n */\n display: DisplayFormat;\n}\n\n/**\n * The display format to use.\n *\n * \"pretty\" is the default format and outputs in a human readable format with aligned columns.\n * \"inline\" is a logfmt style format that outputs in a single line.\n */\nexport type DisplayFormat = \"inline\" | \"pretty\";\n\n/**\n * Default configuration values, without any environment overrides\n */\nexport const DEFAULT_CONFIG: ExpectConfig = {\n ...DEFAULT_RETRY_OPTIONS,\n soft: false,\n colorize: true,\n display: \"pretty\",\n assertFn: assert,\n};\n\n/**\n * Configuration loader that handles different sources of configuration\n * with clear precedence rules\n */\nexport class ConfigLoader {\n /**\n * Loads configuration with the following precedence (highest to lowest):\n * 1. Environment variables\n * 2. Explicit configuration passed to the function\n * 3. Default values\n */\n static load(explicitConfig: Partial = {}): ExpectConfig {\n const envConfig = ConfigLoader.loadFromEnv();\n\n return {\n ...DEFAULT_CONFIG,\n ...explicitConfig,\n ...envConfig,\n };\n }\n\n /**\n * Loads configuration from environment variables\n * Returns only the values that are explicitly set in the environment\n */\n private static loadFromEnv(): Partial {\n const config: Partial = {};\n\n // Load colorize from environment variable\n if (envParser.hasValue(\"K6_TESTING_COLORIZE\")) {\n config.colorize = envParser.boolean(\"K6_TESTING_COLORIZE\");\n }\n\n // Load display from environment variable\n if (envParser.hasValue(\"K6_TESTING_DISPLAY\")) {\n config.display = envParser.enum(\n \"K6_TESTING_DISPLAY\",\n [\"inline\", \"pretty\"],\n );\n }\n\n // Load timeout from environment variable\n if (envParser.hasValue(\"K6_TESTING_TIMEOUT\")) {\n config.timeout = envParser.number(\"K6_TESTING_TIMEOUT\");\n }\n\n // Load interval from environment variable\n if (envParser.hasValue(\"K6_TESTING_INTERVAL\")) {\n config.interval = envParser.number(\"K6_TESTING_INTERVAL\");\n }\n\n return config;\n }\n}\n", "import type { StackFrame, Stacktrace } from \"./stacktrace.ts\";\n\n/**\n * Holds the execution context for a given assertion, and is used to render the error message.\n */\nexport interface ExecutionContext {\n /**\n * The file path where the assertion was called. e.g. \"/some/path.ts\".\n */\n filePath: string;\n\n /**\n * The file name where the assertion was called. e.g. \"path.ts\".\n */\n fileName: string;\n\n /**\n * The line number within `filename` where the assertion was called. e.g. 42.\n */\n lineNumber: number;\n\n /**\n * The column number within `filename` where the assertion was called. e.g. 24.\n */\n columnNumber: number;\n\n /**\n * The location of the assertion. e.g. \"/some/path.ts:124:12\".\n */\n at: string;\n\n /**\n * The stacktrace this execution context was captured from.\n */\n stacktrace?: Stacktrace;\n}\n\n/**\n * Captures the execution context from the provided stacktrace.\n *\n * If no stacktrace is provided, the execution context is not captured and the function returns `undefined`.\n *\n * @param stacktrace - The stacktrace to capture the execution context from, as returned by `new Error().stack`.\n * @returns the execution context\n */\nexport function captureExecutionContext(\n st: Stacktrace,\n): ExecutionContext | undefined {\n // In order to capture a useful execution context, we need at least 2 stack frames.\n // The first frame is the current function, the second frame is the one that called it.\n // In most cases, the first frame will be the matcher function itself, which is not useful to users.\n // What we want is the second frame, which is the one that called the matcher.\n if (!st || st.length <= 1) {\n return undefined;\n }\n\n const stackFrame: StackFrame = st[1];\n\n const filePath = stackFrame.filePath;\n const fileName = stackFrame.fileName;\n const lineNumber = stackFrame.lineNumber;\n const columnNumber = stackFrame.columnNumber;\n const at = `${filePath}:${lineNumber}:${columnNumber}`;\n\n return {\n filePath,\n fileName,\n lineNumber,\n columnNumber,\n at,\n };\n}\n", "/**\n * A stacktrace, represented as an array of stack frames.\n */\nexport type Stacktrace = StackFrame[];\n\n/**\n * A single frame in a stacktrace.\n */\nexport interface StackFrame {\n // Name of the function, if any.\n functionName: string;\n\n // The full path to the file, if any.\n filePath: string;\n\n // Name of the file, if any.\n fileName: string;\n\n // Line number in the file, if any.\n lineNumber: number;\n\n // Column number in the file, if any.\n columnNumber: number;\n}\n\n/**\n * Parses a stacktrace from a string.\n *\n * If no stacktrace is provided, returns an empty array.\n *\n * @param stack the stacktrace to parse, as returned by `new Error().stack`\n * @returns the parsed stacktrace\n */\nexport function parseStackTrace(stack?: string): Stacktrace {\n // If no stacktrace is provided, return an empty array.\n if (!stack) return [];\n\n const lines = stack.split(\"\\n\");\n const frames: StackFrame[] = [];\n\n for (let i = 0; i < lines.length; i++) {\n let lineStr = lines[i].trim();\n\n // Skip the first line if it's \"Error\" or any line that doesn't start with \"at \"\n if (i === 0 && lineStr.startsWith(\"Error\")) continue;\n if (!lineStr.startsWith(\"at \")) continue;\n\n // Remove \"at \"\n lineStr = lineStr.slice(3).trim();\n\n // 1. Separate the function name from file info\n let functionName = \"\";\n let fileInfo = lineStr;\n const firstParenIndex = lineStr.indexOf(\"(\");\n const fileProtocolIndex = lineStr.indexOf(\"file://\");\n\n if (fileProtocolIndex === 0) {\n functionName = \"\";\n fileInfo = lineStr.slice(fileProtocolIndex);\n } else if (firstParenIndex >= 0) {\n functionName = lineStr.slice(0, firstParenIndex).trim() || \"\";\n fileInfo = lineStr\n .slice(firstParenIndex + 1, lineStr.lastIndexOf(\")\"))\n .trim();\n } else {\n fileInfo = lineStr;\n }\n\n // 2. Remove any trailing \"(X)\" offset\n const offsetParenIndex = fileInfo.lastIndexOf(\"(\");\n if (offsetParenIndex >= 0) {\n fileInfo = fileInfo.slice(0, offsetParenIndex);\n }\n\n // 3. Handle file:// protocol\n if (fileInfo.startsWith(\"file://\")) {\n fileInfo = fileInfo.slice(7);\n }\n\n // 4. Separate file, line, and column\n const lastColon = fileInfo.lastIndexOf(\":\");\n if (lastColon === -1) continue; // Malformed\n const secondLastColon = fileInfo.lastIndexOf(\":\", lastColon - 1);\n if (secondLastColon === -1) continue; // Malformed\n\n const filePath = fileInfo.slice(0, secondLastColon);\n const fileName = filePath.split(\"/\").pop() ?? \"\";\n const lineNumberStr = fileInfo.slice(secondLastColon + 1, lastColon);\n const columnNumberStr = fileInfo.slice(lastColon + 1);\n\n frames.push({\n functionName,\n filePath,\n fileName,\n lineNumber: parseInt(lineNumberStr, 10),\n columnNumber: parseInt(columnNumberStr, 10),\n });\n }\n\n return frames;\n}\n", "export const ANSI_COLORS = {\n reset: \"\\x1b[0m\",\n\n // Standard Colors\n black: \"\\x1b[30m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n blue: \"\\x1b[34m\",\n magenta: \"\\x1b[35m\",\n cyan: \"\\x1b[36m\",\n white: \"\\x1b[37m\",\n\n // Bright Colors\n brightBlack: \"\\x1b[90m\",\n brightRed: \"\\x1b[91m\",\n brightGreen: \"\\x1b[92m\",\n brightYellow: \"\\x1b[93m\",\n brightBlue: \"\\x1b[94m\",\n brightMagenta: \"\\x1b[95m\",\n brightCyan: \"\\x1b[96m\",\n brightWhite: \"\\x1b[97m\",\n\n // Dark Colors\n darkGrey: \"\\x1b[90m\",\n} as const;\n\nexport function colorize(\n text: string | undefined,\n color: keyof typeof ANSI_COLORS,\n): string {\n return `${ANSI_COLORS[color]}${text}${ANSI_COLORS.reset}`;\n}\n", "import type { ExecutionContext } from \"./execution.ts\";\nimport { type ANSI_COLORS, colorize } from \"./colors.ts\";\nimport type { DisplayFormat, RenderConfig } from \"./config.ts\";\n\n/**\n * The interface that all matchers error renderers must implement.\n */\nexport interface MatcherErrorRenderer {\n render(info: RenderedErrorInfo, config: RenderConfig): string;\n}\n\n/**\n * The data structure holding all info to be rendered when a matcher fails.\n *\n * Because some matchers require additional info to be rendered, we use a generic type\n * to allow for additional properties to be added to the info structure.\n */\nexport interface MatcherErrorInfo extends RenderedErrorInfo {\n matcherSpecific?: Record;\n}\n\n/**\n * The data structure holding all info to be rendered.\n */\nexport interface RenderedErrorInfo {\n // The execution context of the assertion, holding the file name, line number, and column number\n // where the assertion was called.\n executionContext: ExecutionContext;\n\n // This would be something like: \"expect(received).toBe(expected)\"\n // plus color info or text appended for extra context.\n matcherName: string;\n\n // The underlying operation that was used to make the assertion. e.g. \"Object.is\".\n matcherOperation?: string;\n\n // The expected value. e.g. \"false\".\n expected: string;\n\n // The received value. e.g. \"true\".\n received: string;\n\n // The stacktrace of the assertion. e.g. \"Error\".\n stacktrace?: string;\n}\n\n/**\n * A registry of matchers error renderers.\n */\nexport class MatcherErrorRendererRegistry {\n private static renderers: Map = new Map();\n private static config: RenderConfig = { colorize: true, display: \"pretty\" };\n\n static register(matcherName: string, renderer: MatcherErrorRenderer) {\n this.renderers.set(matcherName, renderer);\n }\n\n static getRenderer(matcherName: string): MatcherErrorRenderer {\n return this.renderers.get(matcherName) || new DefaultMatcherErrorRenderer();\n }\n\n static configure(config: RenderConfig) {\n this.config = { ...this.config, ...config };\n }\n\n static getConfig(): RenderConfig {\n return this.config;\n }\n}\n\n/**\n * Base class for all matcher error renderers that implements common functionality\n */\nexport abstract class BaseMatcherErrorRenderer implements MatcherErrorRenderer {\n protected getReceivedPlaceholder(): string {\n return \"received\";\n }\n\n protected getExpectedPlaceholder(): string {\n return \"expected\";\n }\n\n protected abstract getSpecificLines(\n info: MatcherErrorInfo,\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): LineGroup[];\n\n protected abstract getMatcherName(): string;\n\n protected renderErrorLine(\n _: RenderedErrorInfo,\n config: RenderConfig,\n ): string {\n const maybeColorize = (text: string, color: keyof typeof ANSI_COLORS) =>\n config.colorize ? colorize(text, color) : text;\n\n return maybeColorize(`expect(`, \"darkGrey\") +\n maybeColorize(this.getReceivedPlaceholder(), \"red\") +\n maybeColorize(`).`, \"darkGrey\") +\n maybeColorize(this.getMatcherName(), \"white\") +\n this.renderMatcherArgs(maybeColorize);\n }\n\n protected renderMatcherArgs(\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): string {\n return maybeColorize(`()`, \"darkGrey\");\n }\n\n render(info: MatcherErrorInfo, config: RenderConfig): string {\n const maybeColorize = (text: string, color: keyof typeof ANSI_COLORS) =>\n config.colorize ? colorize(text, color) : text;\n\n const lines: LineGroup[] = [\n { label: \"Error\", value: this.renderErrorLine(info, config), group: 1 },\n {\n label: \"At\",\n value: maybeColorize(\n info.executionContext.at || \"unknown location\",\n \"darkGrey\",\n ),\n group: 1,\n },\n\n ...this.getSpecificLines(info, maybeColorize),\n\n {\n label: \"Filename\",\n value: maybeColorize(info.executionContext.fileName, \"darkGrey\"),\n group: 99,\n },\n {\n label: \"Line\",\n value: maybeColorize(\n info.executionContext.lineNumber.toString(),\n \"darkGrey\",\n ),\n group: 99,\n },\n ];\n\n return DisplayFormatRegistry.getFormatter(config.display).renderLines(\n lines,\n );\n }\n}\n\n/**\n * Base class for matchers that only show the received value\n */\nexport abstract class ReceivedOnlyMatcherRenderer\n extends BaseMatcherErrorRenderer {\n protected getSpecificLines(\n info: MatcherErrorInfo,\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): LineGroup[] {\n return [\n {\n label: \"Received\",\n value: maybeColorize(info.received, \"red\"),\n group: 2,\n },\n ];\n }\n}\n\n/**\n * Base class for matchers that show both expected and received values\n */\nexport abstract class ExpectedReceivedMatcherRenderer\n extends BaseMatcherErrorRenderer {\n protected getSpecificLines(\n info: MatcherErrorInfo,\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): LineGroup[] {\n return [\n {\n label: \"Expected\",\n value: maybeColorize(info.expected, \"green\"),\n group: 2,\n },\n {\n label: \"Received\",\n value: maybeColorize(info.received, \"red\"),\n group: 2,\n },\n ];\n }\n\n protected override renderMatcherArgs(\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): string {\n return maybeColorize(`(`, \"darkGrey\") +\n maybeColorize(this.getExpectedPlaceholder(), \"green\") +\n maybeColorize(`)`, \"darkGrey\");\n }\n}\n\n/**\n * The default matcher error renderer.\n */\nexport class DefaultMatcherErrorRenderer implements MatcherErrorRenderer {\n render(info: RenderedErrorInfo, config: RenderConfig): string {\n const maybeColorize = (text: string, color: keyof typeof ANSI_COLORS) =>\n config.colorize ? colorize(text, color) : text;\n const lines: LineGroup[] = [\n { label: \"Error\", value: this.renderErrorLine(info, config), group: 1 },\n {\n label: \"At\",\n value: maybeColorize(\n info.executionContext.at || \"unknown location\",\n \"darkGrey\",\n ),\n group: 1,\n },\n\n {\n label: \"Expected\",\n value: maybeColorize(info.expected, \"green\"),\n group: 2,\n },\n {\n label: \"Received\",\n value: maybeColorize(info.received, \"red\"),\n group: 2,\n },\n\n {\n label: \"Filename\",\n value: maybeColorize(info.executionContext.fileName, \"darkGrey\"),\n group: 3,\n },\n {\n label: \"Line\",\n value: maybeColorize(\n info.executionContext.lineNumber.toString(),\n \"darkGrey\",\n ),\n group: 3,\n },\n ];\n\n return DisplayFormatRegistry.getFormatter(config.display).renderLines(\n lines,\n );\n }\n\n protected renderErrorLine(\n info: RenderedErrorInfo,\n config: RenderConfig,\n ): string {\n const maybeColorize = (text: string, color: keyof typeof ANSI_COLORS) =>\n config.colorize ? colorize(text, color) : text;\n return maybeColorize(`expect(`, \"darkGrey\") +\n maybeColorize(`received`, \"red\") +\n maybeColorize(`).`, \"darkGrey\") +\n maybeColorize(`${info.matcherName}`, \"white\") +\n maybeColorize(`(`, \"darkGrey\") +\n maybeColorize(`expected`, \"green\") +\n maybeColorize(`)`, \"darkGrey\");\n }\n}\n\ninterface DisplayFormatRenderer {\n renderLines(lines: LineGroup[]): string;\n}\n\n/**\n * Pretty format renderer that groups and aligns output\n *\n * Note that any stylization of the lines, such as colorization is expected to\n * be done by the caller.\n */\nclass PrettyFormatRenderer implements DisplayFormatRenderer {\n renderLines(lines: LineGroup[]): string {\n const maxLabelWidth = Math.max(\n ...lines\n .filter((line) => !line.raw)\n .map(({ label }: { label: string }) => (label + \":\").length),\n );\n\n return \"\\n\\n\" + lines\n .map(({ label, value, raw }, index) => {\n let line: string;\n if (raw) {\n line = value;\n } else {\n const labelWithColon = label + \":\";\n const spaces = \" \".repeat(maxLabelWidth - labelWithColon.length);\n line = spaces + labelWithColon + \" \" + value;\n }\n\n // Add newlines before a new group of lines (except for the first group)\n const nextLine = lines[index + 1];\n if (nextLine && lines[index].group !== nextLine.group) {\n return line + \"\\n\";\n }\n return line;\n })\n .join(\"\\n\") +\n \"\\n\\n\";\n }\n}\n\n/**\n * Inline format renderer that outputs in logfmt style\n */\nclass InlineFormatRenderer implements DisplayFormatRenderer {\n renderLines(lines: LineGroup[]): string {\n return lines\n .map(({ label, value }) => {\n // Escape any spaces or special characters in the value\n const escapedValue = typeof value === \"string\"\n ? value.includes(\" \") ? `\"${value}\"` : value\n : value;\n // Convert label to lowercase and replace spaces with underscores\n const escapedLabel = label.toLowerCase().replace(/\\s+/g, \"_\");\n return `${escapedLabel}=${escapedValue}`;\n })\n .join(\" \");\n }\n}\n\nclass DisplayFormatRegistry {\n private static formatters: Map =\n new Map([\n [\"pretty\", new PrettyFormatRenderer()],\n [\"inline\", new InlineFormatRenderer()],\n ]);\n\n static getFormatter(format: DisplayFormat): DisplayFormatRenderer {\n const formatter = this.formatters.get(format);\n if (!formatter) {\n throw new Error(`Unknown display format: ${format}`);\n }\n return formatter;\n }\n}\n\n/**\n * A line with a label and a value.\n *\n * The label is the text before the colon, and the value is the text after the colon.\n *\n * The group number is used to align the lines at the same column and group them into\n * newline separated sections.\n */\nexport interface LineGroup {\n // The label of the line.\n label: string;\n\n // The value of the line.\n value: string;\n\n // The group number of the line. Lines with the same group number are aligned at the same column.\n group?: number;\n\n // If true, the line is not formatted and is output as raw text.\n raw?: boolean;\n}\n", "import { assert } from \"./assert.ts\";\nimport type { ANSI_COLORS } from \"./colors.ts\";\nimport type { ExpectConfig } from \"./config.ts\";\nimport { captureExecutionContext } from \"./execution.ts\";\nimport { parseStackTrace } from \"./stacktrace.ts\";\nimport {\n DefaultMatcherErrorRenderer,\n ExpectedReceivedMatcherRenderer,\n type LineGroup,\n type MatcherErrorInfo,\n MatcherErrorRendererRegistry,\n ReceivedOnlyMatcherRenderer,\n} from \"./render.ts\";\n\nexport interface NonRetryingExpectation {\n /**\n * Asserts that the value is equal to the expected value.\n *\n * @param expected the expected value\n */\n toBe(expected: unknown): void;\n\n /**\n * Asserts that the value is close to the expected value with a given precision.\n *\n * @param expected the expected value\n * @param precision the number of decimal places to consider\n */\n toBeCloseTo(expected: number, precision?: number): void;\n\n /**\n * Asserts that the value is not `undefined`.\n */\n toBeDefined(): void;\n\n /**\n * Asserts that the value is truthy.\n */\n toBeFalsy(): void;\n\n /**\n * Asserts that the value is greater than the expected value.\n *\n * @param expected the expected value\n */\n toBeGreaterThan(expected: number): void;\n\n /**\n * Asserts that the value is greater than or equal to the expected value.\n *\n * @param expected\n */\n toBeGreaterThanOrEqual(expected: number): void;\n\n /**\n * Ensures that value is an instance of a class. Uses instanceof operator.\n *\n * @param expected The class or constructor function.\n */\n // deno-lint-ignore ban-types\n toBeInstanceOf(expected: Function): void;\n\n /**\n * Asserts that the value is less than the expected value.\n *\n * @param expected the expected value\n */\n toBeLessThan(expected: number): void;\n\n /**\n * Ensures that value <= expected for number or big integer values.\n *\n * @param expected The value to compare to.\n */\n toBeLessThanOrEqual(expected: number | bigint): void;\n\n /**\n * Ensures that value is NaN.\n */\n toBeNaN(): void;\n\n /**\n * Ensures that value is null.\n */\n toBeNull(): void;\n\n /**\n * Ensures that value is true in a boolean context, anything but false, 0, '', null, undefined or NaN.\n * Use this method when you don't care about the specific value.\n */\n toBeTruthy(): void;\n\n /**\n * Ensures that value is `undefined`.\n */\n toBeUndefined(): void;\n\n /**\n * Asserts that the value is equal to the expected value.\n *\n * @param expected the expected value\n */\n toEqual(expected: unknown): void;\n\n /**\n * Ensures that value has a `.length` property equal to expected.\n * Useful for arrays and strings.\n *\n * @param expected\n */\n toHaveLength(expected: number): void;\n}\n\n/**\n * createExpectation is a factory function that creates an expectation object for a given value.\n *\n * It effectively implements the NonRetryingExpectation interface, and provides the actual\n * implementation of the matchers attached to the expectation object.\n *\n * @param received the value to create an expectation for\n * @param isSoft whether the expectation should be a soft assertion\n * @returns an expectation object over the given value exposing the Expectation set of methods\n */\nexport function createExpectation(\n received: unknown,\n config: ExpectConfig,\n): NonRetryingExpectation {\n // In order to facilitate testing, we support passing in a custom assert function.\n // As a result, we need to make sure that the assert function is always available, and\n // if not, we need to use the default assert function.\n //\n // From this point forward, we will use the `usedAssert` variable to refer to the assert function.\n const usedAssert = config.assertFn ?? assert;\n\n // Configure the renderer with the colorize option.\n MatcherErrorRendererRegistry.configure({\n colorize: config.colorize,\n display: config.display,\n });\n\n // Register renderers specific to each matchers at initialization time.\n MatcherErrorRendererRegistry.register(\n \"toBe\",\n new DefaultMatcherErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeCloseTo\",\n new ToBeCloseToErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeDefined\",\n new ToBeDefinedErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeFalsy\",\n new ToBeFalsyErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeGreaterThan\",\n new ToBeGreaterThanErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeGreaterThanOrEqual\",\n new ToBeGreaterThanOrEqualErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeInstanceOf\",\n new ToBeInstanceOfErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeLessThan\",\n new ToBeLessThanErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeLessThanOrEqual\",\n new ToBeLessThanOrEqualErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\"toBeNaN\", new ToBeNaNErrorRenderer());\n MatcherErrorRendererRegistry.register(\n \"toBeNull\",\n new ToBeNullErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeTruthy\",\n new ToBeTruthyErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeUndefined\",\n new ToBeUndefinedErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\"toEqual\", new ToEqualErrorRenderer());\n MatcherErrorRendererRegistry.register(\n \"toHaveLength\",\n new ToHaveLengthErrorRenderer(),\n );\n\n const matcherConfig = {\n usedAssert,\n isSoft: config.soft,\n };\n\n return {\n toBe(expected: unknown): void {\n createMatcher(\n \"toBe\",\n () => Object.is(received, expected),\n expected,\n received,\n matcherConfig,\n );\n },\n\n toBeCloseTo(expected: number, precision: number = 2): void {\n const tolerance = Math.pow(10, -precision) *\n Math.max(Math.abs(received as number), Math.abs(expected));\n const diff = Math.abs((received as number) - expected);\n\n createMatcher(\n \"toBeCloseTo\",\n () => diff < tolerance,\n expected,\n received,\n {\n ...matcherConfig,\n matcherSpecific: {\n precision,\n difference: diff,\n expectedDifference: tolerance,\n },\n },\n );\n },\n\n toBeDefined(): void {\n createMatcher(\n \"toBeDefined\",\n () => received !== undefined,\n \"defined\",\n JSON.stringify(received),\n matcherConfig,\n );\n },\n\n toBeFalsy(): void {\n createMatcher(\n \"toBeFalsy\",\n () => !received,\n \"falsy\",\n JSON.stringify(received),\n matcherConfig,\n );\n },\n\n toBeGreaterThan(expected: number | bigint): void {\n createMatcher(\n \"toBeGreaterThan\",\n () => (received as number) > expected,\n expected,\n received,\n matcherConfig,\n );\n },\n\n toBeGreaterThanOrEqual(expected: number | bigint): void {\n createMatcher(\n \"toBeGreaterThanOrEqual\",\n () => (received as number) >= expected,\n expected,\n received,\n matcherConfig,\n );\n },\n\n // deno-lint-ignore ban-types\n toBeInstanceOf(expected: Function): void {\n createMatcher(\n \"toBeInstanceOf\",\n () => received instanceof expected,\n expected.name,\n (received as { constructor: { name: string } }).constructor.name,\n matcherConfig,\n );\n },\n\n toBeLessThan(expected: number | bigint): void {\n createMatcher(\n \"toBeLessThan\",\n () => (received as number) < expected,\n expected,\n received,\n matcherConfig,\n );\n },\n\n toBeLessThanOrEqual(expected: number | bigint): void {\n createMatcher(\n \"toBeLessThanOrEqual\",\n () => (received as number) <= expected,\n expected,\n received,\n matcherConfig,\n );\n },\n\n toBeNaN(): void {\n createMatcher(\n \"toBeNaN\",\n () => isNaN(received as number),\n \"NaN\",\n JSON.stringify(received),\n matcherConfig,\n );\n },\n\n toBeNull(): void {\n createMatcher(\n \"toBeNull\",\n () => received === null,\n \"null\",\n JSON.stringify(received),\n matcherConfig,\n );\n },\n\n toBeTruthy(): void {\n createMatcher(\n \"toBeTruthy\",\n () => !!received,\n \"truthy\",\n JSON.stringify(received),\n matcherConfig,\n );\n },\n\n toBeUndefined(): void {\n createMatcher(\n \"toBeUndefined\",\n () => received === undefined,\n \"undefined\",\n JSON.stringify(received),\n matcherConfig,\n );\n },\n\n toEqual(expected: unknown): void {\n createMatcher(\n \"toEqual\",\n () => isDeepEqual(received, expected),\n JSON.stringify(expected),\n JSON.stringify(received),\n matcherConfig,\n );\n },\n\n toHaveLength(expected: number): void {\n createMatcher(\n \"toHaveLength\",\n () => (received as Array).length === expected,\n expected.toString(),\n (received as Array).length.toString(),\n matcherConfig,\n );\n },\n };\n}\n\n// Helper function to handle common matcher logic\nfunction createMatcher(\n matcherName: string,\n checkFn: () => boolean,\n expected: unknown,\n received: unknown,\n {\n usedAssert,\n isSoft,\n matcherSpecific = {},\n }: {\n usedAssert: typeof assert;\n isSoft: boolean;\n matcherSpecific?: Record;\n },\n): void {\n const info = createMatcherInfo(\n matcherName,\n expected,\n received,\n matcherSpecific,\n );\n\n usedAssert(\n checkFn(),\n MatcherErrorRendererRegistry.getRenderer(matcherName).render(\n info,\n MatcherErrorRendererRegistry.getConfig(),\n ),\n isSoft,\n );\n}\n\nfunction createMatcherInfo(\n matcherName: string,\n expected: string | unknown,\n received: unknown,\n matcherSpecific: Record = {},\n): MatcherErrorInfo {\n const stacktrace = parseStackTrace(new Error().stack);\n const executionContext = captureExecutionContext(stacktrace);\n\n if (!executionContext) {\n throw new Error(\"k6 failed to capture execution context\");\n }\n\n return {\n executionContext,\n matcherName,\n expected: typeof expected === \"string\"\n ? expected\n : JSON.stringify(expected),\n received: JSON.stringify(received),\n matcherSpecific,\n };\n}\n\n/**\n * A matcher error renderer for the `toBeCloseTo` matcher.\n */\nexport class ToBeCloseToErrorRenderer extends ExpectedReceivedMatcherRenderer {\n protected getMatcherName(): string {\n return \"toBeCloseTo\";\n }\n\n protected override getSpecificLines(\n info: MatcherErrorInfo,\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): LineGroup[] {\n const matcherInfo = info.matcherSpecific as {\n precision: number;\n difference: number;\n expectedDifference: number;\n };\n\n return [\n {\n label: \"Expected precision\",\n value: maybeColorize(matcherInfo.precision.toString(), \"green\"),\n group: 3,\n },\n {\n label: \"Expected difference\",\n value: \"< \" +\n maybeColorize(`${matcherInfo.expectedDifference}`, \"green\"),\n group: 3,\n },\n {\n label: \"Received difference\",\n value: maybeColorize(matcherInfo.difference.toString(), \"red\"),\n group: 3,\n },\n ];\n }\n\n protected override renderMatcherArgs(\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): string {\n return maybeColorize(`(`, \"darkGrey\") +\n maybeColorize(`expected`, \"green\") +\n maybeColorize(`, `, \"darkGrey\") +\n maybeColorize(`precision`, \"white\") +\n maybeColorize(`)`, \"darkGrey\");\n }\n}\n\n/**\n * A matcher error renderer for the `toBeDefined` matcher.\n */\nexport class ToBeDefinedErrorRenderer extends ReceivedOnlyMatcherRenderer {\n protected getMatcherName(): string {\n return \"toBeDefined\";\n }\n}\n\n/**\n * A matcher error renderer for the `toBeFalsy` matcher.\n */\nexport class ToBeFalsyErrorRenderer extends ReceivedOnlyMatcherRenderer {\n protected getMatcherName(): string {\n return \"toBeFalsy\";\n }\n}\n\n/**\n * A matcher error renderer for the `toBeGreaterThan` matcher.\n */\nexport class ToBeGreaterThanErrorRenderer\n extends ExpectedReceivedMatcherRenderer {\n protected getMatcherName(): string {\n return \"toBeGreaterThan\";\n }\n\n protected override getSpecificLines(\n info: MatcherErrorInfo,\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): LineGroup[] {\n return [\n {\n label: \"Expected\",\n value: \"> \" + maybeColorize(info.expected, \"green\"),\n group: 3,\n },\n {\n label: \"Received\",\n value: maybeColorize(info.received, \"red\"),\n group: 3,\n },\n ];\n }\n}\n\n/**\n * A matcher error renderer for the `toBeGreaterThanOrEqual` matcher.\n */\nexport class ToBeGreaterThanOrEqualErrorRenderer\n extends ExpectedReceivedMatcherRenderer {\n protected getMatcherName(): string {\n return \"toBeGreaterThanOrEqual\";\n }\n\n protected override getSpecificLines(\n info: MatcherErrorInfo,\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): LineGroup[] {\n return [\n {\n label: \"Expected\",\n value: \">= \" + maybeColorize(info.expected, \"green\"),\n group: 3,\n },\n {\n label: \"Received\",\n value: maybeColorize(info.received, \"red\"),\n group: 3,\n },\n ];\n }\n}\n\n/**\n * A matcher error renderer for the `toBeInstanceOf` matcher.\n */\nexport class ToBeInstanceOfErrorRenderer\n extends ExpectedReceivedMatcherRenderer {\n protected getMatcherName(): string {\n return \"toBeInstanceOf\";\n }\n\n protected override getSpecificLines(\n info: MatcherErrorInfo,\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): LineGroup[] {\n return [\n {\n label: \"Expected constructor\",\n value: maybeColorize(info.expected, \"green\"),\n group: 3,\n },\n {\n label: \"Received constructor\",\n value: maybeColorize(info.received, \"red\"),\n group: 3,\n },\n ];\n }\n}\n\n/**\n * A matcher error renderer for the `toBeLessThan` matcher.\n */\nexport class ToBeLessThanErrorRenderer extends ExpectedReceivedMatcherRenderer {\n protected getMatcherName(): string {\n return \"toBeLessThan\";\n }\n\n protected override getSpecificLines(\n info: MatcherErrorInfo,\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): LineGroup[] {\n return [\n {\n label: \"Expected\",\n value: \"< \" + maybeColorize(info.expected, \"green\"),\n group: 3,\n },\n {\n label: \"Received\",\n value: maybeColorize(info.received, \"red\"),\n group: 3,\n },\n ];\n }\n}\n\n/**\n * A matcher error renderer for the `toBeLessThanOrEqual` matcher.\n */\nexport class ToBeLessThanOrEqualErrorRenderer\n extends ExpectedReceivedMatcherRenderer {\n protected getMatcherName(): string {\n return \"toBeLessThanOrEqual\";\n }\n\n protected override getSpecificLines(\n info: MatcherErrorInfo,\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): LineGroup[] {\n return [\n {\n label: \"Expected\",\n value: \"<= \" + maybeColorize(info.expected, \"green\"),\n group: 3,\n },\n {\n label: \"Received\",\n value: maybeColorize(info.received, \"red\"),\n group: 3,\n },\n ];\n }\n}\n\n/**\n * A matcher error renderer for the `toBeNaN` matcher.\n */\nexport class ToBeNaNErrorRenderer extends ReceivedOnlyMatcherRenderer {\n protected getMatcherName(): string {\n return \"toBeNaN\";\n }\n}\n\n/**\n * A matcher error renderer for the `toBeNull` matcher.\n */\nexport class ToBeNullErrorRenderer extends ReceivedOnlyMatcherRenderer {\n protected getMatcherName(): string {\n return \"toBeNull\";\n }\n}\n\n/**\n * A matcher error renderer for the `toBeTruthy` matcher.\n */\nexport class ToBeTruthyErrorRenderer extends ReceivedOnlyMatcherRenderer {\n protected getMatcherName(): string {\n return \"toBeTruthy\";\n }\n}\n\n/**\n * A matcher error renderer for the `toBeUndefined` matcher.\n */\nexport class ToBeUndefinedErrorRenderer extends ReceivedOnlyMatcherRenderer {\n protected getMatcherName(): string {\n return \"toBeUndefined\";\n }\n}\n\n/**\n * A matcher error renderer for the `toEqual` matcher.\n */\nexport class ToEqualErrorRenderer extends ExpectedReceivedMatcherRenderer {\n protected getMatcherName(): string {\n return \"toEqual\";\n }\n\n protected override getSpecificLines(\n info: MatcherErrorInfo,\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): LineGroup[] {\n return [\n {\n label: \"Expected\",\n value: maybeColorize(info.expected, \"green\"),\n group: 3,\n },\n {\n label: \"Received\",\n value: maybeColorize(info.received, \"red\"),\n group: 3,\n },\n ];\n }\n}\n\n/**\n * A matcher error renderer for the `toHaveLength` matcher.\n */\nexport class ToHaveLengthErrorRenderer extends ExpectedReceivedMatcherRenderer {\n protected getMatcherName(): string {\n return \"toHaveLength\";\n }\n\n protected override getSpecificLines(\n info: MatcherErrorInfo,\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): LineGroup[] {\n return [\n {\n label: \"Expected length\",\n value: maybeColorize(info.expected, \"green\"),\n group: 3,\n },\n {\n label: \"Received length\",\n value: maybeColorize(info.received, \"red\"),\n group: 3,\n },\n {\n label: \"Received array\",\n value: maybeColorize(\n info.matcherSpecific?.receivedArray as string,\n \"red\",\n ),\n group: 3,\n },\n ];\n }\n}\n\nfunction isDeepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n\n if (a === null || b === null) return false;\n if (typeof a !== \"object\" || typeof b !== \"object\") return false;\n\n const keysA = Object.keys(a as object);\n const keysB = Object.keys(b as object);\n\n if (keysA.length !== keysB.length) return false;\n\n return keysA.every((key) => {\n return keysB.includes(key) &&\n isDeepEqual(\n (a as Record)[key],\n (b as Record)[key],\n );\n });\n}\n", "import { assert } from \"./assert.ts\";\nimport type { ANSI_COLORS } from \"./colors.ts\";\nimport {\n DEFAULT_RETRY_OPTIONS,\n type ExpectConfig,\n type RetryConfig,\n} from \"./config.ts\";\nimport { captureExecutionContext } from \"./execution.ts\";\nimport {\n ExpectedReceivedMatcherRenderer,\n type LineGroup,\n type MatcherErrorInfo,\n MatcherErrorRendererRegistry,\n ReceivedOnlyMatcherRenderer,\n} from \"./render.ts\";\nimport { parseStackTrace } from \"./stacktrace.ts\";\nimport type { Locator } from \"https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/refs/heads/master/types/k6/browser/index.d.ts\";\n\n/**\n * RetryingExpectation is an interface that defines the methods that can be used to create a retrying expectation.\n *\n * Retrying expectations are used to assert that a condition is met within a given timeout.\n * The provided assertion function is called repeatedly until the condition is met or the timeout is reached.\n *\n * The RetryingExpectation interface is implemented by the createExpectation function.\n */\nexport interface RetryingExpectation {\n /**\n * Ensures the Locator points to a checked input.\n */\n toBeChecked(options: Partial): Promise;\n\n /**\n * Ensures the Locator points to a disabled element.\n * Element is disabled if it has \"disabled\" attribute or is disabled via 'aria-disabled'.\n *\n * Note that only native control elements such as HTML button, input, select, textarea, option, optgroup can be disabled by setting \"disabled\" attribute.\n * \"disabled\" attribute on other elements is ignored by the browser.\n */\n toBeDisabled(options: Partial): Promise;\n\n /**\n * Ensures the Locator points to an editable element.\n */\n toBeEditable(options: Partial): Promise;\n\n /**\n * Ensures the Locator points to an enabled element.\n */\n toBeEnabled(options: Partial): Promise;\n\n /**\n * Ensures that Locator either does not resolve to any DOM node, or resolves to a non-visible one.\n */\n toBeHidden(options: Partial): Promise;\n\n /**\n * Ensures that Locator points to an attached and visible DOM node.\n */\n toBeVisible(options: Partial): Promise;\n\n /**\n * Ensures the Locator points to an element with the given input value. You can use regular expressions for the value as well.\n *\n * @param value {string} the expected value of the input\n */\n toHaveValue(value: string, options: Partial): Promise;\n}\n\n/**\n * createExpectation is a factory function that creates an expectation object for a given value.\n *\n * Note that although the browser `is` prefixed methods are used, and return boolean values, we\n * throw errors if the condition is not met. This is to ensure that we align with playwright's\n * API, and have matchers return `Promise`, as opposed to `Promise`.\n *\n * @param locator the value to create an expectation for\n * @param isSoft whether the expectation should be a soft assertion\n * @param assertFn optional custom assertion function\n * @returns an expectation object over the given value exposing the Expectation set of methods\n */\nexport function createExpectation(\n locator: Locator,\n config: ExpectConfig,\n): RetryingExpectation {\n // In order to facilitate testing, we support passing in a custom assert function.\n // As a result, we need to make sure that the assert function is always available, and\n // if not, we need to use the default assert function.\n //\n // From this point forward, we will use the `usedAssert` variable to refer to the assert function.\n const usedAssert = config.assertFn ?? assert;\n const isSoft = config.soft ?? false;\n const retryConfig: RetryConfig = {\n timeout: config.timeout,\n interval: config.interval,\n };\n\n // Configure the renderer with the colorize option.\n MatcherErrorRendererRegistry.configure({\n colorize: config.colorize,\n display: config.display,\n });\n\n // Register renderers specific to each matchers at initialization time.\n MatcherErrorRendererRegistry.register(\n \"toBeChecked\",\n new ToBeCheckedErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeDisabled\",\n new ToBeDisabledErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeEditable\",\n new ToBeEditableErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeEnabled\",\n new ToBeEnabledErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeHidden\",\n new ToBeHiddenErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toBeVisible\",\n new ToBeVisibleErrorRenderer(),\n );\n MatcherErrorRendererRegistry.register(\n \"toHaveValue\",\n new ToHaveValueErrorRenderer(),\n );\n\n const matcherConfig = {\n locator,\n retryConfig,\n usedAssert,\n isSoft,\n };\n\n return {\n async toBeChecked(\n options: Partial = retryConfig,\n ): Promise {\n await createMatcher(\n \"toBeChecked\",\n async () => await locator.isChecked(),\n \"checked\",\n \"unchecked\",\n { ...matcherConfig, options },\n );\n },\n\n async toBeDisabled(\n options: Partial = retryConfig,\n ): Promise {\n await createMatcher(\n \"toBeDisabled\",\n async () => await locator.isDisabled(),\n \"disabled\",\n \"enabled\",\n { ...matcherConfig, options },\n );\n },\n\n async toBeEditable(\n options: Partial = retryConfig,\n ): Promise {\n await createMatcher(\n \"toBeEditable\",\n async () => await locator.isEditable(),\n \"editable\",\n \"uneditable\",\n { ...matcherConfig, options },\n );\n },\n\n async toBeEnabled(\n options: Partial = retryConfig,\n ): Promise {\n await createMatcher(\n \"toBeEnabled\",\n async () => await locator.isEnabled(),\n \"enabled\",\n \"disabled\",\n { ...matcherConfig, options },\n );\n },\n\n async toBeHidden(\n options: Partial = retryConfig,\n ): Promise {\n await createMatcher(\n \"toBeHidden\",\n async () => await locator.isHidden(),\n \"hidden\",\n \"visible\",\n { ...matcherConfig, options },\n );\n },\n\n async toBeVisible(\n options: Partial = retryConfig,\n ): Promise {\n await createMatcher(\n \"toBeVisible\",\n async () => await locator.isVisible(),\n \"visible\",\n \"hidden\",\n { ...matcherConfig, options },\n );\n },\n\n async toHaveValue(\n expectedValue: string,\n options: Partial = retryConfig,\n ): Promise {\n const stacktrace = parseStackTrace(new Error().stack);\n const executionContext = captureExecutionContext(stacktrace);\n if (!executionContext) {\n throw new Error(\"k6 failed to capture execution context\");\n }\n\n const info: MatcherErrorInfo = {\n executionContext,\n matcherName: \"toHaveValue\",\n expected: expectedValue,\n received: \"unknown\",\n };\n\n try {\n await withRetry(async () => {\n const actualValue = await locator.inputValue();\n usedAssert(\n expectedValue === actualValue,\n MatcherErrorRendererRegistry.getRenderer(\"toHaveValue\").render(\n info,\n MatcherErrorRendererRegistry.getConfig(),\n ),\n isSoft,\n );\n }, { ...retryConfig, ...options });\n } catch (_) {\n usedAssert(\n false,\n MatcherErrorRendererRegistry.getRenderer(\"toHaveValue\").render(\n info,\n MatcherErrorRendererRegistry.getConfig(),\n ),\n isSoft,\n );\n }\n },\n };\n}\n\n// Helper function to create common matcher error info\nfunction createMatcherInfo(\n matcherName: string,\n expected: string,\n received: string,\n additionalInfo = {},\n): MatcherErrorInfo {\n const stacktrace = parseStackTrace(new Error().stack);\n const executionContext = captureExecutionContext(stacktrace);\n\n if (!executionContext) {\n throw new Error(\"k6 failed to capture execution context\");\n }\n\n return {\n executionContext,\n matcherName,\n expected,\n received,\n ...additionalInfo,\n };\n}\n\n// Helper function to handle common matcher logic\nasync function createMatcher(\n matcherName: string,\n checkFn: () => Promise,\n expected: string,\n received: string,\n {\n locator,\n retryConfig,\n usedAssert,\n isSoft,\n options = {},\n }: {\n locator: Locator;\n retryConfig: RetryConfig;\n usedAssert: typeof assert;\n isSoft: boolean;\n options?: Partial;\n },\n): Promise {\n const info = createMatcherInfo(matcherName, expected, received, {\n matcherSpecific: {\n locator,\n timeout: options.timeout,\n },\n });\n\n try {\n await withRetry(async () => {\n const result = await checkFn();\n if (!result) {\n throw new Error(\"matcher failed\");\n }\n\n usedAssert(\n result,\n MatcherErrorRendererRegistry.getRenderer(matcherName).render(\n info,\n MatcherErrorRendererRegistry.getConfig(),\n ),\n isSoft,\n );\n }, { ...retryConfig, ...options });\n } catch (_) {\n usedAssert(\n false,\n MatcherErrorRendererRegistry.getRenderer(matcherName).render(\n info,\n MatcherErrorRendererRegistry.getConfig(),\n ),\n isSoft,\n );\n }\n}\n\n/**\n * Base class for boolean state matchers (checked, disabled, etc.)\n */\nexport abstract class BooleanStateErrorRenderer\n extends ReceivedOnlyMatcherRenderer {\n protected abstract state: string;\n protected abstract oppositeState: string;\n\n protected getMatcherName(): string {\n return `toBe${this.state[0].toUpperCase()}${this.state.slice(1)}`;\n }\n\n protected override getReceivedPlaceholder(): string {\n return \"locator\";\n }\n\n protected override getSpecificLines(\n info: MatcherErrorInfo,\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): LineGroup[] {\n return [\n { label: \"Expected\", value: this.state, group: 3 },\n { label: \"Received\", value: this.oppositeState, group: 3 },\n { label: \"Call log\", value: \"\", group: 3 },\n {\n label: \"\",\n value: maybeColorize(\n ` - expect.toBe${this.state[0].toUpperCase()}${\n this.state.slice(1)\n } with timeout ${info.matcherSpecific?.timeout}ms`,\n \"darkGrey\",\n ),\n group: 3,\n raw: true,\n },\n {\n label: \"\",\n value: maybeColorize(` - waiting for locator`, \"darkGrey\"),\n group: 3,\n raw: true,\n },\n ];\n }\n}\n\nexport class ToBeCheckedErrorRenderer extends BooleanStateErrorRenderer {\n protected state = \"checked\";\n protected oppositeState = \"unchecked\";\n}\n\n/**\n * A matcher error renderer for the `toBeDisabled` matcher.\n */\nexport class ToBeDisabledErrorRenderer extends BooleanStateErrorRenderer {\n protected state = \"disabled\";\n protected oppositeState = \"enabled\";\n}\n\nexport class ToBeEditableErrorRenderer extends BooleanStateErrorRenderer {\n protected state = \"editable\";\n protected oppositeState = \"uneditable\";\n}\n\nexport class ToBeEnabledErrorRenderer extends BooleanStateErrorRenderer {\n protected state = \"enabled\";\n protected oppositeState = \"disabled\";\n}\n\nexport class ToBeHiddenErrorRenderer extends BooleanStateErrorRenderer {\n protected state = \"hidden\";\n protected oppositeState = \"visible\";\n}\n\nexport class ToBeVisibleErrorRenderer extends BooleanStateErrorRenderer {\n protected state = \"visible\";\n protected oppositeState = \"hidden\";\n}\n\nexport class ToHaveValueErrorRenderer extends ExpectedReceivedMatcherRenderer {\n protected getMatcherName(): string {\n return \"toHaveValue\";\n }\n\n protected override getSpecificLines(\n info: MatcherErrorInfo,\n maybeColorize: (text: string, color: keyof typeof ANSI_COLORS) => string,\n ): LineGroup[] {\n return [\n // FIXME (@oleiade): When k6/#4210 is fixed, we can use the locator here.\n // { label: \"Locator\", value: maybeColorize(`locator('${info.matcherSpecific?.locator}')`, \"white\"), group: 3 },\n {\n label: \"Expected\",\n value: maybeColorize(info.expected, \"green\"),\n group: 3,\n },\n {\n label: \"Received\",\n value: maybeColorize(info.received, \"red\"),\n group: 3,\n },\n { label: \"Call log\", value: \"\", group: 3 },\n {\n label: \"\",\n value: maybeColorize(\n ` - expect.toHaveValue with timeout ${info.matcherSpecific?.timeout}ms`,\n \"darkGrey\",\n ),\n group: 3,\n raw: true,\n },\n // FIXME (@oleiade): When k6/#4210 is fixed, we can use the locator's selector here.\n {\n label: \"\",\n value: maybeColorize(` - waiting for locator`, \"darkGrey\"),\n group: 3,\n raw: true,\n },\n ];\n }\n}\n\n/**\n * Implements retry logic for async assertions.\n *\n * @param assertion Function that performs the actual check\n * @param options Retry configuration\n * @returns Promise that resolves when assertion passes or rejects if timeout is reached\n */\nexport async function withRetry(\n assertion: () => Promise,\n options: RetryConfig & {\n // Optional test hooks - only used in testing\n _now?: () => number;\n _sleep?: (ms: number) => Promise;\n } = {},\n): Promise {\n const timeout: number = options.timeout ?? DEFAULT_RETRY_OPTIONS.timeout;\n const interval: number = options.interval ?? DEFAULT_RETRY_OPTIONS.interval;\n const getNow = options._now ?? (() => Date.now());\n const sleep = options._sleep ??\n ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));\n\n const startTime: number = getNow();\n\n while (getNow() - startTime < timeout) {\n try {\n await assertion();\n return true;\n } catch (_error) {\n // Ignore error and continue retrying\n }\n\n await sleep(interval);\n }\n\n throw new RetryTimeoutError(\n `Expect condition not met within ${timeout}ms timeout`,\n );\n}\n\n/**\n * RetryTimeoutError is an error that is thrown when an expectation is not met within a provided timeout.\n */\nexport class RetryTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"RetryTimeoutError\";\n }\n}\n", "import type { Locator } from \"https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/refs/heads/master/types/k6/browser/index.d.ts\";\nimport { ConfigLoader, type ExpectConfig } from \"./config.ts\";\nimport {\n createExpectation as createNonRetryingExpectation,\n type NonRetryingExpectation,\n} from \"./expectNonRetrying.ts\";\nimport {\n createExpectation as createRetryingExpectation,\n type RetryingExpectation,\n} from \"./expectRetrying.ts\";\n\n/**\n * The expect function is used to assert that a value meets certain conditions.\n *\n * The expect function can be used in two ways:\n *\n * 1. Non-retrying: The expect function will perform the assertion only once. If the assertion\n * is not met, the test will fail.\n * 2. Retrying: The expect function will perform the assertion multiple times, until the assertion\n * is met or the timeout is reached. If the assertion is not met, the test will fail.\n *\n * @param {unknown | Locator} value The value to assert.\n */\nexport const expect: ExpectFunction = makeExpect();\n\nexport interface ExpectFunction {\n /**\n * The expect function can be used directly to assert that a value meets certain conditions.\n *\n * If the value argument provided to it is a Locator, the expect function will\n * return a (asynchronous) RetryingExpectation, otherwise it will return a NonRetryingExpectation.\n */\n (value: T): T extends Locator ? RetryingExpectation\n : NonRetryingExpectation;\n\n /**\n * The soft function can be used to assert that a value meets certain conditions, but\n * without terminating the test if the assertion is not met.\n */\n soft(\n value: T,\n ): T extends Locator ? RetryingExpectation : NonRetryingExpectation;\n\n /**\n * Creates a new expect instance with the given configuration.\n */\n configure(newConfig: Partial): ExpectFunction;\n\n /**\n * The configuration used by the expect function.\n */\n readonly config: ExpectConfig;\n}\n\n/**\n * Creates a new expect function with the given configuration.\n *\n * This allows us\n *\n * @param baseConfig The base configuration for the expect function.\n * @returns\n */\nfunction makeExpect(baseConfig?: Partial): ExpectFunction {\n /**\n * Loads the configuration for the expect function.\n */\n const config = ConfigLoader.load(baseConfig);\n\n return Object.assign(\n function (\n value: T,\n ): T extends Locator ? RetryingExpectation : NonRetryingExpectation {\n if (isLocator(value)) {\n return createRetryingExpectation(\n value as Locator,\n config,\n ) as T extends Locator ? RetryingExpectation : NonRetryingExpectation;\n } else {\n return createNonRetryingExpectation(\n value,\n config,\n ) as T extends Locator ? RetryingExpectation : NonRetryingExpectation;\n }\n },\n {\n soft(\n value: T,\n ): T extends Locator ? RetryingExpectation : NonRetryingExpectation {\n if (isLocator(value)) {\n return createRetryingExpectation(\n value as Locator,\n { ...config, soft: true },\n ) as T extends Locator ? RetryingExpectation : NonRetryingExpectation;\n } else {\n return createNonRetryingExpectation(\n value,\n { ...config, soft: true },\n ) as T extends Locator ? RetryingExpectation : NonRetryingExpectation;\n }\n },\n configure(newConfig: Partial): ExpectFunction {\n return makeExpect(newConfig);\n },\n get config(): ExpectConfig {\n return { ...config };\n },\n },\n );\n}\n\n/**\n * Checks if the given value is a browser Locator.\n *\n * If it quacks like a duck, it's a duck.\n *\n * @param value The value to check.\n * @returns Whether the value is a Locator.\n */\nfunction isLocator(value: unknown): value is Locator {\n if (!value || typeof value !== \"object\") {\n return false;\n }\n\n const locatorProperties = [\n \"clear\",\n \"isEnabled\",\n \"isHidden\",\n \"getAttribute\",\n \"selectOption\",\n \"press\",\n \"type\",\n \"dispatchEvent\",\n \"dblclick\",\n \"setChecked\",\n \"isDisabled\",\n \"focus\",\n \"innerText\",\n \"inputValue\",\n \"check\",\n \"isEditable\",\n \"fill\",\n \"textContent\",\n \"hover\",\n \"waitFor\",\n \"click\",\n \"uncheck\",\n \"isChecked\",\n \"isVisible\",\n \"innerHTML\",\n \"tap\",\n ];\n\n const hasLocatorProperties = (value: object): boolean => {\n return locatorProperties.every((prop) => prop in value);\n };\n\n return (\n value !== null &&\n value !== undefined &&\n typeof value === \"object\" &&\n hasLocatorProperties(value)\n );\n}\n"], + "mappings": "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", + "names": ["exec", "assert", "condition", "message", "soft", "AssertionFailedError", "getEnvironment", "env", "envParser", "key", "value", "allowedValues", "name", "parsed", "DEFAULT_RETRY_OPTIONS", "DEFAULT_CONFIG", "assert", "ConfigLoader", "_ConfigLoader", "explicitConfig", "envConfig", "config", "envParser", "captureExecutionContext", "st", "stackFrame", "filePath", "fileName", "lineNumber", "columnNumber", "at", "parseStackTrace", "stack", "lines", "frames", "i", "lineStr", "functionName", "fileInfo", "firstParenIndex", "fileProtocolIndex", "offsetParenIndex", "lastColon", "secondLastColon", "filePath", "fileName", "lineNumberStr", "columnNumberStr", "ANSI_COLORS", "colorize", "text", "color", "MatcherErrorRendererRegistry", "matcherName", "renderer", "DefaultMatcherErrorRenderer", "config", "BaseMatcherErrorRenderer", "_", "maybeColorize", "text", "color", "colorize", "info", "lines", "DisplayFormatRegistry", "ReceivedOnlyMatcherRenderer", "ExpectedReceivedMatcherRenderer", "PrettyFormatRenderer", "maxLabelWidth", "line", "label", "value", "raw", "index", "labelWithColon", "nextLine", "InlineFormatRenderer", "escapedValue", "format", "formatter", "createExpectation", "received", "config", "usedAssert", "assert", "MatcherErrorRendererRegistry", "DefaultMatcherErrorRenderer", "ToBeCloseToErrorRenderer", "ToBeDefinedErrorRenderer", "ToBeFalsyErrorRenderer", "ToBeGreaterThanErrorRenderer", "ToBeGreaterThanOrEqualErrorRenderer", "ToBeInstanceOfErrorRenderer", "ToBeLessThanErrorRenderer", "ToBeLessThanOrEqualErrorRenderer", "ToBeNaNErrorRenderer", "ToBeNullErrorRenderer", "ToBeTruthyErrorRenderer", "ToBeUndefinedErrorRenderer", "ToEqualErrorRenderer", "ToHaveLengthErrorRenderer", "matcherConfig", "expected", "createMatcher", "precision", "tolerance", "diff", "isDeepEqual", "matcherName", "checkFn", "isSoft", "matcherSpecific", "info", "createMatcherInfo", "stacktrace", "parseStackTrace", "executionContext", "captureExecutionContext", "ExpectedReceivedMatcherRenderer", "maybeColorize", "matcherInfo", "ReceivedOnlyMatcherRenderer", "a", "b", "keysA", "keysB", "key", "createExpectation", "locator", "config", "usedAssert", "assert", "isSoft", "retryConfig", "MatcherErrorRendererRegistry", "ToBeCheckedErrorRenderer", "ToBeDisabledErrorRenderer", "ToBeEditableErrorRenderer", "ToBeEnabledErrorRenderer", "ToBeHiddenErrorRenderer", "ToBeVisibleErrorRenderer", "ToHaveValueErrorRenderer", "matcherConfig", "options", "createMatcher", "expectedValue", "stacktrace", "parseStackTrace", "executionContext", "captureExecutionContext", "info", "withRetry", "actualValue", "createMatcherInfo", "matcherName", "expected", "received", "additionalInfo", "checkFn", "result", "BooleanStateErrorRenderer", "ReceivedOnlyMatcherRenderer", "maybeColorize", "ExpectedReceivedMatcherRenderer", "assertion", "timeout", "DEFAULT_RETRY_OPTIONS", "interval", "getNow", "sleep", "ms", "resolve", "startTime", "RetryTimeoutError", "message", "expect", "makeExpect", "baseConfig", "config", "ConfigLoader", "value", "isLocator", "createExpectation", "newConfig", "locatorProperties", "hasLocatorProperties", "prop"] +} diff --git a/supported.json b/supported.json index 16eefd2..e2b25ff 100644 --- a/supported.json +++ b/supported.json @@ -8,7 +8,7 @@ "docs-url": "https://github.com/grafana/k6-jslib-summary" }, "k6-testing": { - "versions": ["0.1.0"], + "versions": ["0.1.0", "0.2.0"], "docs-url": "https://github.com/grafana/k6-jslib-testing" }, "k6-replay": {