Coalesce quota refreshes and consolidate shared helpers
Some checks failed
Deploy Sokko G / deploy (push) Failing after 2s
Some checks failed
Deploy Sokko G / deploy (push) Failing after 2s
This commit is contained in:
parent
a4cf633ab4
commit
748415082b
19 changed files with 216 additions and 64 deletions
4
tests/fixtures/project-env.txt
vendored
Normal file
4
tests/fixtures/project-env.txt
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# Rôle : fournit des variables non sensibles pour tester le chargement .env.
|
||||
SOKKOG_ENV_FIXTURE_PORT=4321
|
||||
SOKKOG_ENV_FIXTURE_QUOTED="value # inside"
|
||||
SOKKOG_ENV_FIXTURE_COMMENT=value # outside
|
||||
20
tests/project-env.test.mjs
Normal file
20
tests/project-env.test.mjs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Rôle : vérifie le parsing .env, la priorité du processus et les fichiers facultatifs.
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { loadProjectEnv } from "../scripts/load-project-env.mjs";
|
||||
|
||||
for (const existing of ["9999", ""]) {
|
||||
test(`project env preserves an existing ${existing ? "nonempty" : "empty"} value`, (t) => {
|
||||
const keys = ["SOKKOG_ENV_FIXTURE_PORT", "SOKKOG_ENV_FIXTURE_QUOTED", "SOKKOG_ENV_FIXTURE_COMMENT"];
|
||||
const previous = keys.map((key) => process.env[key]);
|
||||
t.after(() => keys.forEach((key, index) => {
|
||||
if (previous[index] === undefined) delete process.env[key];
|
||||
else process.env[key] = previous[index];
|
||||
}));
|
||||
keys.forEach((key) => { delete process.env[key]; });
|
||||
process.env.SOKKOG_ENV_FIXTURE_PORT = existing;
|
||||
loadProjectEnv("tests/fixtures/project-env.txt");
|
||||
loadProjectEnv("tests/fixtures/missing-env-file");
|
||||
assert.deepEqual(keys.map((key) => process.env[key]), [existing, "value # inside", "value"]);
|
||||
});
|
||||
}
|
||||
90
tests/quota-refresh.test.mjs
Normal file
90
tests/quota-refresh.test.mjs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// Rôle : teste les rafales d'estimations, la concurrence et le nettoyage du quota.
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { createQuotaRefresh } from "../website/src/features/toolboxes/storage/quotaRefresh.js";
|
||||
|
||||
function setup(estimate) {
|
||||
const timers = new Map();
|
||||
const results = [];
|
||||
let id = 0;
|
||||
const refresh = createQuotaRefresh({
|
||||
estimate,
|
||||
onResult: (result) => results.push(result),
|
||||
schedule: (callback) => { timers.set(++id, callback); return id; },
|
||||
cancel: (key) => timers.delete(key)
|
||||
});
|
||||
function tick() {
|
||||
assert.equal(timers.size, 1);
|
||||
const [key, callback] = timers.entries().next().value;
|
||||
timers.delete(key);
|
||||
return callback();
|
||||
}
|
||||
return { ...refresh, timers, results, tick };
|
||||
}
|
||||
|
||||
test("one hundred refresh requests trigger one estimate", async () => {
|
||||
let calls = 0;
|
||||
const refresh = setup(async () => { calls++; return { usage: 12 }; });
|
||||
for (let i = 0; i < 100; i++) refresh.request();
|
||||
await refresh.tick();
|
||||
assert.equal(calls, 1);
|
||||
assert.deepEqual(refresh.results, [{ usage: 12 }]);
|
||||
assert.equal(refresh.timers.size, 0);
|
||||
});
|
||||
|
||||
test("writes during estimation schedule one follow-up and discard the stale result", async () => {
|
||||
let finish;
|
||||
let calls = 0;
|
||||
const refresh = setup(() => {
|
||||
calls++;
|
||||
return new Promise((resolve) => { finish = resolve; });
|
||||
});
|
||||
refresh.request();
|
||||
const first = refresh.tick();
|
||||
for (let i = 0; i < 100; i++) refresh.request();
|
||||
assert.equal(calls, 1);
|
||||
assert.equal(refresh.timers.size, 0);
|
||||
finish({ usage: 1 });
|
||||
await first;
|
||||
assert.deepEqual(refresh.results, []);
|
||||
const second = refresh.tick();
|
||||
finish({ usage: 2 });
|
||||
await second;
|
||||
assert.equal(calls, 2);
|
||||
assert.deepEqual(refresh.results, [{ usage: 2 }]);
|
||||
});
|
||||
|
||||
test("dispose cancels scheduled work and ignores in-flight results", async () => {
|
||||
let finish;
|
||||
const refresh = setup(() => new Promise((resolve) => { finish = resolve; }));
|
||||
refresh.request();
|
||||
refresh.dispose();
|
||||
refresh.request();
|
||||
assert.equal(refresh.timers.size, 0);
|
||||
const active = setup(() => new Promise((resolve) => { finish = resolve; }));
|
||||
active.request();
|
||||
const task = active.tick();
|
||||
active.dispose();
|
||||
finish({ usage: 5 });
|
||||
await task;
|
||||
assert.deepEqual(active.results, []);
|
||||
assert.equal(active.timers.size, 0);
|
||||
});
|
||||
|
||||
test("a failed estimate preserves the last result and allows recovery", async () => {
|
||||
let fail = false;
|
||||
const refresh = setup(async () => {
|
||||
if (fail) throw new Error("unavailable");
|
||||
return { usage: 3 };
|
||||
});
|
||||
refresh.request();
|
||||
await refresh.tick();
|
||||
fail = true;
|
||||
refresh.request();
|
||||
await refresh.tick();
|
||||
assert.deepEqual(refresh.results, [{ usage: 3 }]);
|
||||
fail = false;
|
||||
refresh.request();
|
||||
await refresh.tick();
|
||||
assert.equal(refresh.results.length, 2);
|
||||
});
|
||||
|
|
@ -113,9 +113,9 @@ test("server and vite support local env configuration", async () => {
|
|||
const viteConfig = await readFile("vite.config.js", "utf8");
|
||||
const envExample = await readFile(".env.example", "utf8");
|
||||
|
||||
assert.match(server, /function loadEnvFile/);
|
||||
assert.match(server, /load-project-env\.mjs/);
|
||||
assert.match(server, /process\.env\.PORT/);
|
||||
assert.match(viteConfig, /function loadEnvFile/);
|
||||
assert.match(viteConfig, /load-project-env\.mjs/);
|
||||
assert.match(viteConfig, /process\.env\.PORT/);
|
||||
assert.match(envExample, /PORT=5173/);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue