@elench/testkit 0.1.19 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,11 +5,11 @@ CLI that reads `runner.manifest.json` plus `testkit.config.json` from a product
5
5
  ## Prerequisites
6
6
 
7
7
  ```bash
8
- sudo snap install k6
9
8
  sudo apt-get install -y jq
10
9
  ```
11
10
 
12
- For DAL suites, `@elench/testkit` ships its own `k6` SQL binary.
11
+ `@elench/testkit` ships its own `k6` binary and uses it for both HTTP and DAL suites by default.
12
+ If you need to force a different binary, set `TESTKIT_K6_BIN` to an absolute or relative path.
13
13
 
14
14
  Database isolation uses Docker-managed local Postgres containers. `testkit` creates and reuses template databases automatically, then clones per-worker databases from those templates for fast reruns. The default image is `pgvector/pgvector:pg16`.
15
15
 
@@ -77,6 +77,12 @@ const suite = defineHttpSuite({ auth: clerkSessionAuth }, ({ req, setupData }) =
77
77
  `testkit` bundles these imports before invoking k6, so tests do not need
78
78
  generated `_testkit` files or direct package-manager path imports.
79
79
 
80
+ If you need to override the packaged `k6` binary for local environment reasons:
81
+
82
+ ```bash
83
+ TESTKIT_K6_BIN=/path/to/k6 npx @elench/testkit int
84
+ ```
85
+
80
86
  Legacy compatibility:
81
87
 
82
88
  - `testkit runtime install`
@@ -173,5 +179,4 @@ npm run test:system
173
179
  `test:system` runs real end-to-end fixtures from `test/fixtures/system/`. It requires:
174
180
 
175
181
  - Docker with a running daemon
176
- - `k6` on `PATH`
177
182
  - Playwright Chromium browser assets available to `@playwright/test`
@@ -23,6 +23,7 @@ import {
23
23
 
24
24
  const RUNNER_MANIFEST = "runner.manifest.json";
25
25
  const TESTKIT_CONFIG = "testkit.config.json";
26
+ const TESTKIT_K6_BIN = "TESTKIT_K6_BIN";
26
27
  export function parseDotenv(filePath) {
27
28
  if (!fs.existsSync(filePath)) return {};
28
29
  return parseDotenvString(fs.readFileSync(filePath, "utf8"));
@@ -94,15 +95,35 @@ export function loadConfigs(opts = {}) {
94
95
  });
95
96
  }
96
97
 
97
- export function resolveDalBinary() {
98
+ export function resolveK6Binary() {
99
+ const override = process.env[TESTKIT_K6_BIN]?.trim();
100
+ if (override) {
101
+ const isPathLike =
102
+ path.isAbsolute(override) ||
103
+ override.includes(path.sep) ||
104
+ override.includes(path.posix.sep) ||
105
+ override.includes(path.win32.sep);
106
+ const overridePath = isPathLike ? path.resolve(process.cwd(), override) : override;
107
+
108
+ if (isPathLike && !fs.existsSync(overridePath)) {
109
+ throw new Error(`${TESTKIT_K6_BIN} points to a missing file: ${overridePath}`);
110
+ }
111
+
112
+ return overridePath;
113
+ }
114
+
98
115
  const thisFile = fileURLToPath(import.meta.url);
99
116
  const abs = path.resolve(path.dirname(thisFile), "..", "..", "vendor", "k6");
100
117
  if (!fs.existsSync(abs)) {
101
- throw new Error(`Bundled DAL k6 binary not found: ${abs}`);
118
+ throw new Error(`Bundled k6 binary not found: ${abs}`);
102
119
  }
103
120
  return abs;
104
121
  }
105
122
 
123
+ export function resolveDalBinary() {
124
+ return resolveK6Binary();
125
+ }
126
+
106
127
  export function resolveServiceCwd(productDir, maybeRelative) {
107
128
  return path.resolve(productDir, maybeRelative || ".");
108
129
  }
@@ -1,12 +1,44 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
- import { describe, expect, it } from "vitest";
4
- import { resolveDalBinary } from "./index.mjs";
3
+ import os from "os";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import { resolveDalBinary, resolveK6Binary } from "./index.mjs";
6
+
7
+ const originalK6Bin = process.env.TESTKIT_K6_BIN;
8
+
9
+ afterEach(() => {
10
+ if (originalK6Bin === undefined) {
11
+ delete process.env.TESTKIT_K6_BIN;
12
+ } else {
13
+ process.env.TESTKIT_K6_BIN = originalK6Bin;
14
+ }
15
+ });
5
16
 
6
17
  describe("config-index", () => {
7
- it("resolves the bundled DAL k6 binary from the package root", () => {
8
- const binaryPath = resolveDalBinary();
18
+ it("resolves the bundled k6 binary from the package root", () => {
19
+ const binaryPath = resolveK6Binary();
9
20
  expect(path.basename(binaryPath)).toBe("k6");
10
21
  expect(fs.existsSync(binaryPath)).toBe(true);
11
22
  });
23
+
24
+ it("keeps resolveDalBinary aligned with the shared k6 resolver", () => {
25
+ expect(resolveDalBinary()).toBe(resolveK6Binary());
26
+ });
27
+
28
+ it("uses TESTKIT_K6_BIN when provided with a relative path", () => {
29
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-k6-"));
30
+ const binPath = path.join(tempDir, "k6-custom");
31
+ fs.writeFileSync(binPath, "#!/usr/bin/env bash\nexit 0\n");
32
+ process.env.TESTKIT_K6_BIN = path.relative(process.cwd(), binPath);
33
+
34
+ expect(resolveK6Binary()).toBe(binPath);
35
+ });
36
+
37
+ it("throws a clear error when TESTKIT_K6_BIN points at a missing path", () => {
38
+ process.env.TESTKIT_K6_BIN = "./definitely-missing-k6-bin";
39
+
40
+ expect(() => resolveK6Binary()).toThrow(
41
+ /TESTKIT_K6_BIN points to a missing file/
42
+ );
43
+ });
12
44
  });
@@ -4,7 +4,7 @@ import { spawn } from "child_process";
4
4
  import net from "net";
5
5
  import { execa, execaCommand } from "execa";
6
6
  import { bundleK6File } from "../bundler/index.mjs";
7
- import { resolveDalBinary, resolveServiceCwd } from "../config/index.mjs";
7
+ import { resolveK6Binary, resolveServiceCwd } from "../config/index.mjs";
8
8
  import {
9
9
  cleanupOrphanedLocalInfrastructure,
10
10
  destroyRuntimeDatabase,
@@ -521,6 +521,7 @@ async function runHttpK6Batch(targetConfig, batch) {
521
521
 
522
522
  async function runHttpK6Task(targetConfig, task, baseUrl) {
523
523
  const absFile = path.join(targetConfig.productDir, task.file);
524
+ const k6Binary = resolveK6Binary();
524
525
  const bundledFile = await bundleK6File({
525
526
  productDir: targetConfig.productDir,
526
527
  serviceName: targetConfig.name,
@@ -529,7 +530,7 @@ async function runHttpK6Task(targetConfig, task, baseUrl) {
529
530
  console.log(`·· ${targetConfig.workerLabel}:${task.suiteName} → ${task.file}`);
530
531
  const startedAt = Date.now();
531
532
  try {
532
- await execa("k6", ["run", "--address", "127.0.0.1:0", "-e", `BASE_URL=${baseUrl}`, bundledFile], {
533
+ await execa(k6Binary, ["run", "--address", "127.0.0.1:0", "-e", `BASE_URL=${baseUrl}`, bundledFile], {
533
534
  cwd: targetConfig.productDir,
534
535
  env: buildExecutionEnv(targetConfig),
535
536
  stdio: "inherit",
@@ -567,7 +568,7 @@ async function runDalBatch(targetConfig, batch) {
567
568
 
568
569
  async function runDalTask(targetConfig, task, databaseUrl) {
569
570
  const absFile = path.join(targetConfig.productDir, task.file);
570
- const k6Binary = resolveDalBinary();
571
+ const k6Binary = resolveK6Binary();
571
572
  const bundledFile = await bundleK6File({
572
573
  productDir: targetConfig.productDir,
573
574
  serviceName: targetConfig.name,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/testkit",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "CLI for running manifest-defined local test suites across k6 and Playwright",
5
5
  "type": "module",
6
6
  "exports": {