@streetjs/storage 1.0.0 → 1.0.1
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/dist/drivers/local.d.ts +8 -0
- package/dist/drivers/local.d.ts.map +1 -1
- package/dist/drivers/local.js +18 -3
- package/dist/drivers/local.js.map +1 -1
- package/package.json +12 -6
- package/dist/tests/access.test.d.ts +0 -2
- package/dist/tests/access.test.d.ts.map +0 -1
- package/dist/tests/access.test.js +0 -270
- package/dist/tests/access.test.js.map +0 -1
- package/dist/tests/azure-driver.test.d.ts +0 -2
- package/dist/tests/azure-driver.test.d.ts.map +0 -1
- package/dist/tests/azure-driver.test.js +0 -183
- package/dist/tests/azure-driver.test.js.map +0 -1
- package/dist/tests/backblaze-driver.test.d.ts +0 -2
- package/dist/tests/backblaze-driver.test.d.ts.map +0 -1
- package/dist/tests/backblaze-driver.test.js +0 -185
- package/dist/tests/backblaze-driver.test.js.map +0 -1
- package/dist/tests/bridge-degradation.test.d.ts +0 -2
- package/dist/tests/bridge-degradation.test.d.ts.map +0 -1
- package/dist/tests/bridge-degradation.test.js +0 -138
- package/dist/tests/bridge-degradation.test.js.map +0 -1
- package/dist/tests/cli.test.d.ts +0 -2
- package/dist/tests/cli.test.d.ts.map +0 -1
- package/dist/tests/cli.test.js +0 -127
- package/dist/tests/cli.test.js.map +0 -1
- package/dist/tests/contract.d.ts +0 -131
- package/dist/tests/contract.d.ts.map +0 -1
- package/dist/tests/contract.js +0 -222
- package/dist/tests/contract.js.map +0 -1
- package/dist/tests/contract.test.d.ts +0 -2
- package/dist/tests/contract.test.d.ts.map +0 -1
- package/dist/tests/contract.test.js +0 -110
- package/dist/tests/contract.test.js.map +0 -1
- package/dist/tests/directory.test.d.ts +0 -2
- package/dist/tests/directory.test.d.ts.map +0 -1
- package/dist/tests/directory.test.js +0 -125
- package/dist/tests/directory.test.js.map +0 -1
- package/dist/tests/errors.test.d.ts +0 -2
- package/dist/tests/errors.test.d.ts.map +0 -1
- package/dist/tests/errors.test.js +0 -93
- package/dist/tests/errors.test.js.map +0 -1
- package/dist/tests/events-bridge.test.d.ts +0 -2
- package/dist/tests/events-bridge.test.d.ts.map +0 -1
- package/dist/tests/events-bridge.test.js +0 -228
- package/dist/tests/events-bridge.test.js.map +0 -1
- package/dist/tests/example-smoke.test.d.ts +0 -2
- package/dist/tests/example-smoke.test.d.ts.map +0 -1
- package/dist/tests/example-smoke.test.js +0 -34
- package/dist/tests/example-smoke.test.js.map +0 -1
- package/dist/tests/gcs-driver.test.d.ts +0 -2
- package/dist/tests/gcs-driver.test.d.ts.map +0 -1
- package/dist/tests/gcs-driver.test.js +0 -197
- package/dist/tests/gcs-driver.test.js.map +0 -1
- package/dist/tests/image.test.d.ts +0 -2
- package/dist/tests/image.test.d.ts.map +0 -1
- package/dist/tests/image.test.js +0 -102
- package/dist/tests/image.test.js.map +0 -1
- package/dist/tests/lifecycle.test.d.ts +0 -2
- package/dist/tests/lifecycle.test.d.ts.map +0 -1
- package/dist/tests/lifecycle.test.js +0 -171
- package/dist/tests/lifecycle.test.js.map +0 -1
- package/dist/tests/local-driver.test.d.ts +0 -2
- package/dist/tests/local-driver.test.d.ts.map +0 -1
- package/dist/tests/local-driver.test.js +0 -153
- package/dist/tests/local-driver.test.js.map +0 -1
- package/dist/tests/local-streaming.test.d.ts +0 -2
- package/dist/tests/local-streaming.test.d.ts.map +0 -1
- package/dist/tests/local-streaming.test.js +0 -121
- package/dist/tests/local-streaming.test.js.map +0 -1
- package/dist/tests/memory-driver.test.d.ts +0 -2
- package/dist/tests/memory-driver.test.d.ts.map +0 -1
- package/dist/tests/memory-driver.test.js +0 -180
- package/dist/tests/memory-driver.test.js.map +0 -1
- package/dist/tests/memory-streaming.test.d.ts +0 -2
- package/dist/tests/memory-streaming.test.d.ts.map +0 -1
- package/dist/tests/memory-streaming.test.js +0 -92
- package/dist/tests/memory-streaming.test.js.map +0 -1
- package/dist/tests/minio-driver.test.d.ts +0 -2
- package/dist/tests/minio-driver.test.d.ts.map +0 -1
- package/dist/tests/minio-driver.test.js +0 -146
- package/dist/tests/minio-driver.test.js.map +0 -1
- package/dist/tests/non-s3-integration.test.d.ts +0 -2
- package/dist/tests/non-s3-integration.test.d.ts.map +0 -1
- package/dist/tests/non-s3-integration.test.js +0 -201
- package/dist/tests/non-s3-integration.test.js.map +0 -1
- package/dist/tests/observability.registration.test.d.ts +0 -2
- package/dist/tests/observability.registration.test.d.ts.map +0 -1
- package/dist/tests/observability.registration.test.js +0 -103
- package/dist/tests/observability.registration.test.js.map +0 -1
- package/dist/tests/observability.test.d.ts +0 -2
- package/dist/tests/observability.test.d.ts.map +0 -1
- package/dist/tests/observability.test.js +0 -240
- package/dist/tests/observability.test.js.map +0 -1
- package/dist/tests/plugin.test.d.ts +0 -2
- package/dist/tests/plugin.test.d.ts.map +0 -1
- package/dist/tests/plugin.test.js +0 -112
- package/dist/tests/plugin.test.js.map +0 -1
- package/dist/tests/prop-concurrent.test.d.ts +0 -2
- package/dist/tests/prop-concurrent.test.d.ts.map +0 -1
- package/dist/tests/prop-concurrent.test.js +0 -59
- package/dist/tests/prop-concurrent.test.js.map +0 -1
- package/dist/tests/prop-copy.test.d.ts +0 -2
- package/dist/tests/prop-copy.test.d.ts.map +0 -1
- package/dist/tests/prop-copy.test.js +0 -63
- package/dist/tests/prop-copy.test.js.map +0 -1
- package/dist/tests/prop-delete.test.d.ts +0 -2
- package/dist/tests/prop-delete.test.d.ts.map +0 -1
- package/dist/tests/prop-delete.test.js +0 -35
- package/dist/tests/prop-delete.test.js.map +0 -1
- package/dist/tests/prop-directory.test.d.ts +0 -2
- package/dist/tests/prop-directory.test.d.ts.map +0 -1
- package/dist/tests/prop-directory.test.js +0 -118
- package/dist/tests/prop-directory.test.js.map +0 -1
- package/dist/tests/prop-driver-conformance.test.d.ts +0 -2
- package/dist/tests/prop-driver-conformance.test.d.ts.map +0 -1
- package/dist/tests/prop-driver-conformance.test.js +0 -110
- package/dist/tests/prop-driver-conformance.test.js.map +0 -1
- package/dist/tests/prop-driver-equivalence.test.d.ts +0 -2
- package/dist/tests/prop-driver-equivalence.test.d.ts.map +0 -1
- package/dist/tests/prop-driver-equivalence.test.js +0 -163
- package/dist/tests/prop-driver-equivalence.test.js.map +0 -1
- package/dist/tests/prop-lifecycle.test.d.ts +0 -2
- package/dist/tests/prop-lifecycle.test.d.ts.map +0 -1
- package/dist/tests/prop-lifecycle.test.js +0 -83
- package/dist/tests/prop-lifecycle.test.js.map +0 -1
- package/dist/tests/prop-list.test.d.ts +0 -2
- package/dist/tests/prop-list.test.d.ts.map +0 -1
- package/dist/tests/prop-list.test.js +0 -53
- package/dist/tests/prop-list.test.js.map +0 -1
- package/dist/tests/prop-metadata.test.d.ts +0 -2
- package/dist/tests/prop-metadata.test.d.ts.map +0 -1
- package/dist/tests/prop-metadata.test.js +0 -87
- package/dist/tests/prop-metadata.test.js.map +0 -1
- package/dist/tests/prop-move.test.d.ts +0 -2
- package/dist/tests/prop-move.test.d.ts.map +0 -1
- package/dist/tests/prop-move.test.js +0 -67
- package/dist/tests/prop-move.test.js.map +0 -1
- package/dist/tests/prop-multipart-abort.test.d.ts +0 -2
- package/dist/tests/prop-multipart-abort.test.d.ts.map +0 -1
- package/dist/tests/prop-multipart-abort.test.js +0 -48
- package/dist/tests/prop-multipart-abort.test.js.map +0 -1
- package/dist/tests/prop-multipart.test.d.ts +0 -2
- package/dist/tests/prop-multipart.test.d.ts.map +0 -1
- package/dist/tests/prop-multipart.test.js +0 -65
- package/dist/tests/prop-multipart.test.js.map +0 -1
- package/dist/tests/prop-resumable.test.d.ts +0 -2
- package/dist/tests/prop-resumable.test.d.ts.map +0 -1
- package/dist/tests/prop-resumable.test.js +0 -78
- package/dist/tests/prop-resumable.test.js.map +0 -1
- package/dist/tests/prop-search.test.d.ts +0 -2
- package/dist/tests/prop-search.test.d.ts.map +0 -1
- package/dist/tests/prop-search.test.js +0 -120
- package/dist/tests/prop-search.test.js.map +0 -1
- package/dist/tests/prop-signed-url.test.d.ts +0 -2
- package/dist/tests/prop-signed-url.test.d.ts.map +0 -1
- package/dist/tests/prop-signed-url.test.js +0 -74
- package/dist/tests/prop-signed-url.test.js.map +0 -1
- package/dist/tests/prop-streaming.test.d.ts +0 -2
- package/dist/tests/prop-streaming.test.d.ts.map +0 -1
- package/dist/tests/prop-streaming.test.js +0 -34
- package/dist/tests/prop-streaming.test.js.map +0 -1
- package/dist/tests/prop-upload-download.test.d.ts +0 -2
- package/dist/tests/prop-upload-download.test.d.ts.map +0 -1
- package/dist/tests/prop-upload-download.test.js +0 -30
- package/dist/tests/prop-upload-download.test.js.map +0 -1
- package/dist/tests/prop-validation.test.d.ts +0 -2
- package/dist/tests/prop-validation.test.d.ts.map +0 -1
- package/dist/tests/prop-validation.test.js +0 -50
- package/dist/tests/prop-validation.test.js.map +0 -1
- package/dist/tests/prop-versioning.test.d.ts +0 -2
- package/dist/tests/prop-versioning.test.d.ts.map +0 -1
- package/dist/tests/prop-versioning.test.js +0 -74
- package/dist/tests/prop-versioning.test.js.map +0 -1
- package/dist/tests/queue-bridge.test.d.ts +0 -2
- package/dist/tests/queue-bridge.test.d.ts.map +0 -1
- package/dist/tests/queue-bridge.test.js +0 -111
- package/dist/tests/queue-bridge.test.js.map +0 -1
- package/dist/tests/r2-driver.test.d.ts +0 -2
- package/dist/tests/r2-driver.test.d.ts.map +0 -1
- package/dist/tests/r2-driver.test.js +0 -143
- package/dist/tests/r2-driver.test.js.map +0 -1
- package/dist/tests/realtime-bridge.test.d.ts +0 -2
- package/dist/tests/realtime-bridge.test.d.ts.map +0 -1
- package/dist/tests/realtime-bridge.test.js +0 -106
- package/dist/tests/realtime-bridge.test.js.map +0 -1
- package/dist/tests/resumable.test.d.ts +0 -2
- package/dist/tests/resumable.test.d.ts.map +0 -1
- package/dist/tests/resumable.test.js +0 -104
- package/dist/tests/resumable.test.js.map +0 -1
- package/dist/tests/s3-base.test.d.ts +0 -2
- package/dist/tests/s3-base.test.d.ts.map +0 -1
- package/dist/tests/s3-base.test.js +0 -289
- package/dist/tests/s3-base.test.js.map +0 -1
- package/dist/tests/s3-integration.test.d.ts +0 -2
- package/dist/tests/s3-integration.test.d.ts.map +0 -1
- package/dist/tests/s3-integration.test.js +0 -270
- package/dist/tests/s3-integration.test.js.map +0 -1
- package/dist/tests/s3.test.d.ts +0 -2
- package/dist/tests/s3.test.d.ts.map +0 -1
- package/dist/tests/s3.test.js +0 -203
- package/dist/tests/s3.test.js.map +0 -1
- package/dist/tests/scaffold.test.d.ts +0 -2
- package/dist/tests/scaffold.test.d.ts.map +0 -1
- package/dist/tests/scaffold.test.js +0 -13
- package/dist/tests/scaffold.test.js.map +0 -1
- package/dist/tests/search.test.d.ts +0 -2
- package/dist/tests/search.test.d.ts.map +0 -1
- package/dist/tests/search.test.js +0 -106
- package/dist/tests/search.test.js.map +0 -1
- package/dist/tests/supabase-driver.test.d.ts +0 -2
- package/dist/tests/supabase-driver.test.d.ts.map +0 -1
- package/dist/tests/supabase-driver.test.js +0 -196
- package/dist/tests/supabase-driver.test.js.map +0 -1
- package/dist/tests/testing-utilities.test.d.ts +0 -2
- package/dist/tests/testing-utilities.test.d.ts.map +0 -1
- package/dist/tests/testing-utilities.test.js +0 -138
- package/dist/tests/testing-utilities.test.js.map +0 -1
- package/dist/tests/validation.test.d.ts +0 -2
- package/dist/tests/validation.test.d.ts.map +0 -1
- package/dist/tests/validation.test.js +0 -135
- package/dist/tests/validation.test.js.map +0 -1
- package/dist/tests/versioning.test.d.ts +0 -2
- package/dist/tests/versioning.test.d.ts.map +0 -1
- package/dist/tests/versioning.test.js +0 -128
- package/dist/tests/versioning.test.js.map +0 -1
package/dist/tests/cli.test.js
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
// cli.test.js — unit tests for the @streetjs/storage CLI generators and the
|
|
2
|
-
// storage:verify command (Requirements 21.2, 21.4).
|
|
3
|
-
//
|
|
4
|
-
// Covers three concerns:
|
|
5
|
-
// (1) Generator name validation — isValidGeneratorName / generateStorage
|
|
6
|
-
// reject invalid names and accept valid PascalCase identifiers.
|
|
7
|
-
// (2) Compile-clean scaffold output — the generated `contents` imports only
|
|
8
|
-
// public @streetjs/storage symbols (createStorage + StorageConfig) and
|
|
9
|
-
// wires them into a typed factory.
|
|
10
|
-
// (3) storage:verify pass/fail reporting — StorageCommands.storageVerify
|
|
11
|
-
// reports a pass for the built-in memory provider (process.exitCode is
|
|
12
|
-
// not set to 1) and a failure for an unknown/misconfigured provider
|
|
13
|
-
// (process.exitCode === 1).
|
|
14
|
-
//
|
|
15
|
-
// Uses the Node.js built-in test runner (node:test); executed via
|
|
16
|
-
// `node --test dist/tests/*.test.js`.
|
|
17
|
-
import test from "node:test";
|
|
18
|
-
import assert from "node:assert/strict";
|
|
19
|
-
import { generateStorage, isValidGeneratorName, isValidProvider, DEFAULT_STORAGE_DIR, } from "../cli/generators.js";
|
|
20
|
-
import { StorageCommands } from "../cli/commands.js";
|
|
21
|
-
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
22
|
-
/** Build a ParsedArgs object matching the shape streetjs' parseArgv produces. */
|
|
23
|
-
function parsedArgs(options = {}) {
|
|
24
|
-
const { command = null, positional = [], flags = {} } = options;
|
|
25
|
-
return { command, positional, flags };
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Run `fn` while capturing everything written to console.log/console.error and
|
|
29
|
-
* with process.exitCode reset, restoring both afterwards. Returns the captured
|
|
30
|
-
* output plus the exitCode observed after `fn` completes.
|
|
31
|
-
*/
|
|
32
|
-
async function captureRun(fn) {
|
|
33
|
-
const originalLog = console.log;
|
|
34
|
-
const originalError = console.error;
|
|
35
|
-
const originalExitCode = process.exitCode;
|
|
36
|
-
const logs = [];
|
|
37
|
-
const errors = [];
|
|
38
|
-
console.log = (...args) => logs.push(args.join(" "));
|
|
39
|
-
console.error = (...args) => errors.push(args.join(" "));
|
|
40
|
-
process.exitCode = undefined;
|
|
41
|
-
try {
|
|
42
|
-
await fn();
|
|
43
|
-
return { logs, errors, exitCode: process.exitCode };
|
|
44
|
-
}
|
|
45
|
-
finally {
|
|
46
|
-
console.log = originalLog;
|
|
47
|
-
console.error = originalError;
|
|
48
|
-
process.exitCode = originalExitCode;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
// ── (1) Generator name validation ──────────────────────────────────────────────
|
|
52
|
-
test("isValidGeneratorName rejects invalid names and accepts PascalCase", () => {
|
|
53
|
-
// Invalid: empty, non-identifier, leading digit, hyphen/space/dot.
|
|
54
|
-
assert.equal(isValidGeneratorName(""), false);
|
|
55
|
-
assert.equal(isValidGeneratorName("1Uploads"), false);
|
|
56
|
-
assert.equal(isValidGeneratorName("my-storage"), false);
|
|
57
|
-
assert.equal(isValidGeneratorName("my storage"), false);
|
|
58
|
-
assert.equal(isValidGeneratorName("Up.loads"), false);
|
|
59
|
-
assert.equal(isValidGeneratorName("$Uploads"), false);
|
|
60
|
-
// Valid: identifier-safe tokens including PascalCase.
|
|
61
|
-
assert.equal(isValidGeneratorName("Uploads"), true);
|
|
62
|
-
assert.equal(isValidGeneratorName("UserAvatars"), true);
|
|
63
|
-
assert.equal(isValidGeneratorName("A1"), true);
|
|
64
|
-
assert.equal(isValidGeneratorName("uploads"), true);
|
|
65
|
-
});
|
|
66
|
-
test("generateStorage throws for invalid names before producing output", () => {
|
|
67
|
-
assert.throws(() => generateStorage(""), /Invalid generator name/);
|
|
68
|
-
assert.throws(() => generateStorage("bad-name"), /Invalid generator name/);
|
|
69
|
-
assert.throws(() => generateStorage("9lives"), /Invalid generator name/);
|
|
70
|
-
});
|
|
71
|
-
test("generateStorage throws for a non-built-in provider", () => {
|
|
72
|
-
assert.throws(() => generateStorage("Uploads", DEFAULT_STORAGE_DIR, "s3"), /Invalid storage provider/);
|
|
73
|
-
assert.equal(isValidProvider("memory"), true);
|
|
74
|
-
assert.equal(isValidProvider("local"), true);
|
|
75
|
-
assert.equal(isValidProvider("s3"), false);
|
|
76
|
-
});
|
|
77
|
-
// ── (2) Compile-clean scaffold output ──────────────────────────────────────────
|
|
78
|
-
test("generateStorage emits a scaffold importing only public @streetjs/storage symbols", () => {
|
|
79
|
-
const result = generateStorage("Uploads");
|
|
80
|
-
// Path is derived from the PascalCase class name under the default dir.
|
|
81
|
-
assert.ok(result.path.endsWith("UploadsStorage.ts"), `unexpected path: ${result.path}`);
|
|
82
|
-
const contents = result.contents;
|
|
83
|
-
// Imports only the public package entry point (no deep/internal imports).
|
|
84
|
-
assert.match(contents, /import \{ createStorage \} from "@streetjs\/storage";/);
|
|
85
|
-
assert.match(contents, /import type \{ Storage, StorageConfig \} from "@streetjs\/storage";/);
|
|
86
|
-
assert.ok(!/from "\.\//.test(contents) && !/from "\.\.\//.test(contents), "scaffold must not import from relative/internal paths");
|
|
87
|
-
// Wires a typed StorageConfig and a factory that calls createStorage.
|
|
88
|
-
assert.match(contents, /: StorageConfig = \{/);
|
|
89
|
-
assert.match(contents, /provider: "memory"/);
|
|
90
|
-
assert.match(contents, /export function createUploadsStorage\(\): Storage \{/);
|
|
91
|
-
assert.match(contents, /return createStorage\(/);
|
|
92
|
-
});
|
|
93
|
-
test("generateStorage local provider scaffold supplies a root and stays on the public surface", () => {
|
|
94
|
-
const result = generateStorage("Assets", DEFAULT_STORAGE_DIR, "local");
|
|
95
|
-
const contents = result.contents;
|
|
96
|
-
assert.match(contents, /provider: "local"/);
|
|
97
|
-
assert.match(contents, /root: "\.\/var\/assets"/);
|
|
98
|
-
assert.match(contents, /import \{ createStorage \} from "@streetjs\/storage";/);
|
|
99
|
-
});
|
|
100
|
-
// ── (3) storage:verify pass/fail reporting ──────────────────────────────────────
|
|
101
|
-
test("storageVerify reports a pass for the built-in memory provider", async () => {
|
|
102
|
-
const commands = new StorageCommands();
|
|
103
|
-
const args = parsedArgs({ command: "storage:verify", flags: { provider: "memory" } });
|
|
104
|
-
const { logs, exitCode } = await captureRun(() => commands.storageVerify(args));
|
|
105
|
-
// A passing run must NOT set a failure exit code.
|
|
106
|
-
assert.notEqual(exitCode, 1);
|
|
107
|
-
const output = logs.join("\n");
|
|
108
|
-
assert.match(output, /Contract conformance for driver "memory"/);
|
|
109
|
-
assert.match(output, /— PASS\./);
|
|
110
|
-
// No FAIL check lines expected.
|
|
111
|
-
assert.ok(!/\[FAIL\]/.test(output), "memory provider should have no failing checks");
|
|
112
|
-
});
|
|
113
|
-
test("storageVerify reports failure for an unknown provider (exitCode 1)", async () => {
|
|
114
|
-
const commands = new StorageCommands();
|
|
115
|
-
const args = parsedArgs({ command: "storage:verify", flags: { provider: "does-not-exist" } });
|
|
116
|
-
const { errors, exitCode } = await captureRun(() => commands.storageVerify(args));
|
|
117
|
-
assert.equal(exitCode, 1);
|
|
118
|
-
assert.match(errors.join("\n"), /Unknown storage provider "does-not-exist"/);
|
|
119
|
-
});
|
|
120
|
-
test("storageVerify reports failure for a misconfigured local provider (missing root)", async () => {
|
|
121
|
-
const commands = new StorageCommands();
|
|
122
|
-
const args = parsedArgs({ command: "storage:verify", flags: { provider: "local" } });
|
|
123
|
-
const { errors, exitCode } = await captureRun(() => commands.storageVerify(args));
|
|
124
|
-
assert.equal(exitCode, 1);
|
|
125
|
-
assert.match(errors.join("\n"), /"local" storage provider requires a "root" directory/);
|
|
126
|
-
});
|
|
127
|
-
//# sourceMappingURL=cli.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../../src/tests/cli.test.ts"],"names":[],"mappings":"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"}
|
package/dist/tests/contract.d.ts
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @streetjs/storage — the shared, parameterized contract-conformance suite.
|
|
3
|
-
*
|
|
4
|
-
* Requirement 2 states that every provider implements one `StorageDriver`
|
|
5
|
-
* contract with identical observable behavior: object existence, content bytes,
|
|
6
|
-
* and returned metadata must be equivalent across drivers (Requirement 2.1,
|
|
7
|
-
* 2.3), and a missing key must be reported the same way everywhere
|
|
8
|
-
* (Requirement 2.4). This module encodes the observable core of that contract
|
|
9
|
-
* as a **reusable, driver-agnostic conformance suite** so the exact same checks
|
|
10
|
-
* can be run against any {@link StorageDriver} — the zero-dependency Memory and
|
|
11
|
-
* Local drivers, the in-process testing doubles, and every cloud driver.
|
|
12
|
-
*
|
|
13
|
-
* The suite is designed to be consumed in two ways from one definition:
|
|
14
|
-
*
|
|
15
|
-
* - **Programmatically** (returns pass/fail results). {@link runStorageDriverContract}
|
|
16
|
-
* runs every check against a freshly constructed driver and returns a
|
|
17
|
-
* {@link ContractReport} describing which checks passed. This is what the
|
|
18
|
-
* `storage:verify` CLI command (task 24.2) uses to report whether the
|
|
19
|
-
* configured driver satisfies the contract, and what Property 19 (task 27.3)
|
|
20
|
-
* uses to assert that every driver conforms.
|
|
21
|
-
* - **As node:test tests**. {@link registerStorageDriverContractTests} turns each
|
|
22
|
-
* check into a `node:test` case using a caller-supplied `test` function, so a
|
|
23
|
-
* thin `*.test.js` can run the suite against Memory + Local without this
|
|
24
|
-
* support module importing `node:test` itself (keeping it importable from the
|
|
25
|
-
* CLI, which has no test runner in scope).
|
|
26
|
-
*
|
|
27
|
-
* Each check receives its **own freshly constructed driver** (from the supplied
|
|
28
|
-
* factory) so checks are fully isolated and order-independent. Assertions use
|
|
29
|
-
* `node:assert/strict`; a check throws on failure and returns normally on
|
|
30
|
-
* success. The checked behaviors are:
|
|
31
|
-
*
|
|
32
|
-
* 1. **existence** — `put` then `exists(key)` is `true`; `exists(other)` is `false`.
|
|
33
|
-
* 2. **byte round-trip** — `put(key, bytes)` then `get(key)` yields
|
|
34
|
-
* `{ found: true }` with content bytes exactly equal to the input.
|
|
35
|
-
* 3. **not-found (get)** — `get(missing)` yields `{ found: false }`.
|
|
36
|
-
* 4. **not-found (stat)** — `stat(missing)` yields `null`.
|
|
37
|
-
* 5. **metadata shape** — `put` returns the complete typed
|
|
38
|
-
* {@link StorageObjectMetadata} field set with correctly typed values.
|
|
39
|
-
*
|
|
40
|
-
* This module is a support module under `src/tests/` (not itself a `*.test.js`
|
|
41
|
-
* picked up by the default test glob); it is imported by tests and by the CLI.
|
|
42
|
-
*
|
|
43
|
-
* _Requirements: 2.1, 2.3, 2.4_
|
|
44
|
-
*/
|
|
45
|
-
import type { StorageDriver } from "../driver.js";
|
|
46
|
-
/**
|
|
47
|
-
* A single named conformance check. {@link run} performs the check against the
|
|
48
|
-
* supplied driver and throws (via `node:assert`) when the driver violates the
|
|
49
|
-
* contract; it returns normally when the check passes.
|
|
50
|
-
*/
|
|
51
|
-
export interface ContractCheck {
|
|
52
|
-
/** Stable, human-readable check name (e.g. "byte round-trip"). */
|
|
53
|
-
readonly name: string;
|
|
54
|
-
/** The acceptance-criteria reference this check exercises. */
|
|
55
|
-
readonly requirement: string;
|
|
56
|
-
/** Run the check against `driver`; throws on violation. */
|
|
57
|
-
run(driver: StorageDriver): Promise<void>;
|
|
58
|
-
}
|
|
59
|
-
/** The outcome of running a single {@link ContractCheck}. */
|
|
60
|
-
export interface ContractCheckResult {
|
|
61
|
-
readonly name: string;
|
|
62
|
-
readonly requirement: string;
|
|
63
|
-
readonly passed: boolean;
|
|
64
|
-
/** The failure message when {@link passed} is `false`. */
|
|
65
|
-
readonly error?: string;
|
|
66
|
-
}
|
|
67
|
-
/** The aggregate outcome of running the whole suite against one driver. */
|
|
68
|
-
export interface ContractReport {
|
|
69
|
-
/** The `name` of the driver under test (e.g. "memory", "local", "s3"). */
|
|
70
|
-
readonly driver: string;
|
|
71
|
-
/** `true` when every check passed. */
|
|
72
|
-
readonly passed: boolean;
|
|
73
|
-
/** Per-check results, in suite order. */
|
|
74
|
-
readonly results: readonly ContractCheckResult[];
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Produces a fresh {@link StorageDriver} to test. A new instance is requested
|
|
78
|
-
* for each check so the checks are isolated from one another; the factory may
|
|
79
|
-
* be async (e.g. to allocate a temp directory for the Local driver).
|
|
80
|
-
*/
|
|
81
|
-
export type StorageDriverFactory = () => StorageDriver | Promise<StorageDriver>;
|
|
82
|
-
/**
|
|
83
|
-
* A minimal `node:test`-style runner: a function taking a test name and an async
|
|
84
|
-
* body. Callers pass `test` from `node:test`; typing it structurally keeps this
|
|
85
|
-
* module free of a hard `node:test` import so it stays importable from the CLI.
|
|
86
|
-
*/
|
|
87
|
-
export type TestRunner = (name: string, fn: () => void | Promise<void>) => unknown;
|
|
88
|
-
/**
|
|
89
|
-
* The ordered set of observable-behavior checks that make up the driver
|
|
90
|
-
* contract-conformance suite. Exported so consumers can inspect, subset, or
|
|
91
|
-
* extend the list; most callers use {@link runStorageDriverContract} or
|
|
92
|
-
* {@link registerStorageDriverContractTests} instead.
|
|
93
|
-
*/
|
|
94
|
-
export declare const storageDriverContractChecks: readonly ContractCheck[];
|
|
95
|
-
/** Options for {@link runStorageDriverContract}. */
|
|
96
|
-
export interface RunContractOptions {
|
|
97
|
-
/** Override the checks to run. Defaults to {@link storageDriverContractChecks}. */
|
|
98
|
-
readonly checks?: readonly ContractCheck[];
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Run the contract-conformance suite against a driver and return a pass/fail
|
|
102
|
-
* {@link ContractReport}. Each check is executed against a freshly constructed
|
|
103
|
-
* driver from `makeDriver` so the checks never interfere with one another.
|
|
104
|
-
*
|
|
105
|
-
* This never throws for a contract violation — a failing check is captured as a
|
|
106
|
-
* `passed: false` entry with its error message — so a consumer such as the
|
|
107
|
-
* `storage:verify` CLI (task 24.2) can render every result. Property 19
|
|
108
|
-
* (task 27.3) uses the returned {@link ContractReport.passed} to assert
|
|
109
|
-
* conformance across drivers.
|
|
110
|
-
*
|
|
111
|
-
* @param makeDriver Factory producing a fresh driver for each check.
|
|
112
|
-
* @param options Optional override of the checks to run.
|
|
113
|
-
*/
|
|
114
|
-
export declare function runStorageDriverContract(makeDriver: StorageDriverFactory, options?: RunContractOptions): Promise<ContractReport>;
|
|
115
|
-
/**
|
|
116
|
-
* Register each contract check as an individual `node:test` case using the
|
|
117
|
-
* supplied `test` runner. A thin `*.test.js` passes `test` from `node:test` and
|
|
118
|
-
* a driver factory; each check runs against a fresh driver and fails the test if
|
|
119
|
-
* the driver violates the contract.
|
|
120
|
-
*
|
|
121
|
-
* Taking the runner as a parameter keeps this module free of a hard `node:test`
|
|
122
|
-
* import, so it remains importable from non-test contexts (e.g. the CLI's
|
|
123
|
-
* `storage:verify`).
|
|
124
|
-
*
|
|
125
|
-
* @param label Prefix for each generated test name (e.g. the driver label).
|
|
126
|
-
* @param makeDriver Factory producing a fresh driver for each check.
|
|
127
|
-
* @param runner The `test` function from `node:test` (or a compatible runner).
|
|
128
|
-
* @param checks Optional override of the checks to run.
|
|
129
|
-
*/
|
|
130
|
-
export declare function registerStorageDriverContractTests(label: string, makeDriver: StorageDriverFactory, runner: TestRunner, checks?: readonly ContractCheck[]): void;
|
|
131
|
-
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/tests/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAMlD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2DAA2D;IAC3D,GAAG,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sCAAsC;IACtC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,yCAAyC;IACzC,QAAQ,CAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;CAClD;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AAEhF;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC;AAmEnF;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,EAAE,SAAS,aAAa,EAuE/D,CAAC;AAIF,oDAAoD;AACpD,MAAM,WAAW,kBAAkB;IACjC,mFAAmF;IACnF,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CAC5C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,oBAAoB,EAChC,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,cAAc,CAAC,CA0BzB;AAID;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,UAAU,EAClB,MAAM,GAAE,SAAS,aAAa,EAAgC,GAC7D,IAAI,CAON"}
|
package/dist/tests/contract.js
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @streetjs/storage — the shared, parameterized contract-conformance suite.
|
|
3
|
-
*
|
|
4
|
-
* Requirement 2 states that every provider implements one `StorageDriver`
|
|
5
|
-
* contract with identical observable behavior: object existence, content bytes,
|
|
6
|
-
* and returned metadata must be equivalent across drivers (Requirement 2.1,
|
|
7
|
-
* 2.3), and a missing key must be reported the same way everywhere
|
|
8
|
-
* (Requirement 2.4). This module encodes the observable core of that contract
|
|
9
|
-
* as a **reusable, driver-agnostic conformance suite** so the exact same checks
|
|
10
|
-
* can be run against any {@link StorageDriver} — the zero-dependency Memory and
|
|
11
|
-
* Local drivers, the in-process testing doubles, and every cloud driver.
|
|
12
|
-
*
|
|
13
|
-
* The suite is designed to be consumed in two ways from one definition:
|
|
14
|
-
*
|
|
15
|
-
* - **Programmatically** (returns pass/fail results). {@link runStorageDriverContract}
|
|
16
|
-
* runs every check against a freshly constructed driver and returns a
|
|
17
|
-
* {@link ContractReport} describing which checks passed. This is what the
|
|
18
|
-
* `storage:verify` CLI command (task 24.2) uses to report whether the
|
|
19
|
-
* configured driver satisfies the contract, and what Property 19 (task 27.3)
|
|
20
|
-
* uses to assert that every driver conforms.
|
|
21
|
-
* - **As node:test tests**. {@link registerStorageDriverContractTests} turns each
|
|
22
|
-
* check into a `node:test` case using a caller-supplied `test` function, so a
|
|
23
|
-
* thin `*.test.js` can run the suite against Memory + Local without this
|
|
24
|
-
* support module importing `node:test` itself (keeping it importable from the
|
|
25
|
-
* CLI, which has no test runner in scope).
|
|
26
|
-
*
|
|
27
|
-
* Each check receives its **own freshly constructed driver** (from the supplied
|
|
28
|
-
* factory) so checks are fully isolated and order-independent. Assertions use
|
|
29
|
-
* `node:assert/strict`; a check throws on failure and returns normally on
|
|
30
|
-
* success. The checked behaviors are:
|
|
31
|
-
*
|
|
32
|
-
* 1. **existence** — `put` then `exists(key)` is `true`; `exists(other)` is `false`.
|
|
33
|
-
* 2. **byte round-trip** — `put(key, bytes)` then `get(key)` yields
|
|
34
|
-
* `{ found: true }` with content bytes exactly equal to the input.
|
|
35
|
-
* 3. **not-found (get)** — `get(missing)` yields `{ found: false }`.
|
|
36
|
-
* 4. **not-found (stat)** — `stat(missing)` yields `null`.
|
|
37
|
-
* 5. **metadata shape** — `put` returns the complete typed
|
|
38
|
-
* {@link StorageObjectMetadata} field set with correctly typed values.
|
|
39
|
-
*
|
|
40
|
-
* This module is a support module under `src/tests/` (not itself a `*.test.js`
|
|
41
|
-
* picked up by the default test glob); it is imported by tests and by the CLI.
|
|
42
|
-
*
|
|
43
|
-
* _Requirements: 2.1, 2.3, 2.4_
|
|
44
|
-
*/
|
|
45
|
-
import assert from "node:assert/strict";
|
|
46
|
-
import { STORAGE_METADATA_FIELDS } from "../metadata.js";
|
|
47
|
-
// ── Test fixtures ─────────────────────────────────────────────────────────────
|
|
48
|
-
/** Encode a UTF-8 string into a Uint8Array for storage. */
|
|
49
|
-
function bytesOf(str) {
|
|
50
|
-
return new TextEncoder().encode(str);
|
|
51
|
-
}
|
|
52
|
-
/** The full set of access levels, used to validate the `accessLevel` field. */
|
|
53
|
-
const ACCESS_LEVELS = [
|
|
54
|
-
"public",
|
|
55
|
-
"private",
|
|
56
|
-
"signed",
|
|
57
|
-
"authenticated",
|
|
58
|
-
"role-based",
|
|
59
|
-
"tenant-aware",
|
|
60
|
-
];
|
|
61
|
-
/**
|
|
62
|
-
* Assert that `metadata` carries the complete typed {@link StorageObjectMetadata}
|
|
63
|
-
* field set with correctly typed values. Uses {@link STORAGE_METADATA_FIELDS} as
|
|
64
|
-
* the single source of truth for the required field names so this check tracks
|
|
65
|
-
* the canonical shape automatically (Requirement 2.1, 10.1).
|
|
66
|
-
*/
|
|
67
|
-
function assertMetadataShape(metadata, expected) {
|
|
68
|
-
assert.ok(metadata !== null && typeof metadata === "object", "put must return a metadata object");
|
|
69
|
-
// Every canonical field must be present as an own key.
|
|
70
|
-
for (const field of STORAGE_METADATA_FIELDS) {
|
|
71
|
-
assert.ok(field in metadata, `metadata is missing required field "${field}"`);
|
|
72
|
-
}
|
|
73
|
-
// Identity / value fields must be correctly typed.
|
|
74
|
-
assert.equal(metadata.key, expected.key, "metadata.key must equal the stored key");
|
|
75
|
-
assert.equal(metadata.size, expected.size, "metadata.size must equal the byte length");
|
|
76
|
-
assert.equal(typeof metadata.contentType, "string", "metadata.contentType must be a string");
|
|
77
|
-
assert.equal(typeof metadata.etag, "string", "metadata.etag must be a string");
|
|
78
|
-
assert.equal(typeof metadata.checksum, "string", "metadata.checksum must be a string");
|
|
79
|
-
assert.equal(typeof metadata.createdAt, "number", "metadata.createdAt must be a number");
|
|
80
|
-
assert.equal(typeof metadata.updatedAt, "number", "metadata.updatedAt must be a number");
|
|
81
|
-
assert.ok(metadata.custom !== null && typeof metadata.custom === "object", "metadata.custom must be an object");
|
|
82
|
-
assert.ok(ACCESS_LEVELS.includes(metadata.accessLevel), `metadata.accessLevel must be a valid AccessLevel (got "${metadata.accessLevel}")`);
|
|
83
|
-
// owner/tenant are optional: absent (undefined) or a string.
|
|
84
|
-
if (metadata.owner !== undefined) {
|
|
85
|
-
assert.equal(typeof metadata.owner, "string", "metadata.owner must be a string when present");
|
|
86
|
-
}
|
|
87
|
-
if (metadata.tenant !== undefined) {
|
|
88
|
-
assert.equal(typeof metadata.tenant, "string", "metadata.tenant must be a string when present");
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
// ── The checks ────────────────────────────────────────────────────────────────
|
|
92
|
-
/**
|
|
93
|
-
* The ordered set of observable-behavior checks that make up the driver
|
|
94
|
-
* contract-conformance suite. Exported so consumers can inspect, subset, or
|
|
95
|
-
* extend the list; most callers use {@link runStorageDriverContract} or
|
|
96
|
-
* {@link registerStorageDriverContractTests} instead.
|
|
97
|
-
*/
|
|
98
|
-
export const storageDriverContractChecks = [
|
|
99
|
-
{
|
|
100
|
-
name: "existence: put then exists reports presence and absence",
|
|
101
|
-
requirement: "2.1",
|
|
102
|
-
async run(driver) {
|
|
103
|
-
const key = "contract/existence.txt";
|
|
104
|
-
assert.equal(await driver.exists(key), false, "exists must be false before the object is stored");
|
|
105
|
-
await driver.put(key, bytesOf("present"), {});
|
|
106
|
-
assert.equal(await driver.exists(key), true, "exists must be true after put");
|
|
107
|
-
assert.equal(await driver.exists("contract/never-written.txt"), false, "exists must be false for an unrelated key");
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
name: "byte round-trip: get returns the stored bytes unchanged",
|
|
112
|
-
requirement: "2.1",
|
|
113
|
-
async run(driver) {
|
|
114
|
-
const key = "contract/round-trip.bin";
|
|
115
|
-
// Include boundary byte values so a lossy round-trip is caught.
|
|
116
|
-
const content = new Uint8Array([0, 1, 127, 128, 254, 255, 65, 66, 67]);
|
|
117
|
-
await driver.put(key, content, {});
|
|
118
|
-
const result = await driver.get(key);
|
|
119
|
-
assert.equal(result.found, true, "get must report found:true for a stored key");
|
|
120
|
-
assert.ok(result.found === true, "narrowing: result must be the found variant");
|
|
121
|
-
assert.deepEqual(result.bytes, content, "get must return the exact stored bytes");
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
name: "not-found (get): missing key reports found:false",
|
|
126
|
-
requirement: "2.4",
|
|
127
|
-
async run(driver) {
|
|
128
|
-
const result = await driver.get("contract/absent-get.txt");
|
|
129
|
-
assert.equal(result.found, false, "get on a missing key must report found:false");
|
|
130
|
-
assert.ok(result.found === false, "the not-found result must be the { found: false } variant");
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
name: "not-found (stat): missing key reports null",
|
|
135
|
-
requirement: "2.4",
|
|
136
|
-
async run(driver) {
|
|
137
|
-
const meta = await driver.stat("contract/absent-stat.txt");
|
|
138
|
-
assert.equal(meta, null, "stat on a missing key must return null");
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
name: "metadata shape: put returns the complete typed field set",
|
|
143
|
-
requirement: "2.1",
|
|
144
|
-
async run(driver) {
|
|
145
|
-
const key = "contract/metadata-shape.txt";
|
|
146
|
-
const content = bytesOf("shape check");
|
|
147
|
-
const metadata = await driver.put(key, content, {
|
|
148
|
-
contentType: "text/plain",
|
|
149
|
-
owner: "user-1",
|
|
150
|
-
tenant: "tenant-a",
|
|
151
|
-
accessLevel: "public",
|
|
152
|
-
custom: { label: "invoice" },
|
|
153
|
-
});
|
|
154
|
-
assertMetadataShape(metadata, { key, size: content.byteLength });
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
];
|
|
158
|
-
/**
|
|
159
|
-
* Run the contract-conformance suite against a driver and return a pass/fail
|
|
160
|
-
* {@link ContractReport}. Each check is executed against a freshly constructed
|
|
161
|
-
* driver from `makeDriver` so the checks never interfere with one another.
|
|
162
|
-
*
|
|
163
|
-
* This never throws for a contract violation — a failing check is captured as a
|
|
164
|
-
* `passed: false` entry with its error message — so a consumer such as the
|
|
165
|
-
* `storage:verify` CLI (task 24.2) can render every result. Property 19
|
|
166
|
-
* (task 27.3) uses the returned {@link ContractReport.passed} to assert
|
|
167
|
-
* conformance across drivers.
|
|
168
|
-
*
|
|
169
|
-
* @param makeDriver Factory producing a fresh driver for each check.
|
|
170
|
-
* @param options Optional override of the checks to run.
|
|
171
|
-
*/
|
|
172
|
-
export async function runStorageDriverContract(makeDriver, options) {
|
|
173
|
-
const checks = options?.checks ?? storageDriverContractChecks;
|
|
174
|
-
const results = [];
|
|
175
|
-
let driverName = "unknown";
|
|
176
|
-
for (const check of checks) {
|
|
177
|
-
const driver = await makeDriver();
|
|
178
|
-
driverName = driver.name;
|
|
179
|
-
try {
|
|
180
|
-
await check.run(driver);
|
|
181
|
-
results.push({ name: check.name, requirement: check.requirement, passed: true });
|
|
182
|
-
}
|
|
183
|
-
catch (error) {
|
|
184
|
-
results.push({
|
|
185
|
-
name: check.name,
|
|
186
|
-
requirement: check.requirement,
|
|
187
|
-
passed: false,
|
|
188
|
-
error: error instanceof Error ? error.message : String(error),
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
return {
|
|
193
|
-
driver: driverName,
|
|
194
|
-
passed: results.every((result) => result.passed),
|
|
195
|
-
results,
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
// ── node:test integration ─────────────────────────────────────────────────────
|
|
199
|
-
/**
|
|
200
|
-
* Register each contract check as an individual `node:test` case using the
|
|
201
|
-
* supplied `test` runner. A thin `*.test.js` passes `test` from `node:test` and
|
|
202
|
-
* a driver factory; each check runs against a fresh driver and fails the test if
|
|
203
|
-
* the driver violates the contract.
|
|
204
|
-
*
|
|
205
|
-
* Taking the runner as a parameter keeps this module free of a hard `node:test`
|
|
206
|
-
* import, so it remains importable from non-test contexts (e.g. the CLI's
|
|
207
|
-
* `storage:verify`).
|
|
208
|
-
*
|
|
209
|
-
* @param label Prefix for each generated test name (e.g. the driver label).
|
|
210
|
-
* @param makeDriver Factory producing a fresh driver for each check.
|
|
211
|
-
* @param runner The `test` function from `node:test` (or a compatible runner).
|
|
212
|
-
* @param checks Optional override of the checks to run.
|
|
213
|
-
*/
|
|
214
|
-
export function registerStorageDriverContractTests(label, makeDriver, runner, checks = storageDriverContractChecks) {
|
|
215
|
-
for (const check of checks) {
|
|
216
|
-
runner(`${label}: ${check.name}`, async () => {
|
|
217
|
-
const driver = await makeDriver();
|
|
218
|
-
await check.run(driver);
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
//# sourceMappingURL=contract.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/tests/contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"contract.test.d.ts","sourceRoot":"","sources":["../../src/tests/contract.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
// Contract-conformance suite run against the two zero-dependency drivers.
|
|
2
|
-
//
|
|
3
|
-
// Exercises the shared, parameterized suite from `./contract.js` (task 27.1)
|
|
4
|
-
// against MemoryStorageDriver and LocalStorageDriver, verifying both directions
|
|
5
|
-
// it is consumed in production:
|
|
6
|
-
//
|
|
7
|
-
// - as node:test cases via registerStorageDriverContractTests (what a driver's
|
|
8
|
-
// own test file would do), and
|
|
9
|
-
// - programmatically via runStorageDriverContract (what `storage:verify` and
|
|
10
|
-
// Property 19 use), asserting the returned report passes for every check.
|
|
11
|
-
//
|
|
12
|
-
// Each check receives a freshly constructed driver from the supplied factory;
|
|
13
|
-
// the Local driver gets a fresh temp directory per instance so checks stay
|
|
14
|
-
// isolated. Executed via `node --test dist/tests/*.test.js`.
|
|
15
|
-
//
|
|
16
|
-
// Requirements: 2.1, 2.3, 2.4
|
|
17
|
-
import test from "node:test";
|
|
18
|
-
import assert from "node:assert/strict";
|
|
19
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
20
|
-
import { tmpdir } from "node:os";
|
|
21
|
-
import { join } from "node:path";
|
|
22
|
-
import { runStorageDriverContract, registerStorageDriverContractTests, storageDriverContractChecks, } from "./contract.js";
|
|
23
|
-
import { MemoryStorageDriver } from "../drivers/memory.js";
|
|
24
|
-
import { LocalStorageDriver } from "../drivers/local.js";
|
|
25
|
-
/** A fixed clock for deterministic timestamps. */
|
|
26
|
-
const fixedClock = () => 1_700_000_000_000;
|
|
27
|
-
/** Factory: a fresh in-memory driver per call. */
|
|
28
|
-
function makeMemoryDriver() {
|
|
29
|
-
return new MemoryStorageDriver({ clock: fixedClock });
|
|
30
|
-
}
|
|
31
|
-
/** Temp roots allocated for Local drivers, cleaned up after the run. */
|
|
32
|
-
const tempRoots = [];
|
|
33
|
-
/** Factory: a fresh filesystem driver rooted at a unique temp dir per call. */
|
|
34
|
-
function makeLocalDriver() {
|
|
35
|
-
const root = mkdtempSync(join(tmpdir(), "streetjs-storage-contract-"));
|
|
36
|
-
tempRoots.push(root);
|
|
37
|
-
return new LocalStorageDriver({ root, clock: fixedClock });
|
|
38
|
-
}
|
|
39
|
-
test.after(() => {
|
|
40
|
-
for (const root of tempRoots) {
|
|
41
|
-
rmSync(root, { recursive: true, force: true });
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
// ── As node:test cases (per-driver, per-check) ────────────────────────────────
|
|
45
|
-
registerStorageDriverContractTests("memory driver contract", makeMemoryDriver, test);
|
|
46
|
-
registerStorageDriverContractTests("local driver contract", makeLocalDriver, test);
|
|
47
|
-
// ── Programmatically (the storage:verify / Property 19 consumption path) ──────
|
|
48
|
-
test("runStorageDriverContract reports a full pass for the memory driver", async () => {
|
|
49
|
-
const report = await runStorageDriverContract(makeMemoryDriver);
|
|
50
|
-
assert.equal(report.driver, "memory");
|
|
51
|
-
assert.equal(report.passed, true);
|
|
52
|
-
assert.equal(report.results.length, storageDriverContractChecks.length);
|
|
53
|
-
assert.ok(report.results.every((result) => result.passed), `all checks must pass, got: ${JSON.stringify(report.results)}`);
|
|
54
|
-
});
|
|
55
|
-
test("runStorageDriverContract reports a full pass for the local driver", async () => {
|
|
56
|
-
const report = await runStorageDriverContract(makeLocalDriver);
|
|
57
|
-
assert.equal(report.driver, "local");
|
|
58
|
-
assert.equal(report.passed, true);
|
|
59
|
-
assert.equal(report.results.length, storageDriverContractChecks.length);
|
|
60
|
-
assert.ok(report.results.every((result) => result.passed), `all checks must pass, got: ${JSON.stringify(report.results)}`);
|
|
61
|
-
});
|
|
62
|
-
test("a non-conforming driver is reported as failed, not thrown", async () => {
|
|
63
|
-
// A driver that always reports a missing object exists violates the
|
|
64
|
-
// not-found and round-trip checks; the runner must capture this as failures
|
|
65
|
-
// rather than throwing.
|
|
66
|
-
const brokenDriver = {
|
|
67
|
-
name: "broken",
|
|
68
|
-
async put(key, bytes) {
|
|
69
|
-
return {
|
|
70
|
-
key,
|
|
71
|
-
size: bytes.byteLength,
|
|
72
|
-
contentType: "application/octet-stream",
|
|
73
|
-
etag: "x",
|
|
74
|
-
checksum: "x",
|
|
75
|
-
accessLevel: "private",
|
|
76
|
-
createdAt: 0,
|
|
77
|
-
updatedAt: 0,
|
|
78
|
-
custom: {},
|
|
79
|
-
};
|
|
80
|
-
},
|
|
81
|
-
async get() {
|
|
82
|
-
return { found: false };
|
|
83
|
-
},
|
|
84
|
-
async exists() {
|
|
85
|
-
return false;
|
|
86
|
-
},
|
|
87
|
-
async delete() { },
|
|
88
|
-
async stat() {
|
|
89
|
-
return null;
|
|
90
|
-
},
|
|
91
|
-
async list() {
|
|
92
|
-
return [];
|
|
93
|
-
},
|
|
94
|
-
async putStream(key, _stream, _metadata) {
|
|
95
|
-
return this.put(key, new Uint8Array(), {});
|
|
96
|
-
},
|
|
97
|
-
async getStream() {
|
|
98
|
-
throw new Error("unsupported");
|
|
99
|
-
},
|
|
100
|
-
};
|
|
101
|
-
const report = await runStorageDriverContract(() => brokenDriver);
|
|
102
|
-
assert.equal(report.driver, "broken");
|
|
103
|
-
assert.equal(report.passed, false);
|
|
104
|
-
// existence and byte round-trip must fail (get always reports not-found);
|
|
105
|
-
// the two not-found checks and metadata shape still pass.
|
|
106
|
-
const failed = report.results.filter((result) => !result.passed).map((r) => r.name);
|
|
107
|
-
assert.ok(failed.some((name) => name.startsWith("existence")), "existence check should fail for the broken driver");
|
|
108
|
-
assert.ok(failed.some((name) => name.startsWith("byte round-trip")), "byte round-trip check should fail for the broken driver");
|
|
109
|
-
});
|
|
110
|
-
//# sourceMappingURL=contract.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"contract.test.js","sourceRoot":"","sources":["../../src/tests/contract.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"directory.test.d.ts","sourceRoot":"","sources":["../../src/tests/directory.test.ts"],"names":[],"mappings":""}
|