test-api.k6.io

Collection of HTTP and WebSocket APIs demonstrating the power of k6

HTTP REST APIs

Public APIs

GET /public/crocodiles/ Public endpoint. List all public crocodiles.
GET /public/crocodiles/{id}/ Public endpoint. Get a single public crocodile.

Registration and authentication

POST /user/register/ Public endpoint. Register a new user.
POST /auth/cookie/login/ Public endpoint. Cookie/Session based authentication login.
POST /auth/cookie/logout/ Private endpoint. Cookie/Session logout.
POST /auth/basic/login/ Public endpoint. HTTP basic-auth login.
POST /auth/token/login/ Public endpoint. Bearer/JWT token authentication.

Private APIs

GET /my/crocodiles/ Private endpoint. List all your crocodiles
GET /my/crocodiles/{id}/ Private endpoint. Get a single crocodile.
POST /my/crocodiles/ Private endpoint. Create a new crocodile (max 100).
PUT /my/crocodiles/{id}/ Private endpoint. Update your crocodile.
PATCH /my/crocodiles/{id}/ Private endpoint. Update selected fields on your crocodile.
DELETE /my/crocodiles/{id}/ Private endpoint. Remove your crocodile.

WebSocket APIs

CONNECT /ws/crocochat/{room-name}/ WS URL to join chat in {room-name}.
message out
SET_NAME
{
  "event": "SET_NAME",
  "new_name": "MyName"
}
Outgoing WebSocket message. Sets the User name in the chat
message out
SAY
{
  "event": "SAY",
  "message": "Hello"
}
Outgoing WebSocket message. Sends message to everyone in the room
message in
USER_JOINED
{
  "event": "USER_JOINED",
  "user": "username",
  "room": "room-name"
}
Incoming WebSocket message. Someone joined the chat
message in
CHAT_MSG
{
  "event": "CHAT_MSG",
  "user": "username",
  "room": "room-name",
  "message": "message"
}
Incoming WebSocket message. Received by everyone in the room after user sends a `SAY` message
message out
LEAVE
{
  "event": "LEAVE",
  "user": "username",
  "room": "room-name"
}
Incoming/outgoing WebSocket message. Sent by user who wants to leave. Received by everyone in the room

Sample HTTP API test script

import { describe } from 'https://jslib.k6.io/functional/0.0.3/index.js';
import { Httpx, Request, Get, Post } from 'https://jslib.k6.io/httpx/0.0.2/index.js';
import { randomIntBetween, randomItem } from "https://jslib.k6.io/k6-utils/1.1.0/index.js";

export let options = {
  thresholds: {
    checks: [{threshold: 'rate == 1.00', abortOnFail: true}],
  },
  vus: 1,
  iterations: 1
};

const USERNAME = `user${randomIntBetween(1, 100000)}@example.com`;  // Set your own email;
const PASSWORD = 'superCroc2019';

let session = new Httpx({baseURL: 'https://test-api.k6.io'});

export default function testSuite() {

  describe('01. Fetch public crocs', (t) => {
    let responses = session.batch([
      new Get('/public/crocodiles/1/'),
      new Get('/public/crocodiles/2/'),
      new Get('/public/crocodiles/3/'),
      new Get('/public/crocodiles/4/'),
    ], {
      tags: {name: 'PublicCrocs'},
    });

    responses.forEach(response => {
      t.expect(response.status).as("response status").toEqual(200)
        .and(response).toHaveValidJson()
        .and(response.json('age')).as('croc age').toBeGreaterThan(7);
    });
  })

  describe(`02. Create a test user ${USERNAME}`, (t) => {

    let resp = session.post(`/user/register/`, {
      first_name: 'Crocodile',
      last_name: 'Owner',
      username: USERNAME,
      password: PASSWORD,
    });

    t.expect(resp.status).as("status").toEqual(201)
      .and(resp).toHaveValidJson();
  })

  describe(`03. Authenticate the new user ${USERNAME}`, (t) => {

    let resp = session.post(`/auth/token/login/`, {
      username: USERNAME,
      password: PASSWORD
    });

    t.expect(resp.status).as("Auth status").toBeBetween(200, 204)
      .and(resp).toHaveValidJson()
      .and(resp.json('access')).as("auth token").toBeTruthy();

    let authToken = resp.json('access');
    // set the authorization header on the session for the subsequent requests.
    session.addHeader('Authorization', `Bearer ${authToken}`);

  })

  describe('04. Create a new crocodile', (t) => {
    let payload = {
      name: `Croc Name`,
      sex: randomItem(["M", "F"]),
      date_of_birth: '2019-01-01',
    };

    let resp = session.post(`/my/crocodiles/`, payload);

    t.expect(resp.status).as("Croc creation status").toEqual(201)
      .and(resp).toHaveValidJson();

    session.newCrocId=resp.json('id');
  })

  describe('05. Fetch private crocs', (t) => {

    let response = session.get('/my/crocodiles/');

    t.expect(response.status).as("response status").toEqual(200)
      .and(response).toHaveValidJson()
      .and(response.json().length).as("number of crocs").toEqual(1);
  })

  describe('06. Update the croc', (t) => {
    let payload = {
      name: `New name`,
    };

    let resp = session.patch(`/my/crocodiles/${session.newCrocId}/`, payload);

    t.expect(resp.status).as("Croc patch status").toEqual(200)
      .and(resp).toHaveValidJson()
      .and(resp.json('name')).as('name').toEqual('New name');

    let resp1 = session.get(`/my/crocodiles/${session.newCrocId}/`);

  })

  describe('07. Delete the croc', (t) => {

    let resp = session.delete(`/my/crocodiles/${session.newCrocId}/`);

    t.expect(resp.status).as("Croc delete status").toEqual(204);
  });

}

Sample WebSocket API test script


import { randomString, randomIntBetween } from "https://jslib.k6.io/k6-utils/1.1.0/index.js";
import ws from 'k6/ws';
import { check, sleep } from 'k6';

let sessionDuration = randomIntBetween(5000, 60000); // user session between 5s and 1m
let chatRoomName = 'publicRoom'; // choose your chat room name

export let options = {
  vus: 10,
  iterations: 10,
};

export default function () {
  let url = `wss://test-api.k6.io/ws/crocochat/${chatRoomName}/`;
  let params = { tags: { my_tag: 'my ws session' } };

  let res = ws.connect(url, params, function (socket) {
    socket.on('open', function open() {
      console.log(`VU ${__VU}: connected`);

      socket.send(JSON.stringify({'event': 'SET_NAME', 'new_name': `Croc ${__VU}`}));

      socket.setInterval(function timeout() {
        socket.send(JSON.stringify({'event': 'SAY', 'message': `I'm saying ${randomString(5)}`}));
      }, randomIntBetween(2000, 8000)); // say something every 2-8seconds
    });

    socket.on('ping', function () {
      console.log('PING!');
    });

    socket.on('pong', function () {
      console.log('PONG!');
    });

    socket.on('close', function () {
      console.log(`VU ${__VU}: disconnected`);
    });

    socket.on('message', function (message){
      let msg = JSON.parse(message);
      if(msg.event === 'CHAT_MSG'){
        console.log(`VU ${__VU} received: ${msg.user} says: ${msg.message}`)
      }
      else if(msg.event === 'ERROR'){
        console.error(`VU ${__VU} received:: ${msg.message}`)
      }
      else{
        console.log(`VU ${__VU} received unhandled message: ${msg.message}`)
      }
    });

    socket.setTimeout(function () {
      console.log(`VU ${__VU}: ${sessionDuration}ms passed, leaving the chat`);
      socket.send(JSON.stringify({'event': 'LEAVE'}));

    }, sessionDuration);

    socket.setTimeout(function () {
      console.log(`Closing the socket forcefully 3s after graceful LEAVE`);
      socket.close();
    }, sessionDuration+3000);
  });

  check(res, { 'Connected successfully': (r) => r && r.status === 101 });
}