@harperfast/integration-testing 0.1.0 → 0.2.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.
@@ -0,0 +1,156 @@
1
+ import { ChildProcess } from 'node:child_process';
2
+ import { type SuiteContext, type TestContext } from 'node:test';
3
+ /**
4
+ * Minimal context interface required by startHarper/teardownHarper.
5
+ *
6
+ * This is intentionally loose so it can be satisfied by:
7
+ * - node:test SuiteContext/TestContext objects (via ContextWithHarper)
8
+ * - Plain objects (e.g. Playwright worker fixtures: `createHarperContext()`)
9
+ */
10
+ export interface HarperTestContext {
11
+ /** Optional name used for log directory naming (e.g. suite name or Playwright worker index). */
12
+ name?: string;
13
+ /** Populated by startHarper(). May be pre-seeded with dataRootDir/hostname to reuse across restarts. */
14
+ harper?: Partial<HarperContext>;
15
+ }
16
+ /**
17
+ * A started context — harper is fully populated after startHarper() resolves.
18
+ */
19
+ export interface StartedHarperTestContext extends HarperTestContext {
20
+ harper: HarperContext;
21
+ }
22
+ /**
23
+ * Creates a plain object satisfying HarperTestContext, for use outside node:test
24
+ * (e.g. as a Playwright worker fixture).
25
+ *
26
+ * @param name Optional name for log directory naming (e.g. Playwright worker index).
27
+ */
28
+ export declare function createHarperContext(name?: string): HarperTestContext;
29
+ export declare const OPERATIONS_API_PORT = 9925;
30
+ export declare const DEFAULT_ADMIN_USERNAME = "admin";
31
+ export declare const DEFAULT_ADMIN_PASSWORD = "Abc1234!";
32
+ export declare const DEFAULT_STARTUP_TIMEOUT_MS: number;
33
+ /**
34
+ * Options for setting up a Harper instance.
35
+ */
36
+ export interface StartHarperOptions {
37
+ /**
38
+ * Timeout in milliseconds to wait for Harper to start.
39
+ * @default 30000
40
+ */
41
+ startupTimeoutMs?: number;
42
+ /**
43
+ * Additional configuration options to pass to the Harper CLI.
44
+ */
45
+ config?: any;
46
+ /**
47
+ * Environment variables to set when running Harper.
48
+ */
49
+ env?: any;
50
+ /**
51
+ * Explicit path to the Harper CLI script (dist/bin/harper.js).
52
+ * If not provided, resolution order is:
53
+ * 1. This option
54
+ * 2. HARPER_INTEGRATION_TEST_INSTALL_SCRIPT environment variable
55
+ * 3. Auto-resolved from 'harper' package in node_modules
56
+ */
57
+ harperBinPath?: string;
58
+ }
59
+ export interface HarperContext {
60
+ /** Absolute path to the Harper installation directory */
61
+ dataRootDir: string;
62
+ /** Admin credentials for the Harper instance */
63
+ admin: {
64
+ /** Admin username (default: 'admin') */
65
+ username: string;
66
+ /** Admin password (default: 'Abc1234!') */
67
+ password: string;
68
+ };
69
+ /** HTTP URL for the Harper instance (e.g., 'http://127.0.0.2:9926') */
70
+ httpURL: string;
71
+ /** Operations API URL (e.g., 'http://127.0.0.2:9925') */
72
+ operationsAPIURL: string;
73
+ /** Assigned loopback IP address (e.g., '127.0.0.2') */
74
+ hostname: string;
75
+ /** Child process for the Harper instance */
76
+ process: ChildProcess;
77
+ /** Absolute path to the log directory for this suite (only set when HARPER_INTEGRATION_TEST_LOG_DIR is configured) */
78
+ logDir?: string;
79
+ }
80
+ /**
81
+ * Test context interface with Harper instance details, for use with node:test.
82
+ *
83
+ * This interface is populated by `startHarper()` and contains
84
+ * all necessary information to interact with the test Harper instance.
85
+ *
86
+ * For use outside node:test (e.g. Playwright), use `createHarperContext()` to
87
+ * create a plain object satisfying `HarperTestContext` instead.
88
+ */
89
+ export interface ContextWithHarper extends SuiteContext, TestContext {
90
+ harper: HarperContext;
91
+ }
92
+ /**
93
+ * Sets up a Harper instance with a component pre-installed from a local directory.
94
+ *
95
+ * Copies `fixturePath` into `{dataRootDir}/components/{name}` before Harper starts,
96
+ * so the component is available on the first request without a post-startup deploy.
97
+ * Use this when tests need a known route available at startup (e.g. mTLS cert tests).
98
+ *
99
+ * @param ctx - The test context to populate with Harper instance details
100
+ * @param fixturePath - Absolute path to the component directory to pre-install
101
+ * @param options - Optional configuration for the setup process
102
+ */
103
+ export declare function setupHarperWithFixture(ctx: HarperTestContext, fixturePath: string, options?: StartHarperOptions): Promise<StartedHarperTestContext>;
104
+ /**
105
+ * Sets up and starts a Harper instance for testing.
106
+ *
107
+ * @param ctx - The test context to populate with Harper instance details
108
+ * @param options - Optional configuration for the setup process
109
+ * @returns The context with the `harper` property populated
110
+ *
111
+ * @example
112
+ * ```ts
113
+ * suite('My tests', (ctx: ContextWithHarper) => {
114
+ * before(async () => {
115
+ * await startHarper(ctx);
116
+ * });
117
+ *
118
+ * after(async () => {
119
+ * await teardownHarper(ctx);
120
+ * });
121
+ *
122
+ * test('can connect', async () => {
123
+ * const response = await fetch(ctx.harper.httpURL);
124
+ * // ...
125
+ * });
126
+ * });
127
+ * ```
128
+ */
129
+ export declare function startHarper(ctx: HarperTestContext, options?: StartHarperOptions): Promise<StartedHarperTestContext>;
130
+ /**
131
+ * Kill harper process (can be used for teardown, or killing it before a restart)
132
+ * @param ctx
133
+ */
134
+ export declare function killHarper(ctx: StartedHarperTestContext): Promise<void>;
135
+ /**
136
+ * Tears down a Harper instance and cleans up all resources.
137
+ *
138
+ * This function stops the Harper instance, releases the loopback address,
139
+ * and removes the installation directory.
140
+ * @param ctx - The test context with Harper instance details
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * suite('My tests', (ctx: ContextWithHarper) => {
145
+ * before(async () => {
146
+ * await startHarper(ctx);
147
+ * });
148
+ *
149
+ * after(async () => {
150
+ * await teardownHarper(ctx);
151
+ * });
152
+ * });
153
+ * ```
154
+ */
155
+ export declare function teardownHarper(ctx: StartedHarperTestContext): Promise<void>;
156
+ export declare function sendOperation(context: HarperContext, operation: any): Promise<any>;
@@ -0,0 +1,3 @@
1
+ export { startHarper, setupHarperWithFixture, killHarper, teardownHarper, sendOperation, createHarperContext, OPERATIONS_API_PORT, DEFAULT_ADMIN_USERNAME, DEFAULT_ADMIN_PASSWORD, DEFAULT_STARTUP_TIMEOUT_MS, type StartHarperOptions, type HarperContext, type HarperTestContext, type StartedHarperTestContext, type ContextWithHarper, } from './harperLifecycle.ts';
2
+ export { validateLoopbackAddressPool, getNextAvailableLoopbackAddress, releaseLoopbackAddress, releaseAllLoopbackAddressesForCurrentProcess, } from './loopbackAddressPool.ts';
3
+ export { targz } from './targz.ts';
@@ -0,0 +1,50 @@
1
+ /**
2
+ * This method attempts to validate all loopback addresses in the pool by trying to
3
+ * bind to each one. It returns an object containing arrays of successfully bound
4
+ * loopback addresses and those that failed along with their errors.
5
+ *
6
+ * It will check all loopback addresses from 127.0.0.1 to 127.0.0.32 (by default).
7
+ *
8
+ * Use the HARPER_INTEGRATION_TEST_LOOPBACK_POOL_COUNT environment variable to
9
+ * adjust the number of loopback addresses to validate (up to 255).
10
+ */
11
+ export declare function validateLoopbackAddressPool(): Promise<{
12
+ successful: string[];
13
+ failed: {
14
+ loopbackAddress: string;
15
+ error: Error;
16
+ }[];
17
+ }>;
18
+ /**
19
+ * Retrieves the next available loopback address from the pool using a file-based
20
+ * locking mechanism to safely allocate addresses across concurrent test processes.
21
+ *
22
+ * **How it works:**
23
+ * 1. Acquires a file-based lock to prevent race conditions with other processes
24
+ * 2. Reads the pool state (a JSON array of process IDs, with null for available slots)
25
+ * 3. Finds the first available (null) slot and assigns the current process PID to it
26
+ * 4. Writes the updated pool back to disk and releases the lock
27
+ * 5. Validates that the allocated address can actually be bound to
28
+ * 6. Returns the loopback address (e.g., "127.0.0.2")
29
+ *
30
+ * If no addresses are available, waits and retries until one becomes available.
31
+ *
32
+ * **Pool file location:** `${tmpdir()}/harper-integration-test-loopback-pool.json`
33
+ * **Lock file location:** `${tmpdir()}/harper-integration-test-loopback-pool.lock`
34
+ *
35
+ * @returns A promise that resolves with an allocated loopback address
36
+ * @throws {LoopbackAddressValidationError} If the allocated address cannot be bound to
37
+ */
38
+ export declare function getNextAvailableLoopbackAddress(): Promise<string>;
39
+ /**
40
+ * Releases a loopback address back to the pool, making it available for other processes.
41
+ *
42
+ * @param address The loopback address to release (e.g., "127.0.0.1")
43
+ * @throws InvalidLoopbackAddressError if the address format is invalid
44
+ */
45
+ export declare function releaseLoopbackAddress(address: string): Promise<void>;
46
+ /**
47
+ * Releases all loopback addresses assigned to the current process.
48
+ * Useful for cleanup during graceful shutdown.
49
+ */
50
+ export declare function releaseAllLoopbackAddressesForCurrentProcess(): Promise<void>;
package/dist/run.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Packs and compresses a directory into a base64-encoded tar.gz string.
3
+ *
4
+ * @param dirPath path to directory to pack and compress
5
+ */
6
+ export declare function targz(dirPath: string): Promise<string>;
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@harperfast/integration-testing",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "description": "Integration testing utilities for Harper-based projects. Provides Harper instance lifecycle management, loopback address pooling, and a test runner script.",
6
6
  "license": "Apache-2.0",
7
7
  "exports": {
8
- ".": "./src/index.ts",
9
- "./run": "./src/scripts/run.ts"
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ }
10
12
  },
11
13
  "bin": {
12
14
  "harper-integration-test-run": "dist/run.js",