TASK22269: add phase22 azurestorage helper contract tests
This commit is contained in:
@@ -2975,3 +2975,35 @@ Validation:
|
|||||||
Follow-ups:
|
Follow-ups:
|
||||||
|
|
||||||
- Any further `azurestorage.js` cleanup should remain bounded (e.g., logging-only normalization) and separated from behavior-affecting refactors.
|
- Any further `azurestorage.js` cleanup should remain bounded (e.g., logging-only normalization) and separated from behavior-affecting refactors.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### CL-083: TASK22269 Slice B1.8 — phase22 azurestorage helper contract coverage
|
||||||
|
|
||||||
|
date: 2026-03-26
|
||||||
|
author: Cline
|
||||||
|
scope: `tests/phase22/{azurestorage-helper-behaviour,index}.test.cjs`
|
||||||
|
type: change
|
||||||
|
rationale: Execute the selected bounded test-only follow-up by adding focused regression coverage for recently added azurestorage helper contracts.
|
||||||
|
impact: Improves confidence in query-path and hash-metadata helper output stability without changing runtime behavior.
|
||||||
|
status: completed
|
||||||
|
|
||||||
|
Summary:
|
||||||
|
|
||||||
|
- Added new phase22 suite: `tests/phase22/azurestorage-helper-behaviour.test.cjs`.
|
||||||
|
- Test suite isolates helper block from `actions/azurestorage.js` and verifies:
|
||||||
|
- `buildDownloadBlobQueryPath` default encoding output
|
||||||
|
- `buildDeleteBlobQueryPath` non-encoded option behavior
|
||||||
|
- `buildGetBlobListQueryPath` query output contract
|
||||||
|
- `buildHashMetadataPaths` key/value shape (`hashedfilepath`, `hasheddeletepath`, `hashgetblobs`)
|
||||||
|
- Wired suite into aggregate runner `tests/phase22/index.test.cjs`.
|
||||||
|
|
||||||
|
Validation:
|
||||||
|
|
||||||
|
- `npm run lint` -> pass with warnings only (pre-existing `react-hooks/exhaustive-deps`; no new lint errors)
|
||||||
|
- `node tests/phase22/index.test.cjs` -> pass (includes new azurestorage-helper 4/4)
|
||||||
|
- `node tests/phase7/service-behaviour.test.cjs` -> pass (13/13)
|
||||||
|
|
||||||
|
Follow-ups:
|
||||||
|
|
||||||
|
- Optional next bounded slice: add an explicit assertion for encoded `casefolderID` variants containing reserved query characters (`?`, `&`) if those inputs are expected in future flows.
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
const vm = require("vm");
|
||||||
|
const assert = require("assert");
|
||||||
|
|
||||||
|
const rootDir = path.resolve(__dirname, "..", "..");
|
||||||
|
|
||||||
|
const loadAzureStorageHelperModule = (injected = {}) => {
|
||||||
|
const filePath = path.join(rootDir, "actions", "azurestorage.js");
|
||||||
|
const source = fs.readFileSync(filePath, "utf8");
|
||||||
|
|
||||||
|
const start = source.indexOf("const buildDownloadBlobQueryPath =");
|
||||||
|
const end = source.indexOf("export const createContainerSas =");
|
||||||
|
|
||||||
|
if (start < 0 || end < 0 || end <= start) {
|
||||||
|
throw new Error("Unable to isolate azurestorage helper function block");
|
||||||
|
}
|
||||||
|
|
||||||
|
let helperSource = source.slice(start, end);
|
||||||
|
helperSource +=
|
||||||
|
"\nmodule.exports = { buildDownloadBlobQueryPath, buildDeleteBlobQueryPath, buildGetBlobListQueryPath, buildHashMetadataPaths };\n";
|
||||||
|
|
||||||
|
const context = {
|
||||||
|
module: { exports: {} },
|
||||||
|
exports: {},
|
||||||
|
require,
|
||||||
|
encodeURIComponent,
|
||||||
|
hashAPIPath: (route) => `HASH(${route})`,
|
||||||
|
...injected
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.runInNewContext(helperSource, context, { filename: filePath });
|
||||||
|
return context.module.exports;
|
||||||
|
};
|
||||||
|
|
||||||
|
const tests = [];
|
||||||
|
const test = (name, fn) => tests.push({ name, fn });
|
||||||
|
|
||||||
|
test("azurestorage helper builds download path with default encoding", () => {
|
||||||
|
const mod = loadAzureStorageHelperModule();
|
||||||
|
|
||||||
|
const pathResult = mod.buildDownloadBlobQueryPath({
|
||||||
|
containerName: "alpha",
|
||||||
|
casefolderID: "A/B",
|
||||||
|
blobname: "my doc.pdf"
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
pathResult,
|
||||||
|
"/api/file/downloadblob?container=alpha&casefolderID=A%2FB&blobname=my%20doc.pdf"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("azurestorage helper preserves raw values when encoding disabled", () => {
|
||||||
|
const mod = loadAzureStorageHelperModule();
|
||||||
|
|
||||||
|
const deletePath = mod.buildDeleteBlobQueryPath({
|
||||||
|
containerName: "alpha",
|
||||||
|
casefolderID: "A/B",
|
||||||
|
blobname: "my doc.pdf",
|
||||||
|
encodeCasefolderID: false,
|
||||||
|
encodeBlobname: false
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
deletePath,
|
||||||
|
"/api/file/deleteblob?container=alpha&casefolderID=A/B&blobname=my doc.pdf"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("azurestorage helper builds getbloblist path without field mutation", () => {
|
||||||
|
const mod = loadAzureStorageHelperModule();
|
||||||
|
|
||||||
|
const listPath = mod.buildGetBlobListQueryPath({
|
||||||
|
containerName: "alpha",
|
||||||
|
casefolderID: "A/B"
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
listPath,
|
||||||
|
"/api/file/getbloblist?container=alpha&casefolderID=A/B"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("azurestorage helper builds hash metadata map with stable keys", () => {
|
||||||
|
const mod = loadAzureStorageHelperModule({
|
||||||
|
hashAPIPath: (route) => `signed:${route}`
|
||||||
|
});
|
||||||
|
|
||||||
|
const metadata = mod.buildHashMetadataPaths({
|
||||||
|
containerName: "alpha",
|
||||||
|
casefolderID: "A/B",
|
||||||
|
blobname: "my doc.pdf"
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepStrictEqual(JSON.parse(JSON.stringify(metadata)), {
|
||||||
|
hashedfilepath:
|
||||||
|
"signed:/api/file/downloadblob?container=alpha&casefolderID=A%2FB&blobname=my%20doc.pdf",
|
||||||
|
hasheddeletepath:
|
||||||
|
"signed:/api/file/deleteblob?container=alpha&casefolderID=A%2FB&blobname=my%20doc.pdf",
|
||||||
|
hashgetblobs:
|
||||||
|
"signed:/api/file/getbloblist?container=alpha&casefolderID=A/B"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const run = async () => {
|
||||||
|
let passed = 0;
|
||||||
|
for (const currentTest of tests) {
|
||||||
|
await currentTest.fn();
|
||||||
|
passed += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Phase 22 azurestorage-helper tests passed (${passed}/${tests.length}).`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = run;
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
run().catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ const runCaseServiceTests = require("./case-service-behaviour.test.cjs");
|
|||||||
const runPortalServiceTests = require("./portal-service-behaviour.test.cjs");
|
const runPortalServiceTests = require("./portal-service-behaviour.test.cjs");
|
||||||
const runAuthRedirectSafetyTests = require("./auth-redirect-safety.test.cjs");
|
const runAuthRedirectSafetyTests = require("./auth-redirect-safety.test.cjs");
|
||||||
const runI18nRouteParityTests = require("./i18n-route-parity.test.cjs");
|
const runI18nRouteParityTests = require("./i18n-route-parity.test.cjs");
|
||||||
|
const runAzurestorageHelperTests = require("./azurestorage-helper-behaviour.test.cjs");
|
||||||
|
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
await runCoreTokenTests();
|
await runCoreTokenTests();
|
||||||
@@ -14,6 +15,7 @@ const run = async () => {
|
|||||||
await runPortalServiceTests();
|
await runPortalServiceTests();
|
||||||
await runAuthRedirectSafetyTests();
|
await runAuthRedirectSafetyTests();
|
||||||
await runI18nRouteParityTests();
|
await runI18nRouteParityTests();
|
||||||
|
await runAzurestorageHelperTests();
|
||||||
console.log("Phase 22 combined suite passed.");
|
console.log("Phase 22 combined suite passed.");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user