Apiboo-Dokumentation

DokuAPIs

Skripte & Tests

Pre-Request- und Post-Response-Skripte, die boo.*-API, Postmans pm.*, Brunos bru.* und Hoppscotchs pw.*, und die Testergebnisse.

Skripte & Tests

Skripte sind kleine JavaScript-Stücke, die mit einem Request laufen. Ein Pre-Request-Skript läuft, bevor der Request rausgeht, etwa um ein Token zu holen. Ein Post-Response-Skript läuft, nachdem die Antwort da ist, und enthält meist deine Tests: „Status ist 200“, „die Liste hat zehn Bücher“. Apiboos eigene Skript-API heißt boo.*, Postmans pm.* funktioniert ebenfalls, genauso Brunos bru.*/req/res/test() und Hoppscotchs pw.*. Die meisten importierten Skripte laufen also unverändert (die Ausnahmen stehen weiter unten).

Wo Skripte liegen

Öffne einen Request und klick auf den Tab Skript. Er hat zwei Teile:

TeilLäuftTypischer Einsatz
Pre RequestBevor der Request gesendet wird.Variablen setzen oder berechnen, ein Token holen.
Post ResponseNachdem die Antwort da ist.Tests und Werte aus der Antwort übernehmen.

Der Editor ist ein vollwertiger Code-Editor mit JavaScript-Hervorhebung und Autovervollständigung. Strg+Enter (⌘+Enter) sendet den Request direkt aus dem Editor, und Speichern speichert die Skripte mit dem Request.

Bei jedem Senden ist die Reihenfolge immer:

  1. das Pre Request-Skript des Requests,
  2. der Request wird gesendet,
  3. das Post Response-Skript des Requests.
Der Tab Skript von GET /v1/books mit geöffnetem Post Response und zwei boo.test-Aufrufen

Einen Test schreiben

Ein Test besteht aus einem Namen und einer Funktion. Wirft die Funktion einen Fehler, schlägt der Test fehl.

boo.test('status is 200', function () {
  boo.expect(boo.response.code).to.equal(200);
});

boo.test('returns books', function () {
  const books = boo.response.json();
  boo.expect(books).to.be.a('array');
  boo.expect(books.length).to.be.above(0);
});

Das Response-Objekt hat außerdem Abkürzungen für häufige Prüfungen:

boo.test('ok and JSON', function () {
  boo.response.to.be.ok();            // jeder 2xx-Status
  boo.response.to.have.status(200);
  boo.response.to.have.header('Content-Type');
});

Autovervollständigung und Snippets

Tipp boo. oder pm., um die Mitglieder zu sehen. Am Anfang einer leeren Zeile bietet die Autovervollständigung außerdem fertige Snippets an:

  • boo.test — status code is 200
  • boo.test — body value equals
  • boo.test — response time is fast
  • boo.test — has header
  • boo.environment.set — save token
  • boo.variables.set — from response

Testergebnisse lesen

Öffne nach dem Senden den Tab Testergebnisse der Antwort. Sein Badge zeigt, wie viele Tests gelaufen sind.

  • Eine Zusammenfassung, zum Beispiel 3 / 3 bestanden, mit einem Badge für „alle bestanden“ oder die Zahl der fehlgeschlagenen.
  • Jeden Test mit Haken oder Kreuz, seinem Namen und bei einem Fehlschlag dem Grund.
  • Ein abgestürztes Skript erscheint als Skript-Fehler: mit der Meldung.
  • Ist ein Test fehlgeschlagen, bittet Explain failures den KI-Assistenten um Hilfe.
Testergebnisse für GET /v1/books: 2 / 3 bestanden, mit der Fehlermeldung des fehlgeschlagenen Tests

Steht im Tab Keine Tests definiert, hat der Request kein Post-Response-Skript. Sende die Anfrage, um Testergebnisse zu sehen bedeutet, dass du ihn noch nicht gesendet hast.

Die Ergebnisse werden bei jedem Senden geleert. Bei einer Antwort, die ein laufender Event-Stream ist, läuft das Post-Response-Skript nicht (siehe Server-Sent Events).

Mit Variablen arbeiten

AufrufWirkung
boo.environment.get('name')Liest eine Variable. Gibt null zurück, wenn es sie nicht gibt.
boo.environment.set('name', value)Setzt eine Variable. Der Wert wird als Text gespeichert.
boo.environment.unset('name')Entfernt sie.
boo.environment.has('name')true, wenn es sie gibt.
boo.variables.get / set / unset / hasEine Variable nur für dieses Senden.
pm.variables.replaceIn('{{baseUrl}}/books')Setzt die Variablen in einen Text ein.

Ein Wert, den du mit environment.set setzt, gilt für deine weiteren Requests in dieser Sitzung und hat Vorrang vor Ordner-, Collection-, Umgebungs-, Arbeitsbereichs- und globalen Variablen gleichen Namens. In die Umgebung selbst wird er nicht geschrieben: Nach einem Neustart von Apiboo oder dem Abmelden ist er weg. Soll ein Wert bleiben, trag ihn von Hand in die Umgebung ein (siehe Variablen & Umgebungen).

replaceIn versteht außerdem die dynamischen Variablen {{$guid}}, {{$randomUUID}}, {{$timestamp}}, {{$isoTimestamp}} und {{$randomInt}}.

Geheime Variablen

Ein Skript kann eine geheime Variable nur lesen, wenn du es erlaubst. Liest oder setzt es ein zurückgehaltenes Geheimnis, bricht das Skript mit einem Fehler ab, und has() antwortet false. Zum Erlauben klickst du in der Variablentabelle auf das Code-Symbol in der Zeile des Geheimnisses. Sein Tooltip lautet „Scripts cannot read this secret — click to allow (needed for request signing)“. Ein weiterer Klick hält das Geheimnis wieder zurück.

Request und Antwort

MitgliedWert
boo.request.urlDie URL, Variablen bereits eingesetzt.
boo.request.methodDie Methode in Großbuchstaben.
boo.request.headers.get('name') / .toObject()Die Request-Header. In einem Pre-Request-Skript ist das leer.
boo.response.codeDer Statuscode, zum Beispiel 200.
boo.response.statusEbenfalls der Statuscode. (Bei pm.* ist es der Text, etwa "OK".)
boo.response.responseTimeDie Dauer in Millisekunden.
boo.response.json() / .text()Der Body, als JSON geparst oder als Text.
boo.response.headers.get('name') / .toObject()Die Antwort-Header.

In einem Pre-Request-Skript gibt es noch keine Antwort, boo.response ist dort null.

Assertions

boo.expect(value) kennt diese Prüfungen. Verkette sie mit to, be, have, that, which, and und not.

ArtPrüfungen
Gleichheitequal, equals, eql, deep.equal
Typa('string'), a('array') und so weiter
Zahlenabove, below, least, most
Inhaltinclude (Text und Arrays), match(/regex/), oneOf([...]), lengthOf(n), property('key'), keys(...), members([...])
Zuständeexist, ok, true, false, null, undefined, empty

not funktioniert mit exist, ok, equal, include und status.

Postman-Skripte (pm.*)

Alles oben funktioniert auch als pm.*, und insomnia.* ist ein weiterer Name dafür. Einige Postman-Funktionen verhalten sich anders:

PostmanIn Apiboo
pm.environmentFunktioniert wie unter Mit Variablen arbeiten beschrieben.
pm.globals, pm.collectionVariablesDasselbe wie pm.environment. Globale und Collection-Variablen ändern sie nicht.
pm.response.statusDer Statustext, etwa "OK". Für die Zahl nimm pm.response.code.
pm.response.to.have.jsonBody()Unterstützt.
pm.sendRequestIn Pre-Request-Skripten unterstützt, siehe Einen anderen Endpunkt aufrufen: pm.sendRequest.
pm.info.requestName, pm.info.requestIdUnterstützt.
pm.cookies, pm.iterationData, pm.setNextRequestVorhanden, aber ohne Wirkung.

Bruno-Skripte (bru.*, req, res, test)

Skripte in einer importierten Bruno-Collection laufen so, wie sie sind.

BrunoIn Apiboo
bru.getEnvVar / setEnvVar / getVar / setVar / hasVar / deleteVarFunktionieren. setVar und setEnvVar setzen beide einen Wert für die Sitzung (wie boo.environment.set); er wird nicht in die Umgebung gespeichert.
bru.interpolate('{{x}}')Funktioniert.
await bru.sendRequest({ url, method, headers, data })Funktioniert in Pre-Request-Skripten, mit oder ohne Callback; dieselben Grenzen wie pm.sendRequest (5 Aufrufe). Wie in Bruno ist eine 4xx- oder 5xx-Antwort ein Fehler: await wirft, und die response des Fehlers hat status, headers und data. Mit Callback bekommt der Callback den Fehler.
await bru.sleep(ms)Funktioniert, höchstens 3 Sekunden.
req.getUrl / getMethod / getBodyFunktionieren. In einem Pre-Request-Skript ist getBody() der Body, wie du ihn getippt hast, bevor {{Variablen}} eingesetzt werden; JSON kommt als Objekt zurück. Für ein Multipart-Formular gibt es ihn nicht.
req.getHeader / getHeadersFunktionieren, sehen in einem Pre-Request-Skript aber nur Header, die das Skript selbst gesetzt hat: Die eigenen Header des Requests sind da noch nicht zusammengesetzt.
req.setHeader / setHeaders / deleteHeader / setBody / setMethodFunktionieren in einem Pre-Request-Skript: Die Änderung wird zuletzt angewendet, nach der Auth. Änderungen gehen genau so raus, wie das Skript sie setzt: {{Variablen}} darin werden nicht eingesetzt (nimm bru.interpolate()). Header-Werte dürfen keine Zeilenumbrüche enthalten, und Host, Content-Length und ähnliche Header lassen sich nicht ändern.
req.setUrlNicht unterstützt: stoppt das Skript. Ändere stattdessen die URL im Request.
res.status, res.body, res('pfad.zu[0].wert'), res.getHeader(...)Funktionieren in Post-Response-Skripten.
test() und expect()Funktionieren; auf einen async-Test wird gewartet.
bru.getProcessEnv, require(...), bru.runRequest, bru.cookiesNicht unterstützt. Brunos .env-Datei wird nie gelesen.
bru.setNextRequest, bru.runner.*Vorhanden, aber ohne Wirkung.

Hoppscotch-Skripte (pw.*)

pw.env.get / set / unset / resolve / getResolve, pw.test, pw.expect(...).toBe / toBeLevel2xx…5xx / toBeType / toHaveLength / toInclude (und .not) sowie pw.response.status / body / headers funktionieren. Die neuere hopp.*-API wird nicht unterstützt.

Einen anderen Endpunkt aufrufen: pm.sendRequest

Ein Pre-Request-Skript kann mit pm.sendRequest eigene HTTP-Aufrufe machen. Es nimmt eine URL oder ein Request-Objekt und einen Callback:

pm.sendRequest({
  url: '{{baseUrl}}/books?limit=1',
  method: 'GET',
  header: { Accept: 'application/json' }
}, function (err, res) {
  if (err) throw err;
  pm.environment.set('firstBookId', res.json()[0].id);
});
  • {{Variablen}} in der URL werden eingesetzt.
  • header kann ein Objekt sein, eine Liste von { key, value }-Paaren oder Zeilen der Form "Name: value".
  • Ein einfaches Objekt als body wird als JSON gesendet. Mit body: { mode: 'raw', raw: … } geht der Text unverändert raus, und Content-Type setzt du selbst.
  • res hat code, status, responseTime, responseSize, json() und text(); res.headers ist ein einfaches Objekt.
  • Der Request läuft über Apiboo, dein Proxy und deine Zertifikate gelten also.

Grenzen:

  • Es funktioniert in Pre Request-Skripten, beim Senden eines Requests und unter Run Collection. In Post-Response-Skripten bricht es mit „not available in this context“ ab.
  • Es arbeitet mit einem Callback; es gibt kein Promise zurück, und await lässt sich nicht nutzen (bru.sendRequest gibt eins zurück).
  • Ein Skript darf bis zu 5 Aufrufe machen.

Rezept: vor jedem Request ein Token holen

Viele APIs wollen ein kurzlebiges Token. Dieses Pre-Request-Skript holt eins und legt es in {{token}} ab:

pm.sendRequest({
  url: '{{baseUrl}}/oauth/token',
  method: 'POST',
  header: { 'Content-Type': 'application/json' },
  body: {
    mode: 'raw',
    raw: JSON.stringify({
      client_id: pm.environment.get('clientId'),
      client_secret: pm.environment.get('clientSecret')
    })
  }
}, function (err, res) {
  if (err) throw err;
  pm.environment.set('token', res.json().access_token);
});

Stell dann die Autorisierung des Requests auf Bearer Token mit {{token}}. Apiboo wartet vor dem Senden auf den Callback, das frische Token wird also verwendet.

  • Das Token wird bei jedem Senden neu geholt. Um es wiederzuverwenden, pack den Aufruf in if (!pm.environment.has('token')) { … }.
  • Ist clientSecret eine geheime Variable, erlaube Skripten, sie zu lesen (siehe Geheime Variablen).
  • Das Token gilt nur für die Sitzung.

Wenn ein Skript fehlschlägt

  • Ein Fehler im Pre Request-Skript stoppt das Senden. Eine Meldung mit dem Titel Request not sent zeigt die erste Zeile des Fehlers und sagt, dass nichts gesendet wurde.
  • Ein Fehler im Post Response-Skript erscheint unter Testergebnisse als Skript-Fehler:.

Grenzen

  • Jedes Skript läuft in einer eigenen Sandbox ohne Netzwerkzugriff, abgesehen von pm.sendRequest und bru.sendRequest.
  • Ein Skript darf 5 Sekunden laufen (30 Sekunden, solange ein Request unterwegs ist). Danach wird es gestoppt.
  • await funktioniert auf oberster Ebene eines Skripts (für bru.sendRequest und bru.sleep). Auf eine boo.test-/pm.test-Funktion, die ein Promise zurückgibt, wird nicht gewartet; auf Brunos test() schon. Warten zählt gegen die 5-Sekunden-Grenze (30 Sekunden nur, solange ein Request unterwegs ist): Ein Skript, das insgesamt länger schläft oder wartet, wird gestoppt, und ein Test, der nie fertig wird, lässt den Lauf eine Zeitüberschreitung statt seiner Testergebnisse melden.
  • Header-Änderungen über req.* sind begrenzt: höchstens 100 Header, 16 KB pro Wert und 5 MB Body. Mehr stoppt das Skript.
  • Nutzt der Request AWS Signature als Auth, ändere Header, Body oder Methode nicht in einem Pre-Request-Skript: Die Änderung kommt nach dem Signieren, und der Server lehnt die Signatur ab.
  • Die Ausgabe von console.log erscheint nirgends in der App. Nutze einen Test oder eine Variable, um einen Wert zu sehen.