@autometa/assertions 1.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +19 -0
- package/dist/__tests__/ensure.test-d.d.ts +67 -0
- package/dist/__tests__/helpers/matcher-context.d.ts +18 -0
- package/dist/assertion-error.d.ts +13 -0
- package/dist/core/constants.d.ts +4 -0
- package/dist/core/context.d.ts +14 -0
- package/dist/core/messages.d.ts +10 -0
- package/dist/core/predicates.d.ts +5 -0
- package/dist/ensure.d.ts +33 -0
- package/dist/index.cjs +815 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +809 -0
- package/dist/index.js.map +1 -0
- package/dist/matchers/__tests__/http.note.d.ts +6 -0
- package/dist/matchers/collections.d.ts +6 -0
- package/dist/matchers/equality.d.ts +4 -0
- package/dist/matchers/http.d.ts +57 -0
- package/dist/matchers/instance.d.ts +2 -0
- package/dist/matchers/nullish.d.ts +4 -0
- package/dist/matchers/numeric.d.ts +6 -0
- package/dist/matchers/truthiness.d.ts +3 -0
- package/dist/plugins/runtime-assertions-plugin.d.ts +140 -0
- package/dist/plugins.d.ts +50 -0
- package/package.json +61 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/assertion-error.ts","../src/matchers/collections.ts","../src/core/constants.ts","../src/core/context.ts","../src/core/messages.ts","../src/core/predicates.ts","../src/matchers/equality.ts","../src/matchers/instance.ts","../src/matchers/nullish.ts","../src/matchers/numeric.ts","../src/matchers/truthiness.ts","../src/ensure.ts","../src/plugins.ts","../src/plugins/runtime-assertions-plugin.ts"],"names":["equals","ensure","table"],"mappings":"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","sourcesContent":["import { inspect } from \"node:util\";\n\nexport interface EnsureErrorDetails {\n readonly matcher: string;\n readonly message: string;\n readonly actual?: unknown;\n readonly expected?: unknown;\n readonly receivedLabel?: string;\n}\n\nexport class EnsureError extends Error {\n public readonly matcher: string;\n public readonly actual?: unknown;\n public readonly expected?: unknown;\n\n constructor(details: EnsureErrorDetails) {\n const formattedMessage = buildMessage(details);\n super(formattedMessage);\n this.name = \"EnsureError\";\n this.matcher = details.matcher;\n this.actual = details.actual;\n this.expected = details.expected;\n }\n}\n\nfunction buildMessage({ matcher, message, actual, expected, receivedLabel }: EnsureErrorDetails): string {\n const parts = [message];\n const extras: string[] = [];\n\n if (typeof expected !== \"undefined\" && !containsSection(message, \"Expected:\")) {\n extras.push(`Expected: ${formatValue(expected)}`);\n }\n\n if (typeof actual !== \"undefined\") {\n const label = receivedLabel ? `Received ${receivedLabel}` : \"Received\";\n if (!containsSection(message, `${label}:`)) {\n extras.push(`${label}: ${formatValue(actual)}`);\n }\n }\n\n if (!containsSection(message, \"Matcher:\")) {\n extras.push(`Matcher: ${matcher}`);\n }\n\n if (extras.length > 0) {\n parts.push(\"\", ...extras);\n }\n\n return parts.join(\"\\n\");\n}\n\nfunction formatValue(value: unknown): string {\n return inspect(value, { depth: 4, maxArrayLength: 10, breakLength: 60, sorted: true });\n}\n\nfunction containsSection(message: string, label: string): boolean {\n return message\n .split(\"\\n\")\n .some((line) => line.trimStart().startsWith(label));\n}\n","import { equals } from \"@jest/expect-utils\";\n\nimport { EQUALITY_TESTERS, SUBSET_TESTERS } from \"../core/constants\";\nimport { type MatcherContext, shouldFail } from \"../core/context\";\nimport { buildFailureMessage, formatDiff, formatMissingList } from \"../core/messages\";\nimport { hasLengthProperty, isIterable, isRecord } from \"../core/predicates\";\n\nexport function assertObjectContaining<T>(\n ctx: MatcherContext<T>,\n shape: Record<PropertyKey, unknown>\n): void {\n const isObject = isRecord(ctx.value);\n if (!isObject) {\n if (!ctx.negated) {\n ctx.fail(\"toBeObjectContaining\", {\n message: buildFailureMessage(\"toBeObjectContaining\", \"Expected value to be an object\", {\n actual: ctx.value,\n }),\n actual: ctx.value,\n });\n }\n return;\n }\n\n const pass = equals(ctx.value, shape, SUBSET_TESTERS);\n if (shouldFail(pass, ctx.negated)) {\n const baseMessage = ctx.negated\n ? \"Expected object not to match the provided subset\"\n : \"Object does not match the provided subset\";\n ctx.fail(\"toBeObjectContaining\", {\n message: buildFailureMessage(\"toBeObjectContaining\", baseMessage, {\n expected: shape,\n actual: ctx.value,\n diff: formatDiff(shape, ctx.value),\n }),\n expected: shape,\n actual: ctx.value,\n });\n }\n}\n\nexport function assertArrayContaining<T>(\n ctx: MatcherContext<T>,\n expected: readonly unknown[]\n): readonly unknown[] {\n if (!Array.isArray(ctx.value)) {\n if (!ctx.negated) {\n ctx.fail(\"toBeArrayContaining\", {\n message: buildFailureMessage(\"toBeArrayContaining\", \"Expected value to be an array\", {\n actual: ctx.value,\n }),\n actual: ctx.value,\n });\n }\n return ctx.value as unknown as readonly unknown[];\n }\n\n const actual = ctx.value as readonly unknown[];\n const missing = expected.filter((item) =>\n !actual.some((entry: unknown) => equals(entry, item, EQUALITY_TESTERS))\n );\n\n const pass = missing.length === 0;\n if (shouldFail(pass, ctx.negated)) {\n const baseMessage = ctx.negated\n ? \"Expected array not to contain the provided elements\"\n : \"Array is missing expected elements\";\n ctx.fail(\"toBeArrayContaining\", {\n message: buildFailureMessage(\"toBeArrayContaining\", baseMessage, {\n expected,\n actual,\n extra: [formatMissingList(\"Missing elements:\", missing)],\n diff: formatDiff(expected, actual),\n }),\n expected,\n actual,\n });\n }\n\n return actual;\n}\n\nexport function assertContainEqual<T>(\n ctx: MatcherContext<T>,\n expected: unknown\n): readonly unknown[] {\n if (!Array.isArray(ctx.value)) {\n if (!ctx.negated) {\n ctx.fail(\"toContainEqual\", {\n message: buildFailureMessage(\"toContainEqual\", \"Expected value to be an array\", {\n actual: ctx.value,\n }),\n actual: ctx.value,\n });\n }\n return ctx.value as unknown as readonly unknown[];\n }\n\n const actual = ctx.value as readonly unknown[];\n const pass = actual.some((entry: unknown) => equals(entry, expected, EQUALITY_TESTERS));\n if (shouldFail(pass, ctx.negated)) {\n const baseMessage = ctx.negated\n ? \"Expected array not to contain the provided element\"\n : \"Array is missing the expected element\";\n ctx.fail(\"toContainEqual\", {\n message: buildFailureMessage(\"toContainEqual\", baseMessage, {\n expected,\n actual,\n diff: formatDiff(expected, actual),\n }),\n expected,\n actual,\n });\n }\n\n return actual;\n}\n\nexport function assertIterableContaining<T>(\n ctx: MatcherContext<T>,\n expected: readonly unknown[]\n): Iterable<unknown> {\n if (!isIterable(ctx.value)) {\n if (!ctx.negated) {\n ctx.fail(\"toBeIterableContaining\", {\n message: buildFailureMessage(\"toBeIterableContaining\", \"Expected value to be iterable\", {\n actual: ctx.value,\n }),\n actual: ctx.value,\n });\n }\n return ctx.value as unknown as Iterable<unknown>;\n }\n\n const entries = Array.from(ctx.value as Iterable<unknown>);\n const missing = expected.filter((item) =>\n !entries.some((entry) => equals(entry, item, EQUALITY_TESTERS))\n );\n\n const pass = missing.length === 0;\n if (shouldFail(pass, ctx.negated)) {\n const baseMessage = ctx.negated\n ? \"Expected iterable not to contain the provided elements\"\n : \"Iterable is missing expected elements\";\n ctx.fail(\"toBeIterableContaining\", {\n message: buildFailureMessage(\"toBeIterableContaining\", baseMessage, {\n expected,\n actual: entries,\n extra: [formatMissingList(\"Missing elements:\", missing)],\n }),\n expected,\n actual: entries,\n });\n }\n\n return ctx.value as unknown as Iterable<unknown>;\n}\n\nexport function assertHasLength<T>(ctx: MatcherContext<T>, expected: number): number {\n if (!hasLengthProperty(ctx.value)) {\n if (!ctx.negated) {\n ctx.fail(\"toHaveLength\", {\n message: buildFailureMessage(\"toHaveLength\", \"Expected value to have a numeric length property\", {\n actual: ctx.value,\n }),\n actual: ctx.value,\n });\n }\n return NaN;\n }\n\n const actualLength = (ctx.value as { length: number }).length;\n const pass = actualLength === expected;\n if (shouldFail(pass, ctx.negated)) {\n const baseMessage = ctx.negated\n ? `Expected length to differ from ${expected}`\n : \"Length does not match expectation\";\n ctx.fail(\"toHaveLength\", {\n message: buildFailureMessage(\"toHaveLength\", baseMessage, {\n expected,\n actual: actualLength,\n diff: formatDiff(expected, actualLength),\n }),\n expected,\n actual: actualLength,\n });\n }\n\n return actualLength;\n}\n","import { iterableEquality, subsetEquality, type Tester } from \"@jest/expect-utils\";\n\nexport const MATCHER_CALL = \"ensure(received)\";\n\nexport const EQUALITY_TESTERS: Tester[] = [iterableEquality];\n\nexport const SUBSET_TESTERS: Tester[] = [iterableEquality, subsetEquality];\n","export interface FailureDetails {\n readonly message: string;\n readonly actual?: unknown;\n readonly expected?: unknown;\n}\n\nexport interface MatcherState<T> {\n readonly value: T;\n readonly label?: string;\n readonly negated: boolean;\n}\n\nexport interface MatcherContext<T> extends MatcherState<T> {\n fail(matcher: string, details: FailureDetails): never;\n}\n\nexport function shouldFail(pass: boolean, negated: boolean): boolean {\n return negated ? pass : !pass;\n}\n","import { diff } from \"jest-diff\";\nimport { printExpected, printReceived } from \"jest-matcher-utils\";\n\nimport { MATCHER_CALL } from \"./constants\";\n\nexport interface FailureMessageOptions {\n readonly expected?: unknown;\n readonly actual?: unknown;\n readonly diff?: string | undefined;\n readonly extra?: readonly (string | undefined)[];\n readonly actualLabel?: string;\n}\n\nexport function buildFailureMessage(\n matcher: string,\n baseMessage: string,\n options: FailureMessageOptions = {}\n): string {\n const sections: string[] = [`${MATCHER_CALL}.${matcher}(expected)`, baseMessage];\n\n if (Object.prototype.hasOwnProperty.call(options, \"expected\")) {\n sections.push(`Expected: ${printExpected(options.expected)}`);\n }\n\n if (Object.prototype.hasOwnProperty.call(options, \"actual\")) {\n const label = options.actualLabel ?? \"Received\";\n sections.push(`${label}: ${printReceived(options.actual)}`);\n }\n\n if (options.extra) {\n for (const extra of options.extra) {\n if (extra && extra.trim().length > 0) {\n sections.push(extra);\n }\n }\n }\n\n if (options.diff && options.diff.trim().length > 0) {\n sections.push(options.diff);\n }\n\n return sections.join(\"\\n\\n\");\n}\n\nexport function formatDiff(expected: unknown, actual: unknown): string | undefined {\n const difference = diff(expected, actual, { expand: false });\n return difference && difference.trim().length > 0 ? difference : undefined;\n}\n\nexport function formatMissingList(title: string, values: readonly unknown[]): string {\n if (values.length === 0) {\n return \"\";\n }\n const items = values.map((value) => ` - ${printExpected(value)}`).join(\"\\n\");\n return `${title}\\n${items}`;\n}\n","export function isRecord(candidate: unknown): candidate is Record<PropertyKey, unknown> {\n return typeof candidate === \"object\" && candidate !== null;\n}\n\nexport function isIterable(candidate: unknown): candidate is Iterable<unknown> {\n return typeof (candidate as { [Symbol.iterator]?: unknown })?.[Symbol.iterator] === \"function\";\n}\n\nexport function hasLengthProperty(candidate: unknown): candidate is { length: number } {\n return typeof (candidate as { length?: unknown })?.length === \"number\";\n}\n","import { equals } from \"@jest/expect-utils\";\n\nimport { EQUALITY_TESTERS } from \"../core/constants\";\nimport { type MatcherContext } from \"../core/context\";\nimport { buildFailureMessage, formatDiff } from \"../core/messages\";\n\nexport function assertToBe<T>(ctx: MatcherContext<T>, expected: T): void {\n const pass = Object.is(ctx.value, expected);\n if (ctx.negated ? pass : !pass) {\n const baseMessage = ctx.negated\n ? \"Expected values not to be strictly equal\"\n : \"Expected values to be strictly equal\";\n ctx.fail(\"toBe\", {\n message: buildFailureMessage(\"toBe\", baseMessage, {\n actual: ctx.value,\n expected,\n diff: formatDiff(expected, ctx.value),\n }),\n actual: ctx.value,\n expected,\n });\n }\n}\n\nexport function assertToEqual<T>(ctx: MatcherContext<T>, expected: unknown): void {\n const pass = equals(ctx.value, expected, EQUALITY_TESTERS);\n if (ctx.negated ? pass : !pass) {\n const baseMessage = ctx.negated\n ? \"Expected values not to be deeply equal\"\n : \"Expected values to be deeply equal\";\n ctx.fail(\"toEqual\", {\n message: buildFailureMessage(\"toEqual\", baseMessage, {\n actual: ctx.value,\n expected,\n diff: formatDiff(expected, ctx.value),\n }),\n actual: ctx.value,\n expected,\n });\n }\n}\n\nexport function assertToStrictEqual<T>(ctx: MatcherContext<T>, expected: unknown): void {\n const pass = equals(ctx.value, expected, EQUALITY_TESTERS, true);\n if (ctx.negated ? pass : !pass) {\n const baseMessage = ctx.negated\n ? \"Expected values not to be strictly equal (including prototypes and property definitions)\"\n : \"Expected values to be strictly equal (including prototypes and property definitions)\";\n ctx.fail(\"toStrictEqual\", {\n message: buildFailureMessage(\"toStrictEqual\", baseMessage, {\n actual: ctx.value,\n expected,\n diff: formatDiff(expected, ctx.value),\n }),\n actual: ctx.value,\n expected,\n });\n }\n}\n","import type { MatcherContext } from \"../core/context\";\nimport { buildFailureMessage } from \"../core/messages\";\n\nexport function assertToBeInstanceOf<\n T,\n Ctor extends abstract new (...args: never[]) => unknown\n>(ctx: MatcherContext<T>, ctor: Ctor): InstanceType<Ctor> {\n if (typeof ctor !== \"function\") {\n ctx.fail(\"toBeInstanceOf\", {\n message: buildFailureMessage(\"toBeInstanceOf\", \"Constructor must be a callable function\", {\n expected: ctor,\n }),\n expected: ctor,\n });\n }\n\n const pass = ctx.value instanceof ctor;\n if (ctx.negated ? pass : !pass) {\n const label = ctor.name || \"<anonymous>\";\n const baseMessage = ctx.negated\n ? `Expected value not to be an instance of ${label}`\n : `Expected value to be an instance of ${label}`;\n ctx.fail(\"toBeInstanceOf\", {\n message: buildFailureMessage(\"toBeInstanceOf\", baseMessage, {\n expected: ctor,\n actual: ctx.value,\n }),\n expected: ctor,\n actual: ctx.value,\n });\n }\n\n return ctx.value as InstanceType<Ctor>;\n}\n","import type { MatcherContext } from \"../core/context\";\nimport { buildFailureMessage } from \"../core/messages\";\n\nconst NIL_MESSAGE = \"Value is null or undefined\";\n\nexport function assertToBeDefined<T>(ctx: MatcherContext<T>): NonNullable<T> {\n const isDefined = ctx.value !== null && typeof ctx.value !== \"undefined\";\n if (ctx.negated ? isDefined : !isDefined) {\n const baseMessage = ctx.negated\n ? \"Expected value to be null or undefined\"\n : NIL_MESSAGE;\n ctx.fail(\"toBeDefined\", {\n message: buildFailureMessage(\"toBeDefined\", baseMessage, {\n actual: ctx.value,\n }),\n actual: ctx.value,\n });\n }\n return ctx.value as NonNullable<T>;\n}\n\nexport function assertToBeUndefined<T>(ctx: MatcherContext<T>): undefined {\n const isUndefined = typeof ctx.value === \"undefined\";\n if (ctx.negated ? isUndefined : !isUndefined) {\n const baseMessage = ctx.negated\n ? \"Expected value not to be undefined\"\n : \"Expected value to be undefined\";\n ctx.fail(\"toBeUndefined\", {\n message: buildFailureMessage(\"toBeUndefined\", baseMessage, {\n actual: ctx.value,\n }),\n actual: ctx.value,\n });\n }\n return undefined;\n}\n\nexport function assertToBeNull<T>(ctx: MatcherContext<T>): null {\n const isNull = ctx.value === null;\n if (ctx.negated ? isNull : !isNull) {\n const baseMessage = ctx.negated\n ? \"Expected value not to be null\"\n : \"Expected value to be null\";\n ctx.fail(\"toBeNull\", {\n message: buildFailureMessage(\"toBeNull\", baseMessage, {\n actual: ctx.value,\n }),\n actual: ctx.value,\n });\n }\n return null;\n}\n","import type { MatcherContext } from \"../core/context\";\nimport { shouldFail } from \"../core/context\";\nimport { buildFailureMessage } from \"../core/messages\";\n\nfunction requireFiniteNumber<T>(\n ctx: MatcherContext<T>,\n matcher: string\n): number {\n const value = ctx.value;\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n ctx.fail(matcher, {\n message: buildFailureMessage(\n matcher,\n \"Expected value to be a finite number\",\n { actual: value }\n ),\n actual: value,\n expected: \"finite number\",\n });\n }\n return value;\n}\n\nfunction requireFiniteExpected(\n ctx: MatcherContext<unknown>,\n matcher: string,\n expected: number,\n name = \"expected\"\n): void {\n if (typeof expected !== \"number\" || !Number.isFinite(expected)) {\n ctx.fail(matcher, {\n message: buildFailureMessage(\n matcher,\n `Expected ${name} to be a finite number`,\n { actual: expected }\n ),\n actual: expected,\n expected: \"finite number\",\n });\n }\n}\n\nexport function assertToBeGreaterThan<T>(\n ctx: MatcherContext<T>,\n expected: number\n): number {\n const actual = requireFiniteNumber(ctx, \"toBeGreaterThan\");\n requireFiniteExpected(ctx as MatcherContext<unknown>, \"toBeGreaterThan\", expected);\n\n const pass = actual > expected;\n if (shouldFail(pass, ctx.negated)) {\n const baseMessage = ctx.negated\n ? `Expected value not to be greater than ${expected}`\n : `Expected value to be greater than ${expected}`;\n\n ctx.fail(\"toBeGreaterThan\", {\n message: buildFailureMessage(\"toBeGreaterThan\", baseMessage, {\n expected,\n actual,\n }),\n actual,\n expected,\n });\n }\n\n return actual;\n}\n\nexport function assertToBeGreaterThanOrEqual<T>(\n ctx: MatcherContext<T>,\n expected: number\n): number {\n const actual = requireFiniteNumber(ctx, \"toBeGreaterThanOrEqual\");\n requireFiniteExpected(\n ctx as MatcherContext<unknown>,\n \"toBeGreaterThanOrEqual\",\n expected\n );\n\n const pass = actual >= expected;\n if (shouldFail(pass, ctx.negated)) {\n const baseMessage = ctx.negated\n ? `Expected value not to be greater than or equal to ${expected}`\n : `Expected value to be greater than or equal to ${expected}`;\n\n ctx.fail(\"toBeGreaterThanOrEqual\", {\n message: buildFailureMessage(\"toBeGreaterThanOrEqual\", baseMessage, {\n expected,\n actual,\n }),\n actual,\n expected,\n });\n }\n\n return actual;\n}\n\nexport function assertToBeLessThan<T>(\n ctx: MatcherContext<T>,\n expected: number\n): number {\n const actual = requireFiniteNumber(ctx, \"toBeLessThan\");\n requireFiniteExpected(ctx as MatcherContext<unknown>, \"toBeLessThan\", expected);\n\n const pass = actual < expected;\n if (shouldFail(pass, ctx.negated)) {\n const baseMessage = ctx.negated\n ? `Expected value not to be less than ${expected}`\n : `Expected value to be less than ${expected}`;\n\n ctx.fail(\"toBeLessThan\", {\n message: buildFailureMessage(\"toBeLessThan\", baseMessage, {\n expected,\n actual,\n }),\n actual,\n expected,\n });\n }\n\n return actual;\n}\n\nexport function assertToBeLessThanOrEqual<T>(\n ctx: MatcherContext<T>,\n expected: number\n): number {\n const actual = requireFiniteNumber(ctx, \"toBeLessThanOrEqual\");\n requireFiniteExpected(\n ctx as MatcherContext<unknown>,\n \"toBeLessThanOrEqual\",\n expected\n );\n\n const pass = actual <= expected;\n if (shouldFail(pass, ctx.negated)) {\n const baseMessage = ctx.negated\n ? `Expected value not to be less than or equal to ${expected}`\n : `Expected value to be less than or equal to ${expected}`;\n\n ctx.fail(\"toBeLessThanOrEqual\", {\n message: buildFailureMessage(\"toBeLessThanOrEqual\", baseMessage, {\n expected,\n actual,\n }),\n actual,\n expected,\n });\n }\n\n return actual;\n}\n\nexport function assertToBeCloseTo<T>(\n ctx: MatcherContext<T>,\n expected: number,\n precision = 2\n): number {\n const actual = requireFiniteNumber(ctx, \"toBeCloseTo\");\n requireFiniteExpected(ctx as MatcherContext<unknown>, \"toBeCloseTo\", expected);\n\n if (!Number.isInteger(precision) || precision < 0 || precision > 20) {\n ctx.fail(\"toBeCloseTo\", {\n message: buildFailureMessage(\n \"toBeCloseTo\",\n \"Expected precision to be an integer between 0 and 20\",\n { actual: precision }\n ),\n actual: precision,\n expected: \"integer between 0 and 20\",\n });\n }\n\n const tolerance = Math.pow(10, -precision) / 2;\n const difference = Math.abs(actual - expected);\n // Floating-point operations can produce tiny rounding errors near the boundary.\n // We allow an EPSILON-scaled slack so values that are mathematically on the\n // boundary don't fail due to representation quirks.\n const epsilon = Number.EPSILON * Math.max(1, Math.abs(actual), Math.abs(expected)) * 2;\n const pass = difference <= tolerance + epsilon;\n\n if (shouldFail(pass, ctx.negated)) {\n const baseMessage = ctx.negated\n ? `Expected value not to be close to ${expected} (precision ${precision})`\n : `Expected value to be close to ${expected} (precision ${precision})`;\n\n ctx.fail(\"toBeCloseTo\", {\n message: buildFailureMessage(\"toBeCloseTo\", baseMessage, {\n expected,\n actual,\n extra: [\n `Difference: ${difference}`,\n `Tolerance: ${tolerance}`,\n ],\n }),\n actual,\n expected,\n });\n }\n\n return actual;\n}\n","import type { MatcherContext } from \"../core/context\";\nimport { buildFailureMessage } from \"../core/messages\";\n\nexport function assertToBeTruthy<T>(ctx: MatcherContext<T>): void {\n const pass = Boolean(ctx.value);\n if (ctx.negated ? pass : !pass) {\n const baseMessage = ctx.negated\n ? \"Expected value to be falsy\"\n : \"Expected value to be truthy\";\n ctx.fail(\"toBeTruthy\", {\n message: buildFailureMessage(\"toBeTruthy\", baseMessage, {\n actual: ctx.value,\n }),\n actual: ctx.value,\n });\n }\n}\n\nexport function assertToBeFalsy<T>(ctx: MatcherContext<T>): void {\n const pass = !ctx.value;\n if (ctx.negated ? pass : !pass) {\n const baseMessage = ctx.negated\n ? \"Expected value to be truthy\"\n : \"Expected value to be falsy\";\n ctx.fail(\"toBeFalsy\", {\n message: buildFailureMessage(\"toBeFalsy\", baseMessage, {\n actual: ctx.value,\n }),\n actual: ctx.value,\n });\n }\n}\n","import { EnsureError, type EnsureErrorDetails } from \"./assertion-error\";\nimport {\n type FailureDetails,\n type MatcherContext,\n type MatcherState,\n} from \"./core/context\";\nimport {\n assertArrayContaining,\n assertContainEqual,\n assertHasLength,\n assertIterableContaining,\n assertObjectContaining,\n} from \"./matchers/collections\";\nimport { assertToBe, assertToEqual, assertToStrictEqual } from \"./matchers/equality\";\nimport { assertToBeInstanceOf } from \"./matchers/instance\";\nimport {\n assertToBeDefined,\n assertToBeNull,\n assertToBeUndefined,\n} from \"./matchers/nullish\";\nimport {\n assertToBeCloseTo,\n assertToBeGreaterThan,\n assertToBeGreaterThanOrEqual,\n assertToBeLessThan,\n assertToBeLessThanOrEqual,\n} from \"./matchers/numeric\";\nimport { assertToBeFalsy, assertToBeTruthy } from \"./matchers/truthiness\";\n\nexport interface EnsureOptions {\n readonly label?: string;\n}\n\ntype Toggle<Negated extends boolean> = Negated extends true ? false : true;\n\ninterface EnsureChainInternal<T, Negated extends boolean> {\n readonly value: T;\n readonly not: EnsureChainInternal<T, Toggle<Negated>>;\n toBe(expected: T): EnsureChainInternal<T, Negated>;\n toEqual(expected: unknown): EnsureChainInternal<T, Negated>;\n toStrictEqual(expected: unknown): EnsureChainInternal<T, Negated>;\n toBeDefined(): EnsureChainInternal<Negated extends true ? T : NonNullable<T>, Negated>;\n toBeUndefined(): EnsureChainInternal<Negated extends true ? T : undefined, Negated>;\n toBeNull(): EnsureChainInternal<Negated extends true ? T : null, Negated>;\n toBeTruthy(): EnsureChainInternal<T, Negated>;\n toBeFalsy(): EnsureChainInternal<T, Negated>;\n toBeGreaterThan(expected: number): EnsureChainInternal<\n Negated extends true ? T : Extract<T, number>,\n Negated\n >;\n toBeGreaterThanOrEqual(expected: number): EnsureChainInternal<\n Negated extends true ? T : Extract<T, number>,\n Negated\n >;\n toBeLessThan(expected: number): EnsureChainInternal<\n Negated extends true ? T : Extract<T, number>,\n Negated\n >;\n toBeLessThanOrEqual(expected: number): EnsureChainInternal<\n Negated extends true ? T : Extract<T, number>,\n Negated\n >;\n toBeCloseTo(expected: number, precision?: number): EnsureChainInternal<\n Negated extends true ? T : Extract<T, number>,\n Negated\n >;\n toBeInstanceOf<Ctor extends abstract new (...args: never[]) => unknown>(\n ctor: Ctor\n ): EnsureChainInternal<Negated extends true ? T : InstanceType<Ctor>, Negated>;\n toBeObjectContaining<Shape extends Record<PropertyKey, unknown>>(\n shape: Shape\n ): EnsureChainInternal<T, Negated>;\n toBeArrayContaining(expected: readonly unknown[]): EnsureChainInternal<\n Negated extends true ? T : Extract<T, readonly unknown[]>,\n Negated\n >;\n toContainEqual(expected: unknown): EnsureChainInternal<\n Negated extends true ? T : Extract<T, readonly unknown[]>,\n Negated\n >;\n toBeIterableContaining(expected: readonly unknown[]): EnsureChainInternal<\n Negated extends true ? T : Extract<T, Iterable<unknown>>,\n Negated\n >;\n toHaveLength(expected: number): EnsureChainInternal<\n Negated extends true ? T : Extract<T, { length: number }> ,\n Negated\n >;\n}\n\nexport type EnsureChain<T> = EnsureChainInternal<T, false>;\nexport type EnsureNegatedChain<T> = EnsureChainInternal<T, true>;\n\nexport function ensure<T>(value: T, options: EnsureOptions = {}): EnsureChain<T> {\n const state = {\n value,\n negated: false as const,\n ...(options.label !== undefined ? { label: options.label } : {}),\n } satisfies MatcherState<T> & { negated: false };\n return new EnsureChainImpl<T, false>(state);\n}\n\nclass EnsureChainImpl<T, Negated extends boolean>\n implements EnsureChainInternal<T, Negated> {\n private readonly state: MatcherState<T> & { negated: Negated };\n\n constructor(state: MatcherState<T> & { negated: Negated }) {\n this.state = state;\n }\n\n public get value(): T {\n return this.state.value;\n }\n\n public get not(): EnsureChainInternal<T, Toggle<Negated>> {\n const toggled = (!this.state.negated) as Toggle<Negated>;\n const nextState = {\n value: this.state.value,\n negated: toggled,\n ...(this.state.label !== undefined ? { label: this.state.label } : {}),\n };\n return new EnsureChainImpl<T, Toggle<Negated>>(\n nextState as MatcherState<T> & { negated: Toggle<Negated> }\n );\n }\n\n public toBe(expected: T): EnsureChainInternal<T, Negated> {\n assertToBe(this.createContext(), expected);\n return this;\n }\n\n public toEqual(expected: unknown): EnsureChainInternal<T, Negated> {\n assertToEqual(this.createContext(), expected);\n return this;\n }\n\n public toStrictEqual(expected: unknown): EnsureChainInternal<T, Negated> {\n assertToStrictEqual(this.createContext(), expected);\n return this;\n }\n\n public toBeDefined(): EnsureChainInternal<Negated extends true ? T : NonNullable<T>, Negated> {\n const defined = assertToBeDefined(this.createContext());\n const next = this.state.negated ? this : this.rewrap(defined);\n return next as EnsureChainInternal<Negated extends true ? T : NonNullable<T>, Negated>;\n }\n\n public toBeUndefined(): EnsureChainInternal<Negated extends true ? T : undefined, Negated> {\n const result = assertToBeUndefined(this.createContext());\n const next = this.state.negated ? this : this.rewrap(result);\n return next as EnsureChainInternal<Negated extends true ? T : undefined, Negated>;\n }\n\n public toBeNull(): EnsureChainInternal<Negated extends true ? T : null, Negated> {\n const result = assertToBeNull(this.createContext());\n const next = this.state.negated ? this : this.rewrap(result);\n return next as EnsureChainInternal<Negated extends true ? T : null, Negated>;\n }\n\n public toBeTruthy(): EnsureChainInternal<T, Negated> {\n assertToBeTruthy(this.createContext());\n return this;\n }\n\n public toBeFalsy(): EnsureChainInternal<T, Negated> {\n assertToBeFalsy(this.createContext());\n return this;\n }\n\n public toBeGreaterThan(\n expected: number\n ): EnsureChainInternal<Negated extends true ? T : Extract<T, number>, Negated> {\n const actual = assertToBeGreaterThan(this.createContext(), expected);\n const next = this.state.negated ? this : this.rewrap(actual as Extract<T, number>);\n return next as EnsureChainInternal<\n Negated extends true ? T : Extract<T, number>,\n Negated\n >;\n }\n\n public toBeGreaterThanOrEqual(\n expected: number\n ): EnsureChainInternal<Negated extends true ? T : Extract<T, number>, Negated> {\n const actual = assertToBeGreaterThanOrEqual(this.createContext(), expected);\n const next = this.state.negated ? this : this.rewrap(actual as Extract<T, number>);\n return next as EnsureChainInternal<\n Negated extends true ? T : Extract<T, number>,\n Negated\n >;\n }\n\n public toBeLessThan(\n expected: number\n ): EnsureChainInternal<Negated extends true ? T : Extract<T, number>, Negated> {\n const actual = assertToBeLessThan(this.createContext(), expected);\n const next = this.state.negated ? this : this.rewrap(actual as Extract<T, number>);\n return next as EnsureChainInternal<\n Negated extends true ? T : Extract<T, number>,\n Negated\n >;\n }\n\n public toBeLessThanOrEqual(\n expected: number\n ): EnsureChainInternal<Negated extends true ? T : Extract<T, number>, Negated> {\n const actual = assertToBeLessThanOrEqual(this.createContext(), expected);\n const next = this.state.negated ? this : this.rewrap(actual as Extract<T, number>);\n return next as EnsureChainInternal<\n Negated extends true ? T : Extract<T, number>,\n Negated\n >;\n }\n\n public toBeCloseTo(\n expected: number,\n precision?: number\n ): EnsureChainInternal<Negated extends true ? T : Extract<T, number>, Negated> {\n const actual = assertToBeCloseTo(this.createContext(), expected, precision);\n const next = this.state.negated ? this : this.rewrap(actual as Extract<T, number>);\n return next as EnsureChainInternal<\n Negated extends true ? T : Extract<T, number>,\n Negated\n >;\n }\n\n public toBeInstanceOf<Ctor extends abstract new (...args: never[]) => unknown>(\n ctor: Ctor\n ): EnsureChainInternal<Negated extends true ? T : InstanceType<Ctor>, Negated> {\n const instance = assertToBeInstanceOf(this.createContext(), ctor);\n const next = this.state.negated ? this : this.rewrap(instance);\n return next as EnsureChainInternal<Negated extends true ? T : InstanceType<Ctor>, Negated>;\n }\n\n public toBeObjectContaining<Shape extends Record<PropertyKey, unknown>>(\n shape: Shape\n ): EnsureChainInternal<T, Negated> {\n assertObjectContaining(this.createContext(), shape);\n return this;\n }\n\n public toBeArrayContaining(\n expected: readonly unknown[]\n ): EnsureChainInternal<Negated extends true ? T : Extract<T, readonly unknown[]>, Negated> {\n const array = assertArrayContaining(this.createContext(), expected);\n const next = this.state.negated\n ? this\n : this.rewrap(array as Extract<T, readonly unknown[]>);\n return next as EnsureChainInternal<\n Negated extends true ? T : Extract<T, readonly unknown[]>,\n Negated\n >;\n }\n\n public toContainEqual(\n expected: unknown\n ): EnsureChainInternal<Negated extends true ? T : Extract<T, readonly unknown[]>, Negated> {\n const array = assertContainEqual(this.createContext(), expected);\n const next = this.state.negated\n ? this\n : this.rewrap(array as Extract<T, readonly unknown[]>);\n return next as EnsureChainInternal<\n Negated extends true ? T : Extract<T, readonly unknown[]>,\n Negated\n >;\n }\n\n public toBeIterableContaining(\n expected: readonly unknown[]\n ): EnsureChainInternal<Negated extends true ? T : Extract<T, Iterable<unknown>>, Negated> {\n const iterable = assertIterableContaining(this.createContext(), expected);\n const next = this.state.negated\n ? this\n : this.rewrap(iterable as Extract<T, Iterable<unknown>>);\n return next as EnsureChainInternal<\n Negated extends true ? T : Extract<T, Iterable<unknown>>,\n Negated\n >;\n }\n\n public toHaveLength(\n expected: number\n ): EnsureChainInternal<Negated extends true ? T : Extract<T, { length: number }>, Negated> {\n assertHasLength(this.createContext(), expected);\n const next = this.state.negated\n ? this\n : this.rewrap(this.state.value as Extract<T, { length: number }>);\n return next as EnsureChainInternal<\n Negated extends true ? T : Extract<T, { length: number }> ,\n Negated\n >;\n }\n\n private createContext(): MatcherContext<T> {\n return {\n value: this.state.value,\n negated: this.state.negated,\n fail: (matcher, details) => this.fail(matcher, details),\n ...(this.state.label !== undefined ? { label: this.state.label } : {}),\n } as MatcherContext<T>;\n }\n\n private rewrap<U>(value: U): EnsureChainImpl<U, Negated> {\n const nextState = {\n value,\n negated: this.state.negated,\n ...(this.state.label !== undefined ? { label: this.state.label } : {}),\n };\n return new EnsureChainImpl<U, Negated>(\n nextState as MatcherState<U> & { negated: Negated }\n );\n }\n\n private fail(matcher: string, details: FailureDetails): never {\n const errorDetails: EnsureErrorDetails = {\n matcher,\n message: details.message,\n ...(details.actual !== undefined ? { actual: details.actual } : {}),\n ...(details.expected !== undefined ? { expected: details.expected } : {}),\n ...(this.state.label !== undefined ? { receivedLabel: this.state.label } : {}),\n };\n throw new EnsureError(errorDetails);\n }\n}\n","import type { EnsureChain, EnsureOptions } from \"./ensure\";\nimport { ensure as baseEnsure } from \"./ensure\";\n\nexport type EnsureInvoker = typeof baseEnsure;\n\nexport type EnsureInvoke = <T>(value: T, options?: EnsureOptions) => EnsureChain<T>;\n\n/**\n * An ensure invoker that also exposes a stable, non-negated invoker.\n *\n * This exists to support plugin-level negation (`ensure.not.<plugin>.*`) without\n * forcing plugin authors to manually import the base ensure.\n *\n * Use `ensure.always(...)` for required-value extraction/preconditions that must\n * not be inverted by `.not`.\n */\nexport type EnsureInvokeWithAlways = EnsureInvoke & {\n readonly always: EnsureInvoke;\n};\n\nexport type EnsureFacade<World, Facets extends Record<string, unknown>> = EnsureInvoke &\n Facets & { readonly world: World; readonly not: Facets };\n\nexport type EnsureFactory<World, Facets extends Record<string, unknown>> = (\n world: World\n) => EnsureFacade<World, Facets>;\n\nexport interface AssertionPluginContext {\n readonly ensure: EnsureInvokeWithAlways;\n\n /**\n * True when this plugin facet is being invoked via plugin-level negation\n * (e.g. `ensure.not.<facet>.*`).\n *\n * Mirrors Jest's `this.isNot` matcher context flag.\n */\n readonly isNot: boolean;\n}\n\nexport type AssertionPlugin<World, Facet> = (\n context: AssertionPluginContext\n) => (world: World) => Facet;\n\ntype PluginFacetResult<World, Plugin> = Plugin extends AssertionPlugin<World, infer Facet>\n ? Facet\n : never;\ntype PluginFacets<World, Plugins extends Record<string, AssertionPlugin<World, unknown>>> = {\n readonly [Key in keyof Plugins]: PluginFacetResult<World, Plugins[Key]>;\n};\n\nexport type EnsurePluginFacets<\n World,\n Plugins extends Record<string, AssertionPlugin<World, unknown>>\n> = PluginFacets<World, Plugins>;\n\n/**\n * Assemble a world-aware ensure factory using the provided assertion plugins.\n * Each plugin receives the base ensure function and returns a facet builder that is\n * invoked with the current world instance. The resulting facets are attached to a\n * callable ensure facade, preserving the base ensure invocation signature.\n */\nexport function createEnsureFactory<\n World,\n Plugins extends Record<string, AssertionPlugin<World, unknown>>\n>(\n ensureFn: EnsureInvoke,\n plugins: Plugins\n): EnsureFactory<World, PluginFacets<World, Plugins>> {\n const withAlways = (\n invoker: EnsureInvoke,\n always: EnsureInvoke\n ): EnsureInvokeWithAlways => {\n Object.defineProperty(invoker, \"always\", {\n value: always,\n enumerable: false,\n configurable: false,\n writable: false,\n });\n return invoker as EnsureInvokeWithAlways;\n };\n\n const positiveEnsure = withAlways(ensureFn, ensureFn);\n const pluginEntries = (Object.keys(plugins) as Array<keyof Plugins>).map((key) => {\n const plugin = plugins[key];\n if (!plugin) {\n throw new Error(`Assertion plugin \"${String(key)}\" is not defined.`);\n }\n const factory = plugin({ ensure: positiveEnsure, isNot: false });\n return [key, factory] as const;\n });\n\n const negatedEnsureFn: EnsureInvoke = <T>(value: T, options?: EnsureOptions) => {\n return ensureFn(value, options).not as unknown as EnsureChain<T>;\n };\n\n const negativeEnsure = withAlways(negatedEnsureFn, ensureFn);\n\n const negativePluginEntries = (Object.keys(plugins) as Array<keyof Plugins>).map((key) => {\n const plugin = plugins[key];\n if (!plugin) {\n throw new Error(`Assertion plugin \"${String(key)}\" is not defined.`);\n }\n const factory = plugin({ ensure: negativeEnsure, isNot: true });\n return [key, factory] as const;\n });\n\n return (world) => {\n const facade = ((value: unknown, options?: EnsureOptions) => ensureFn(value, options)) as EnsureFacade<\n World,\n PluginFacets<World, Plugins>\n >;\n\n Object.defineProperty(facade, \"world\", {\n value: world,\n enumerable: false,\n configurable: false,\n writable: false,\n });\n\n for (const [key, buildFacet] of pluginEntries) {\n const facet = buildFacet(world);\n Object.defineProperty(facade, key, {\n value: facet,\n enumerable: true,\n configurable: false,\n writable: false,\n });\n }\n\n const notFacade = {};\n for (const [key, buildFacet] of negativePluginEntries) {\n const facet = buildFacet(world);\n Object.defineProperty(notFacade, key, {\n value: facet,\n enumerable: true,\n configurable: false,\n writable: false,\n });\n }\n\n Object.defineProperty(facade, \"not\", {\n value: notFacade,\n enumerable: true,\n configurable: false,\n writable: false,\n });\n\n return facade;\n };\n}\n\n/**\n * Create a default ensure factory without any plugins. Useful when consumers\n * want a world-aware ensure facade without additional facets.\n */\nexport function createDefaultEnsureFactory<World>(): EnsureFactory<World, Record<string, never>> {\n return createEnsureFactory<World, Record<string, never>>(baseEnsure, {});\n}\n","import type {\n HeaderlessTable,\n HeaderlessTableOptions,\n HorizontalTable,\n HorizontalTableOptions,\n MatrixTable,\n MatrixTableOptions,\n TableShape,\n VerticalTable,\n VerticalTableOptions,\n} from \"@autometa/gherkin\";\nimport type { RawTable, StepRuntimeHelpers, StepRuntimeMetadata } from \"@autometa/executor\";\n\nimport type { AssertionPlugin } from \"../plugins\";\n\n/**\n * Assertion facet attached as `ensure.runtime.*`.\n *\n * This facet is meant for **step-data ergonomics**:\n * - quick preconditions like “a table is present” / “a docstring is present”\n * - extracting required docstrings/tables with consistently-labeled failures\n *\n * It intentionally uses `ensure.always(...)` for required-value extraction so\n * plugin-level negation (`ensure.not.runtime.*`) does **not** invert these\n * preconditions.\n */\nexport interface RuntimeAssertions {\n /**\n * Assert that the current step has an attached data table.\n *\n * Works with plugin-level negation:\n * - `ensure.runtime.hasTable()` asserts table is present\n * - `ensure.not.runtime.hasTable()` asserts table is NOT present\n */\n hasTable(options?: { readonly label?: string }): void;\n\n /**\n * Assert that the current step has an attached docstring.\n *\n * Works with plugin-level negation:\n * - `ensure.runtime.hasDocstring()` asserts docstring is present\n * - `ensure.not.runtime.hasDocstring()` asserts docstring is NOT present\n */\n hasDocstring(options?: { readonly label?: string }): void;\n\n /**\n * Get the current step's docstring without consuming it.\n */\n docstring(): string | undefined;\n\n /**\n * Consume and return the current step's docstring.\n */\n consumeDocstring(): string | undefined;\n\n /**\n * Consume and return the current step's docstring.\n *\n * This is a *required extraction* helper. It is NOT negated under\n * `ensure.not.runtime.*`.\n */\n requireDocstring(options?: { readonly label?: string }): string;\n\n /**\n * Get the current step's data table coerced to the given shape without consuming it.\n */\n table(shape: \"headerless\", options?: HeaderlessTableOptions): HeaderlessTable | undefined;\n /** @inheritdoc */\n table(shape: \"horizontal\", options?: HorizontalTableOptions): HorizontalTable | undefined;\n /** @inheritdoc */\n table(shape: \"vertical\", options?: VerticalTableOptions): VerticalTable | undefined;\n /** @inheritdoc */\n table(shape: \"matrix\", options?: MatrixTableOptions): MatrixTable | undefined;\n /** @inheritdoc */\n table(\n shape: TableShape,\n options?:\n | HeaderlessTableOptions\n | HorizontalTableOptions\n | VerticalTableOptions\n | MatrixTableOptions\n ): HeaderlessTable | HorizontalTable | VerticalTable | MatrixTable | undefined;\n\n /**\n * Consume and return the current step's data table coerced to the given shape.\n */\n consumeTable(shape: \"headerless\", options?: HeaderlessTableOptions): HeaderlessTable | undefined;\n /** @inheritdoc */\n consumeTable(shape: \"horizontal\", options?: HorizontalTableOptions): HorizontalTable | undefined;\n /** @inheritdoc */\n consumeTable(shape: \"vertical\", options?: VerticalTableOptions): VerticalTable | undefined;\n /** @inheritdoc */\n consumeTable(shape: \"matrix\", options?: MatrixTableOptions): MatrixTable | undefined;\n /** @inheritdoc */\n consumeTable(\n shape: TableShape,\n options?:\n | HeaderlessTableOptions\n | HorizontalTableOptions\n | VerticalTableOptions\n | MatrixTableOptions\n ): HeaderlessTable | HorizontalTable | VerticalTable | MatrixTable | undefined;\n\n /**\n * Consume and return the current step's data table coerced to the given shape.\n *\n * This is a *required extraction* helper. It is NOT negated under\n * `ensure.not.runtime.*`.\n */\n requireTable(\n shape: \"headerless\",\n options?: HeaderlessTableOptions & { readonly label?: string }\n ): HeaderlessTable;\n /** @inheritdoc */\n requireTable(\n shape: \"horizontal\",\n options?: HorizontalTableOptions & { readonly label?: string }\n ): HorizontalTable;\n /** @inheritdoc */\n requireTable(\n shape: \"vertical\",\n options?: VerticalTableOptions & { readonly label?: string }\n ): VerticalTable;\n /** @inheritdoc */\n requireTable(\n shape: \"matrix\",\n options?: MatrixTableOptions & { readonly label?: string }\n ): MatrixTable;\n /** @inheritdoc */\n requireTable(\n shape: TableShape,\n options?: (\n | HeaderlessTableOptions\n | HorizontalTableOptions\n | VerticalTableOptions\n | MatrixTableOptions\n ) & { readonly label?: string }\n ): HeaderlessTable | HorizontalTable | VerticalTable | MatrixTable;\n\n /**\n * Return the underlying raw data table (array of string arrays) without consuming it.\n *\n * This is useful for custom table parsing or user-defined table semantics.\n */\n rawTable(): RawTable | undefined;\n\n /**\n * Consume the current step's raw data table.\n */\n consumeRawTable(options?: HeaderlessTableOptions): RawTable | undefined;\n\n /**\n * Consume and return the current step's raw data table.\n *\n * This is a *required extraction* helper. It is NOT negated under\n * `ensure.not.runtime.*`.\n */\n requireRawTable(options?: HeaderlessTableOptions & { readonly label?: string }): RawTable;\n\n /**\n * Return runtime metadata about the current feature/scenario/step, if available.\n */\n stepMetadata(): StepRuntimeMetadata | undefined;\n}\n\ntype WorldWithRuntime = {\n readonly runtime: StepRuntimeHelpers;\n};\n\n/**\n * Standard assertion plugin that provides step-runtime helpers as `ensure.runtime.*`.\n *\n * Register via the runner:\n *\n * ```ts\n * const runner = CucumberRunner.builder()\n * .assertionPlugins({ runtime: runtimeAssertionsPlugin<MyWorld>() });\n * ```\n */\nexport const runtimeAssertionsPlugin = <\n World extends WorldWithRuntime,\n>(): AssertionPlugin<World, RuntimeAssertions> =>\n ({ ensure }) =>\n (world) => {\n const defaultTableLabel = \"step data table\";\n const defaultDocstringLabel = \"step docstring\";\n\n function table(\n shape: \"headerless\",\n options?: HeaderlessTableOptions\n ): HeaderlessTable | undefined;\n function table(\n shape: \"horizontal\",\n options?: HorizontalTableOptions\n ): HorizontalTable | undefined;\n function table(\n shape: \"vertical\",\n options?: VerticalTableOptions\n ): VerticalTable | undefined;\n function table(\n shape: \"matrix\",\n options?: MatrixTableOptions\n ): MatrixTable | undefined;\n function table(\n shape: TableShape,\n options?:\n | HeaderlessTableOptions\n | HorizontalTableOptions\n | VerticalTableOptions\n | MatrixTableOptions\n ): HeaderlessTable | HorizontalTable | VerticalTable | MatrixTable | undefined;\n function table(\n shape: TableShape,\n options?:\n | HeaderlessTableOptions\n | HorizontalTableOptions\n | VerticalTableOptions\n | MatrixTableOptions\n ): HeaderlessTable | HorizontalTable | VerticalTable | MatrixTable | undefined {\n return world.runtime.getTable(shape, options as never);\n }\n\n function consumeTable(\n shape: \"headerless\",\n options?: HeaderlessTableOptions\n ): HeaderlessTable | undefined;\n function consumeTable(\n shape: \"horizontal\",\n options?: HorizontalTableOptions\n ): HorizontalTable | undefined;\n function consumeTable(\n shape: \"vertical\",\n options?: VerticalTableOptions\n ): VerticalTable | undefined;\n function consumeTable(\n shape: \"matrix\",\n options?: MatrixTableOptions\n ): MatrixTable | undefined;\n function consumeTable(\n shape: TableShape,\n options?:\n | HeaderlessTableOptions\n | HorizontalTableOptions\n | VerticalTableOptions\n | MatrixTableOptions\n ): HeaderlessTable | HorizontalTable | VerticalTable | MatrixTable | undefined;\n function consumeTable(\n shape: TableShape,\n options?:\n | HeaderlessTableOptions\n | HorizontalTableOptions\n | VerticalTableOptions\n | MatrixTableOptions\n ): HeaderlessTable | HorizontalTable | VerticalTable | MatrixTable | undefined {\n return world.runtime.consumeTable(shape, options as never);\n }\n\n function requireTable(\n shape: \"headerless\",\n options?: HeaderlessTableOptions & { readonly label?: string }\n ): HeaderlessTable;\n function requireTable(\n shape: \"horizontal\",\n options?: HorizontalTableOptions & { readonly label?: string }\n ): HorizontalTable;\n function requireTable(\n shape: \"vertical\",\n options?: VerticalTableOptions & { readonly label?: string }\n ): VerticalTable;\n function requireTable(\n shape: \"matrix\",\n options?: MatrixTableOptions & { readonly label?: string }\n ): MatrixTable;\n function requireTable(\n shape: TableShape,\n options?: (\n | HeaderlessTableOptions\n | HorizontalTableOptions\n | VerticalTableOptions\n | MatrixTableOptions\n ) & { readonly label?: string }\n ): HeaderlessTable | HorizontalTable | VerticalTable | MatrixTable;\n function requireTable(\n shape: TableShape,\n options?: (\n | HeaderlessTableOptions\n | HorizontalTableOptions\n | VerticalTableOptions\n | MatrixTableOptions\n ) & { readonly label?: string }\n ): HeaderlessTable | HorizontalTable | VerticalTable | MatrixTable {\n const { label, ...tableOptions } = (options ?? {}) as {\n readonly label?: string;\n } & (\n | HeaderlessTableOptions\n | HorizontalTableOptions\n | VerticalTableOptions\n | MatrixTableOptions\n );\n\n const table = consumeTable(shape, tableOptions);\n return ensure.always(table, {\n label:\n label ??\n `Expected ${shape} ${defaultTableLabel} to be attached to the current step.`,\n })\n .toBeDefined()\n .value as HeaderlessTable | HorizontalTable | VerticalTable | MatrixTable;\n }\n\n function consumeRawTable(options?: HeaderlessTableOptions): RawTable | undefined {\n // `getRawTable()` does not consume; to consume we piggy-back on consuming a\n // headerless table.\n const tableInstance = consumeTable(\"headerless\", options);\n return tableInstance?.raw();\n }\n\n function requireRawTable(\n options?: HeaderlessTableOptions & { readonly label?: string }\n ): RawTable {\n const { label, ...tableOptions } = (options ?? {}) as {\n readonly label?: string;\n } & HeaderlessTableOptions;\n\n const raw = consumeRawTable(tableOptions);\n return ensure.always(raw, {\n label: label ?? `Expected ${defaultTableLabel} to be attached to the current step.`,\n })\n .toBeDefined()\n .value;\n }\n\n return {\n hasTable(options) {\n ensure(world.runtime.hasTable, {\n label: options?.label ?? `${defaultTableLabel} is present`,\n }).toBeTruthy();\n },\n hasDocstring(options) {\n ensure(world.runtime.hasDocstring, {\n label: options?.label ?? `${defaultDocstringLabel} is present`,\n }).toBeTruthy();\n },\n docstring() {\n return world.runtime.getDocstring();\n },\n consumeDocstring() {\n return world.runtime.consumeDocstring();\n },\n requireDocstring(options) {\n const docstring = world.runtime.consumeDocstring();\n return ensure.always(docstring, {\n label:\n options?.label ??\n `Expected ${defaultDocstringLabel} to be attached to the current step.`,\n })\n .toBeDefined()\n .value as string;\n },\n table,\n consumeTable,\n requireTable,\n rawTable() {\n return world.runtime.getRawTable();\n },\n consumeRawTable,\n requireRawTable,\n stepMetadata() {\n return world.runtime.getStepMetadata();\n },\n };\n };\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type MatcherContext } from "../core/context";
|
|
2
|
+
export declare function assertObjectContaining<T>(ctx: MatcherContext<T>, shape: Record<PropertyKey, unknown>): void;
|
|
3
|
+
export declare function assertArrayContaining<T>(ctx: MatcherContext<T>, expected: readonly unknown[]): readonly unknown[];
|
|
4
|
+
export declare function assertContainEqual<T>(ctx: MatcherContext<T>, expected: unknown): readonly unknown[];
|
|
5
|
+
export declare function assertIterableContaining<T>(ctx: MatcherContext<T>, expected: readonly unknown[]): Iterable<unknown>;
|
|
6
|
+
export declare function assertHasLength<T>(ctx: MatcherContext<T>, expected: number): number;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type MatcherContext } from "../core/context";
|
|
2
|
+
export declare function assertToBe<T>(ctx: MatcherContext<T>, expected: T): void;
|
|
3
|
+
export declare function assertToEqual<T>(ctx: MatcherContext<T>, expected: unknown): void;
|
|
4
|
+
export declare function assertToStrictEqual<T>(ctx: MatcherContext<T>, expected: unknown): void;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { MatcherContext } from "../core/context";
|
|
3
|
+
type HeadersLike = {
|
|
4
|
+
get(name: string): string | null;
|
|
5
|
+
has?(name: string): boolean;
|
|
6
|
+
entries?: () => IterableIterator<[string, string]>;
|
|
7
|
+
[Symbol.iterator]?: () => IterableIterator<[string, string]>;
|
|
8
|
+
};
|
|
9
|
+
type HeaderSource = HeadersLike | Record<string, unknown> | Headers;
|
|
10
|
+
export type HttpResponseLike = {
|
|
11
|
+
status: number;
|
|
12
|
+
statusText?: string;
|
|
13
|
+
headers: HeaderSource;
|
|
14
|
+
data?: unknown;
|
|
15
|
+
raw?: unknown;
|
|
16
|
+
};
|
|
17
|
+
interface NormalizedResponse {
|
|
18
|
+
readonly status: number;
|
|
19
|
+
readonly statusText: string;
|
|
20
|
+
readonly headers: Record<string, string>;
|
|
21
|
+
readonly original: unknown;
|
|
22
|
+
}
|
|
23
|
+
export type StatusExpectation = number | `${1 | 2 | 3 | 4 | 5}xx` | readonly [number, number] | {
|
|
24
|
+
readonly min: number;
|
|
25
|
+
readonly max: number;
|
|
26
|
+
} | ((status: number) => boolean);
|
|
27
|
+
export type HeaderExpectation = string | RegExp | readonly string[] | ((value: string) => boolean);
|
|
28
|
+
export interface CacheControlExpectation {
|
|
29
|
+
readonly cacheability?: "public" | "private";
|
|
30
|
+
readonly maxAge?: number | {
|
|
31
|
+
readonly min?: number;
|
|
32
|
+
readonly max?: number;
|
|
33
|
+
};
|
|
34
|
+
readonly sMaxAge?: number;
|
|
35
|
+
readonly revalidate?: boolean;
|
|
36
|
+
readonly immutable?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export declare function assertToHaveStatus<T>(ctx: MatcherContext<T>, expectation: StatusExpectation): void;
|
|
39
|
+
export declare function assertToHaveHeader<T>(ctx: MatcherContext<T>, name: string, expectation?: HeaderExpectation): string | undefined;
|
|
40
|
+
export declare function assertToBeCacheable<T>(ctx: MatcherContext<T>, expectation?: CacheControlExpectation): void;
|
|
41
|
+
export declare function assertToHaveCorrelationId<T>(ctx: MatcherContext<T>, headerName?: string): string;
|
|
42
|
+
export type { NormalizedResponse };
|
|
43
|
+
export interface HttpResponseSnapshot<T = unknown> {
|
|
44
|
+
status: number;
|
|
45
|
+
statusText: string;
|
|
46
|
+
headers: Record<string, string>;
|
|
47
|
+
data: T;
|
|
48
|
+
request?: unknown;
|
|
49
|
+
}
|
|
50
|
+
export declare function fromHttpResponse<T extends {
|
|
51
|
+
headers: Record<string, string>;
|
|
52
|
+
}>(response: T & {
|
|
53
|
+
status: number;
|
|
54
|
+
statusText?: string;
|
|
55
|
+
data?: unknown;
|
|
56
|
+
}): HttpResponseLike;
|
|
57
|
+
export declare function fromFetchResponse(response: Response, data?: unknown): HttpResponseLike;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { MatcherContext } from "../core/context";
|
|
2
|
+
export declare function assertToBeDefined<T>(ctx: MatcherContext<T>): NonNullable<T>;
|
|
3
|
+
export declare function assertToBeUndefined<T>(ctx: MatcherContext<T>): undefined;
|
|
4
|
+
export declare function assertToBeNull<T>(ctx: MatcherContext<T>): null;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MatcherContext } from "../core/context";
|
|
2
|
+
export declare function assertToBeGreaterThan<T>(ctx: MatcherContext<T>, expected: number): number;
|
|
3
|
+
export declare function assertToBeGreaterThanOrEqual<T>(ctx: MatcherContext<T>, expected: number): number;
|
|
4
|
+
export declare function assertToBeLessThan<T>(ctx: MatcherContext<T>, expected: number): number;
|
|
5
|
+
export declare function assertToBeLessThanOrEqual<T>(ctx: MatcherContext<T>, expected: number): number;
|
|
6
|
+
export declare function assertToBeCloseTo<T>(ctx: MatcherContext<T>, expected: number, precision?: number): number;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { HeaderlessTable, HeaderlessTableOptions, HorizontalTable, HorizontalTableOptions, MatrixTable, MatrixTableOptions, TableShape, VerticalTable, VerticalTableOptions } from "@autometa/gherkin";
|
|
2
|
+
import type { RawTable, StepRuntimeHelpers, StepRuntimeMetadata } from "@autometa/executor";
|
|
3
|
+
import type { AssertionPlugin } from "../plugins";
|
|
4
|
+
/**
|
|
5
|
+
* Assertion facet attached as `ensure.runtime.*`.
|
|
6
|
+
*
|
|
7
|
+
* This facet is meant for **step-data ergonomics**:
|
|
8
|
+
* - quick preconditions like “a table is present” / “a docstring is present”
|
|
9
|
+
* - extracting required docstrings/tables with consistently-labeled failures
|
|
10
|
+
*
|
|
11
|
+
* It intentionally uses `ensure.always(...)` for required-value extraction so
|
|
12
|
+
* plugin-level negation (`ensure.not.runtime.*`) does **not** invert these
|
|
13
|
+
* preconditions.
|
|
14
|
+
*/
|
|
15
|
+
export interface RuntimeAssertions {
|
|
16
|
+
/**
|
|
17
|
+
* Assert that the current step has an attached data table.
|
|
18
|
+
*
|
|
19
|
+
* Works with plugin-level negation:
|
|
20
|
+
* - `ensure.runtime.hasTable()` asserts table is present
|
|
21
|
+
* - `ensure.not.runtime.hasTable()` asserts table is NOT present
|
|
22
|
+
*/
|
|
23
|
+
hasTable(options?: {
|
|
24
|
+
readonly label?: string;
|
|
25
|
+
}): void;
|
|
26
|
+
/**
|
|
27
|
+
* Assert that the current step has an attached docstring.
|
|
28
|
+
*
|
|
29
|
+
* Works with plugin-level negation:
|
|
30
|
+
* - `ensure.runtime.hasDocstring()` asserts docstring is present
|
|
31
|
+
* - `ensure.not.runtime.hasDocstring()` asserts docstring is NOT present
|
|
32
|
+
*/
|
|
33
|
+
hasDocstring(options?: {
|
|
34
|
+
readonly label?: string;
|
|
35
|
+
}): void;
|
|
36
|
+
/**
|
|
37
|
+
* Get the current step's docstring without consuming it.
|
|
38
|
+
*/
|
|
39
|
+
docstring(): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Consume and return the current step's docstring.
|
|
42
|
+
*/
|
|
43
|
+
consumeDocstring(): string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Consume and return the current step's docstring.
|
|
46
|
+
*
|
|
47
|
+
* This is a *required extraction* helper. It is NOT negated under
|
|
48
|
+
* `ensure.not.runtime.*`.
|
|
49
|
+
*/
|
|
50
|
+
requireDocstring(options?: {
|
|
51
|
+
readonly label?: string;
|
|
52
|
+
}): string;
|
|
53
|
+
/**
|
|
54
|
+
* Get the current step's data table coerced to the given shape without consuming it.
|
|
55
|
+
*/
|
|
56
|
+
table(shape: "headerless", options?: HeaderlessTableOptions): HeaderlessTable | undefined;
|
|
57
|
+
/** @inheritdoc */
|
|
58
|
+
table(shape: "horizontal", options?: HorizontalTableOptions): HorizontalTable | undefined;
|
|
59
|
+
/** @inheritdoc */
|
|
60
|
+
table(shape: "vertical", options?: VerticalTableOptions): VerticalTable | undefined;
|
|
61
|
+
/** @inheritdoc */
|
|
62
|
+
table(shape: "matrix", options?: MatrixTableOptions): MatrixTable | undefined;
|
|
63
|
+
/** @inheritdoc */
|
|
64
|
+
table(shape: TableShape, options?: HeaderlessTableOptions | HorizontalTableOptions | VerticalTableOptions | MatrixTableOptions): HeaderlessTable | HorizontalTable | VerticalTable | MatrixTable | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Consume and return the current step's data table coerced to the given shape.
|
|
67
|
+
*/
|
|
68
|
+
consumeTable(shape: "headerless", options?: HeaderlessTableOptions): HeaderlessTable | undefined;
|
|
69
|
+
/** @inheritdoc */
|
|
70
|
+
consumeTable(shape: "horizontal", options?: HorizontalTableOptions): HorizontalTable | undefined;
|
|
71
|
+
/** @inheritdoc */
|
|
72
|
+
consumeTable(shape: "vertical", options?: VerticalTableOptions): VerticalTable | undefined;
|
|
73
|
+
/** @inheritdoc */
|
|
74
|
+
consumeTable(shape: "matrix", options?: MatrixTableOptions): MatrixTable | undefined;
|
|
75
|
+
/** @inheritdoc */
|
|
76
|
+
consumeTable(shape: TableShape, options?: HeaderlessTableOptions | HorizontalTableOptions | VerticalTableOptions | MatrixTableOptions): HeaderlessTable | HorizontalTable | VerticalTable | MatrixTable | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Consume and return the current step's data table coerced to the given shape.
|
|
79
|
+
*
|
|
80
|
+
* This is a *required extraction* helper. It is NOT negated under
|
|
81
|
+
* `ensure.not.runtime.*`.
|
|
82
|
+
*/
|
|
83
|
+
requireTable(shape: "headerless", options?: HeaderlessTableOptions & {
|
|
84
|
+
readonly label?: string;
|
|
85
|
+
}): HeaderlessTable;
|
|
86
|
+
/** @inheritdoc */
|
|
87
|
+
requireTable(shape: "horizontal", options?: HorizontalTableOptions & {
|
|
88
|
+
readonly label?: string;
|
|
89
|
+
}): HorizontalTable;
|
|
90
|
+
/** @inheritdoc */
|
|
91
|
+
requireTable(shape: "vertical", options?: VerticalTableOptions & {
|
|
92
|
+
readonly label?: string;
|
|
93
|
+
}): VerticalTable;
|
|
94
|
+
/** @inheritdoc */
|
|
95
|
+
requireTable(shape: "matrix", options?: MatrixTableOptions & {
|
|
96
|
+
readonly label?: string;
|
|
97
|
+
}): MatrixTable;
|
|
98
|
+
/** @inheritdoc */
|
|
99
|
+
requireTable(shape: TableShape, options?: (HeaderlessTableOptions | HorizontalTableOptions | VerticalTableOptions | MatrixTableOptions) & {
|
|
100
|
+
readonly label?: string;
|
|
101
|
+
}): HeaderlessTable | HorizontalTable | VerticalTable | MatrixTable;
|
|
102
|
+
/**
|
|
103
|
+
* Return the underlying raw data table (array of string arrays) without consuming it.
|
|
104
|
+
*
|
|
105
|
+
* This is useful for custom table parsing or user-defined table semantics.
|
|
106
|
+
*/
|
|
107
|
+
rawTable(): RawTable | undefined;
|
|
108
|
+
/**
|
|
109
|
+
* Consume the current step's raw data table.
|
|
110
|
+
*/
|
|
111
|
+
consumeRawTable(options?: HeaderlessTableOptions): RawTable | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* Consume and return the current step's raw data table.
|
|
114
|
+
*
|
|
115
|
+
* This is a *required extraction* helper. It is NOT negated under
|
|
116
|
+
* `ensure.not.runtime.*`.
|
|
117
|
+
*/
|
|
118
|
+
requireRawTable(options?: HeaderlessTableOptions & {
|
|
119
|
+
readonly label?: string;
|
|
120
|
+
}): RawTable;
|
|
121
|
+
/**
|
|
122
|
+
* Return runtime metadata about the current feature/scenario/step, if available.
|
|
123
|
+
*/
|
|
124
|
+
stepMetadata(): StepRuntimeMetadata | undefined;
|
|
125
|
+
}
|
|
126
|
+
type WorldWithRuntime = {
|
|
127
|
+
readonly runtime: StepRuntimeHelpers;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Standard assertion plugin that provides step-runtime helpers as `ensure.runtime.*`.
|
|
131
|
+
*
|
|
132
|
+
* Register via the runner:
|
|
133
|
+
*
|
|
134
|
+
* ```ts
|
|
135
|
+
* const runner = CucumberRunner.builder()
|
|
136
|
+
* .assertionPlugins({ runtime: runtimeAssertionsPlugin<MyWorld>() });
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export declare const runtimeAssertionsPlugin: <World extends WorldWithRuntime>() => AssertionPlugin<World, RuntimeAssertions>;
|
|
140
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { EnsureChain, EnsureOptions } from "./ensure";
|
|
2
|
+
import { ensure as baseEnsure } from "./ensure";
|
|
3
|
+
export type EnsureInvoker = typeof baseEnsure;
|
|
4
|
+
export type EnsureInvoke = <T>(value: T, options?: EnsureOptions) => EnsureChain<T>;
|
|
5
|
+
/**
|
|
6
|
+
* An ensure invoker that also exposes a stable, non-negated invoker.
|
|
7
|
+
*
|
|
8
|
+
* This exists to support plugin-level negation (`ensure.not.<plugin>.*`) without
|
|
9
|
+
* forcing plugin authors to manually import the base ensure.
|
|
10
|
+
*
|
|
11
|
+
* Use `ensure.always(...)` for required-value extraction/preconditions that must
|
|
12
|
+
* not be inverted by `.not`.
|
|
13
|
+
*/
|
|
14
|
+
export type EnsureInvokeWithAlways = EnsureInvoke & {
|
|
15
|
+
readonly always: EnsureInvoke;
|
|
16
|
+
};
|
|
17
|
+
export type EnsureFacade<World, Facets extends Record<string, unknown>> = EnsureInvoke & Facets & {
|
|
18
|
+
readonly world: World;
|
|
19
|
+
readonly not: Facets;
|
|
20
|
+
};
|
|
21
|
+
export type EnsureFactory<World, Facets extends Record<string, unknown>> = (world: World) => EnsureFacade<World, Facets>;
|
|
22
|
+
export interface AssertionPluginContext {
|
|
23
|
+
readonly ensure: EnsureInvokeWithAlways;
|
|
24
|
+
/**
|
|
25
|
+
* True when this plugin facet is being invoked via plugin-level negation
|
|
26
|
+
* (e.g. `ensure.not.<facet>.*`).
|
|
27
|
+
*
|
|
28
|
+
* Mirrors Jest's `this.isNot` matcher context flag.
|
|
29
|
+
*/
|
|
30
|
+
readonly isNot: boolean;
|
|
31
|
+
}
|
|
32
|
+
export type AssertionPlugin<World, Facet> = (context: AssertionPluginContext) => (world: World) => Facet;
|
|
33
|
+
type PluginFacetResult<World, Plugin> = Plugin extends AssertionPlugin<World, infer Facet> ? Facet : never;
|
|
34
|
+
type PluginFacets<World, Plugins extends Record<string, AssertionPlugin<World, unknown>>> = {
|
|
35
|
+
readonly [Key in keyof Plugins]: PluginFacetResult<World, Plugins[Key]>;
|
|
36
|
+
};
|
|
37
|
+
export type EnsurePluginFacets<World, Plugins extends Record<string, AssertionPlugin<World, unknown>>> = PluginFacets<World, Plugins>;
|
|
38
|
+
/**
|
|
39
|
+
* Assemble a world-aware ensure factory using the provided assertion plugins.
|
|
40
|
+
* Each plugin receives the base ensure function and returns a facet builder that is
|
|
41
|
+
* invoked with the current world instance. The resulting facets are attached to a
|
|
42
|
+
* callable ensure facade, preserving the base ensure invocation signature.
|
|
43
|
+
*/
|
|
44
|
+
export declare function createEnsureFactory<World, Plugins extends Record<string, AssertionPlugin<World, unknown>>>(ensureFn: EnsureInvoke, plugins: Plugins): EnsureFactory<World, PluginFacets<World, Plugins>>;
|
|
45
|
+
/**
|
|
46
|
+
* Create a default ensure factory without any plugins. Useful when consumers
|
|
47
|
+
* want a world-aware ensure facade without additional facets.
|
|
48
|
+
*/
|
|
49
|
+
export declare function createDefaultEnsureFactory<World>(): EnsureFactory<World, Record<string, never>>;
|
|
50
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@autometa/assertions",
|
|
3
|
+
"version": "1.0.0-rc.0",
|
|
4
|
+
"description": "Runner-agnostic assertion helpers powered by ensure(value) matcher chains.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.cjs",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs",
|
|
15
|
+
"default": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@cucumber/cucumber-expressions": "^16.1.2",
|
|
21
|
+
"@jest/expect-utils": "^29.7.0",
|
|
22
|
+
"jest-diff": "^29.7.0",
|
|
23
|
+
"jest-matcher-utils": "^29.7.0",
|
|
24
|
+
"tslib": "^2.6.2",
|
|
25
|
+
"@autometa/gherkin": "1.0.0-rc.0",
|
|
26
|
+
"@autometa/cucumber-expressions": "1.0.0-rc.0",
|
|
27
|
+
"@autometa/injection": "1.0.0-rc.0",
|
|
28
|
+
"@autometa/scopes": "1.0.0-rc.0",
|
|
29
|
+
"@autometa/executor": "1.0.0-rc.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^18.11.18",
|
|
33
|
+
"@typescript-eslint/eslint-plugin": "^5.54.1",
|
|
34
|
+
"@typescript-eslint/parser": "^5.54.1",
|
|
35
|
+
"eslint": "^8.37.0",
|
|
36
|
+
"eslint-config-prettier": "^8.3.0",
|
|
37
|
+
"rimraf": "^4.1.2",
|
|
38
|
+
"tsup": "^7.2.0",
|
|
39
|
+
"typescript": "^4.9.5",
|
|
40
|
+
"vitest": "1.4.0",
|
|
41
|
+
"eslint-config-custom": "0.6.0",
|
|
42
|
+
"tsconfig": "0.7.0",
|
|
43
|
+
"tsup-config": "0.1.0"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"type-check": "tsc --noEmit -p tsconfig.dev.json",
|
|
47
|
+
"type-check:watch": "tsc --noEmit --watch -p tsconfig.dev.json",
|
|
48
|
+
"build": "tsup && pnpm run build:types",
|
|
49
|
+
"build:types": "rimraf tsconfig.types.tsbuildinfo && tsc --build tsconfig.types.json",
|
|
50
|
+
"build:watch": "tsup --watch",
|
|
51
|
+
"dev": "tsup --watch",
|
|
52
|
+
"test": "vitest run --passWithNoTests",
|
|
53
|
+
"test:watch": "vitest --passWithNoTests",
|
|
54
|
+
"test:ui": "vitest --ui --passWithNoTests",
|
|
55
|
+
"coverage": "vitest run --coverage --passWithNoTests",
|
|
56
|
+
"lint": "eslint . --max-warnings 0",
|
|
57
|
+
"lint:fix": "eslint . --fix",
|
|
58
|
+
"prettify": "prettier --config .prettierrc 'src/**/*.ts' --write",
|
|
59
|
+
"clean": "rimraf dist"
|
|
60
|
+
}
|
|
61
|
+
}
|