LU08.A03 - Bookshelf mit Authentifikation mit Bruno
Erweitere deine Bruno-Requests um Authentifikation, Autorisation und automatisierte Tests – nach Bruno-Best-Practices.
Zielbild
- Ordnerstruktur pro Fachgebiet (
auth,books). - Kurz & klar benannte Requests (kebab-case):
login-admin.bru,read-book.bru,list-books.bru… - Environments je Zielsystem/Rolle statt Test-Steuerlogik im Script.
- Token nur temporär in einem lokalen Environment, das nicht eingecheckt wird.
- Tests sind klein, deterministisch, ohne Ablaufsteuerung.
Ausgangslage
Erweiterte API: https://it.bzz.ch/book/ext/ (Login/Token, Rollen)
| Rolle | Benutzername | Passwort | Berechtigung |
|---|---|---|---|
| admin | admin | admin | alle Funktionen |
| user | musterh | geheim | read, list |
| guest | – | – | nur login |
Ohne gültiges Token → Rolle guest → nur login. Fehlende Berechtigung → 403.
Projektstruktur (Beispiel)
bookshelf-bruno/
auth/
login-admin.bru
login-user.bru
login-invalid.bru
books/
read-book.bru
list-books.bru
save-book.bru (optional)
delete-book.bru (optional)
environments/
dev.json
dev.local.json (in .gitignore!)
Hinweise
dev.json: allgemeine, unverfängliche Variablen (baseUrl).dev.local.json: Token & sensible Werte (nicht ins Repo).- In Bruno das passende Environment aktivieren (oben
Environment).
Environments
environments/dev.json
{ "name": "dev", "vars": { "baseUrl": "https://it.bzz.ch/book/ext" } }
environments/dev.local.json (nicht einchecken)
{ "name": "dev.local", "vars": { "token": "", "username": "admin", "password": "admin" } }
Aktiviere zuerstdev, dann zusätzlichdev.local(oder führe beide Inhalte zu einem aktiven Environment zusammen – Hauptsache:tokenlebt lokal).
Requests (auth)
login-admin.bru
POST → {{baseUrl}}/login
Body (JSON): {„username“:„admin“,„password“:„admin“}
Tests
test("Login admin -> 200 & token gesetzt", () => { expect(res.status).to.equal(200); const data = res.json(); expect(data).to.have.property("token"); // Token nur im aktiven (lokalen) Environment halten: bru.setEnvVar("token", data.token, { persist: false }); });
login-user.bru
POST → {{baseUrl}}/login
Body (JSON): {„username“:„musterh“,„password“:„geheim“}
Tests
test("Login user -> 200 & token gesetzt", () => { expect(res.status).to.equal(200); const data = res.json(); bru.setEnvVar("token", data.token, { persist: false }); });
login-invalid.bru
POST → {{baseUrl}}/login
Body (JSON): {„username“:„wrong“,„password“:„wrong“}
Tests
test("Login invalid -> 401, kein token", () => { expect(res.status).to.equal(401); });
Requests (books)
Gemeinsame Header: im Request Headers
- Key:
Authorization - Value:
Bearer {{token}}
read-book.bru
GET → {{baseUrl}}/read/<book_uuid>
Tests (rollenbewusst, aber ohne Ablaufsteuerung)
test("Read Book – rollenabhängig", () => { const s = res.status; if (bru.getVar("token")) { // Angemeldet: admin/user expect(s).to.equal(200); const b = res.json(); expect(b).to.have.property("book_uuid"); expect(b).to.have.property("title"); } else { // guest (ohne Token) expect(s).to.equal(403); } });
list-books.bru
GET → {{baseUrl}}/list
Tests
test("List Books – rollenabhängig", () => { const s = res.status; if (bru.getVar("token")) { expect(s).to.equal(200); const arr = res.json(); expect(Array.isArray(arr)).to.equal(true); // ggf. bekannte Länge/Felder prüfen } else { expect(s).to.equal(403); } });
Ausführung (Runner ohne Script-Steuerlogik)
Variante 1 (empfohlen & simpel): drei Läufe mit klaren Vorbedingungen
1. ''guest'': ''token'' in ''dev.local.json'' leer lassen → ''list-books'', ''read-book'' ausführen → **403** erwartet. 2. ''user'': ''login-user.bru'' einmal senden → ''token'' wird gesetzt → ''list/read'' → **200**. 3. ''admin'': ''login-admin.bru'' einmal senden → ''list/read'' → **200** (volle Rechte).
Variante 2 (Runner-Ordnung):
- Ordner
authvorbooksausführen (login-*.bruzuerst), danachbooks/*.
Best Practice: Keine Ablaufsteuerung per Script (setNextRequest). Halte Tests kurz & deterministisch; die Reihenfolge steuert der Runner/Ordner.
Qualitäts-Checks (Best Practices)
- DRY: Gemeinsame Header (
Authorization) in den jeweiligen Requests; Wiederholungen minimieren. - Kleine Assertions: Je Testfile 1–3 präzise Assertions (Status, Struktur, zentrale Felder).
- Keine Persistenz für Tokens:
persist: falseverwenden;dev.local.jsonnicht committen. - Sprechende Namen: Dateien/Ordner klar benennen (
login-admin,list-books). - Reproduzierbar: Jeder Request ist alleinstehend ausführbar (kein versteckter Zustand in Tests).
