test(phase6e): acceptance suite, real-Lab rehearsal, and regression fixes for the lock fix
Adds platform/test/e2e-phase6e.js (23 checks): full ROOT 02/03/04 hierarchy/content/assessment-
pool verification, the complete ROOT 01->02->03->04->05 chain proven on one student (each
course's completion unlocking exactly the next), the direct-API lock bypass proven blocked on
both a Phase 6E course pair and a pre-existing unrelated pair, existing ROOT 06+/Capstone/
is_required behavior confirmed unaffected, self-paced no-instructor-deferral scan,
instructor-notes exclusion, RBAC, persistence, isolation, version stability, content validation.
23/23 pass against both a warm and a freshly-reset stack.
Adds platform/test/foundations-helper.js — a shared completeRootFoundations01Through04/
completeThroughRoot06/completeThroughRoot10 helper, extracted once multiple suites needed the
identical real-completion sequence as test setup, rather than duplicating it four times.
Adds infra/scripts/drills/{run,test}-phase6e-foundations-rehearsal — the real Platform API/
Gateway/Provisioner/disposable-Lab/nested-Docker/Git/k3s dress rehearsal: one real Lab task per
new course (nginx inspection, a real merge conflict, a real container-networking fix) plus the
full chain to a genuine ROOT 05 unlock, with k3s reconfirmed healthy and untouched at the end.
13/13 pass against a real, freshly-built stack.
Fixes the regression fallout from the (correct) course-routes.js lock fix: several earlier
suites' own historical shortcuts had accumulated small ordering/scenario gaps the missing
enforcement had been silently covering for — none were platform bugs. e2e-phase6a/6b/6c/6d.js
now inject the real ROOT 01-04 (and where needed ROOT 05/06/10) completion sequence via
foundations-helper.js before touching ROOT 05+ content; e2e-phase6b.js's bypass-student flow now
completes deployment-rollback/job-task/cronjob-task/container-logging-mcq explicitly (real
scenarios added in later phases that its original ALL_STAGES list never included); e2e-phase6a/
6d.js's own ROOT 01/05 completion tests now complete each module fully (through its lab and
reflection) before moving to the next, since those courses' own modules carry real intra-course
prerequisites. Two now-obsolete Phase-6D-era assertions in e2e-phase6d.js (ROOT 02-04 stay
PLANNED / stay vacuously unlocked) are updated to assert the opposite, with a comment explaining
Phase 6E intentionally changed that fact. All four suites re-verified green fresh.
Also fixes a real, reproducible dash-vs-bash bug caught while testing the new ROOT 01
rehearsal's ordering fix: `&>file` misparses under this image's actual /bin/sh (dash), breaking
a later `$!`-based kill — the rehearsal script now writes multi-line completion loops with
explicit status assertions, matching the discipline the other suites already use.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
@@ -150,16 +150,20 @@ async function main() {
|
||||
|
||||
await step('completing the remaining ROOT 01 activities finishes the course and unlocks ROOT 02', async () => {
|
||||
await session.request('POST', '/api/student/activities/root-01-m01-a04-reflection/complete');
|
||||
// ROOT 01's own modules carry real intra-course prerequisites (m02 requires m01 complete,
|
||||
// etc., found and enforced this phase — see docs/PHASE6E_ROOT_FOUNDATIONS_COMPLETION.md) —
|
||||
// each module must complete fully, including its lab and reflection, before the next
|
||||
// module's activities will accept a manual-marker completion.
|
||||
const labs = { m02: 'linux-shell-basics', m03: 'linux-filesystem-navigation', m04: 'linux-files-and-text', m05: 'linux-process-management', m06: 'linux-permissions-foundations' };
|
||||
for (const m of ['m02', 'm03', 'm04', 'm05', 'm06']) {
|
||||
for (const suffix of ['a01-lesson', 'a02-demonstration', 'a03-knowledge-check', 'a04-guided-exercise']) {
|
||||
await session.request('POST', `/api/student/activities/root-01-${m}-${suffix}/complete`);
|
||||
const r = await session.request('POST', `/api/student/activities/root-01-${m}-${suffix}/complete`);
|
||||
assert.equal(r.status, 200, `completing root-01-${m}-${suffix} should 200: ${JSON.stringify(r.body)}`);
|
||||
}
|
||||
await session.request('POST', '/api/progress/record', { scenario_id: labs[m], status: 'completed', environment_id: envId });
|
||||
const r = await session.request('POST', `/api/student/activities/root-01-${m}-a06-reflection/complete`);
|
||||
assert.equal(r.status, 200, `completing root-01-${m}-a06-reflection should 200: ${JSON.stringify(r.body)}`);
|
||||
}
|
||||
for (const [sid, activity] of [['linux-shell-basics', 'root-01-m02-a06-reflection'], ['linux-filesystem-navigation', 'root-01-m03-a06-reflection'], ['linux-files-and-text', 'root-01-m04-a06-reflection'], ['linux-process-management', 'root-01-m05-a06-reflection']]) {
|
||||
await session.request('POST', '/api/progress/record', { scenario_id: sid, status: 'completed', environment_id: envId });
|
||||
await session.request('POST', `/api/student/activities/${activity}/complete`);
|
||||
}
|
||||
await session.request('POST', '/api/student/activities/root-01-m06-a06-reflection/complete');
|
||||
|
||||
const start = await session.request('POST', '/api/assessments/rootnode-linux-foundations-assessment/start');
|
||||
assert.equal(start.status, 201);
|
||||
|
||||
Reference in New Issue
Block a user