local-instance: simulate a teacher, and run the files-storage consumer

`scripts/simulate-teacher.mjs` creates, edits and deletes what teachers
create — course, room, topic, task, board, columns, cards, rich text,
link, Etherpad pad, folder, files — so the MCP server can be exercised
against content the real account has never held. It is the only thing
here that writes to a Schulcloud and refuses any non-localhost address.
`scripts/mcp-env.sh` points the server and CLI at the instance.

Two gaps it exposed in the stack itself:

The files-storage AMQP consumer is a separate entrypoint, and we were
running only the HTTP one. Nothing was bound to the `files-storage`
exchange, so `TaskService.delete` — which awaits deleteFilesOfParent
over AMQP before touching the task — hung until the request timeout.
Deleting any task or topic answered 408 with the entity still there.

The demo data is dated 2017-2018 and the v3 endpoints filter on those
dates, so a student saw no tasks at all. seed.sh now brings courses and
homework into the present, which is the difference between a fixture
that exercises the student-facing surface and one that looks empty.

Teams turn out to be uncreatable through the API (the legacy service
registers no `create`, v3 has no route), and a new board is unpublished
and 403s for students, so the simulation adopts a seeded team and leaves
one board a draft on purpose.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-09-13 15:39:51 +02:00
parent 521c21f7ae
commit 3a168e37e5
7 changed files with 490 additions and 0 deletions

View File

@@ -170,6 +170,45 @@ The second row matters: no submission in the real account has ever had a
numeric grade, so `formatGradeState`'s percentage branch had never been seen
against real data. Here it can be.
## Simulating a teacher
`scripts/simulate-teacher.mjs` creates, edits and deletes the things teachers
create, so the MCP server can be run against content the real account has never
held. It is the only thing in this repository that writes to a Schulcloud, and
it refuses to run against anything but a localhost address.
```bash
node scripts/simulate-teacher.mjs create # course, room, topic, task, board,
# columns, cards, rich text, link,
# Etherpad pad, folder, files
node scripts/simulate-teacher.mjs update # rename and rewrite all of it
node scripts/simulate-teacher.mjs delete # remove it again
```
Ids are kept in `.simulate-teacher.json` between phases, so the MCP server can
be pointed at the instance in between:
```bash
eval "$(./scripts/mcp-env.sh)" # as the demo student
cd .. && npm run smoke # 39 checks against the local instance
```
Two things it does **not** do, because the API does not allow them:
- **Teams cannot be created.** The legacy service registers
`['find','get','update','patch','remove']` and no `create`, and v3 has no team
route beyond news and create-room; `POST /teams` answers 405. The script
adopts a seeded team and edits that instead.
- **A board is created unpublished.** Students get 403 on it while the course
page still lists its title, so `create` publishes the main board and leaves a
second one as a draft on purpose — both states are worth testing against.
`seed.sh` also drags the demo data into the present. The seed ships courses that
ended in 2018 and homework due in 2017, and the v3 endpoints filter on those
dates: a student sees no tasks at all in an ended course, which makes the whole
student-facing surface look empty for reasons that have nothing to do with the
code under test.
## Profiles
| Profile | Services | Cost |