go-ssb-room/docs/testing.md

4.1 KiB

Testing

go-ssb-room has a variety of tests to ensure that functionality that once worked, keeps working (it does not regress.) These tests are scattered around the repositories modules, but they are always contained in a file ending with _test.go—a compiler-enforced naming convention for Golang tests.

Running all tests

You'll need to have Node.js v14 installed before running this.

go test ./...

This command can be run at the root of the repository.

Structure

Most routes are focused on administrating the room server. Tasks such as adding new users, editing notices (like the Welcome or Code of Conduct pages). These are routes that require elevated privileges to perform actions, and they live in web/handlers/admin.

Routes that are to be visited by all users can be found in web/handlers.

Places to write tests

  • web/handlers covers site-functionality usable by all
  • web/handlers/admin covers admin-only functionality
  • roomdb/sqlite covers tests that are using default data as opposed to a given tests's mockdata

Goquery

The frontend tests—tests that check for the presence of various elements on served pages—use the module goquery for querying the returned HTML.

Snippets

Print the raw html of the corresponding page

html, _ := ts.Client.GetHTML(url)
fmt.Println(html.Html())

Find and print the title element of a page

html, _ := ts.Client.GetHTML(url)
title := html.Find("title")
// print the title string
fmt.Println(title.Text())

Filling the mockdb

go-ssb-room uses database mocks for performing tests against the backend database logic. This means prefilling a route with the data you expect to be returned when the route is queried. This type of testing is an alternative to using an entire pre-filled sqlite database of test data.

As such, there is no command you run first to generate your fake database, but functions you have to call in a kind of pre-test setup, inside each testing block you are authoring.

counterfeiter generates a bunch of methods for each function, so you have XXXXReturns, XXXCallCount XXXArgsForCall(i) etc

cryptix

That is, for a function GetUID there is a corresponding mock-filling function GetUIDReturns.

The following examples show more concretely what mocking the data looks like.

Having the List() function return a static list of three items:

// go-ssb-room/web/handlers/admin/allow_list_test.go:113
lst := roomdb.ListEntries{
	{ID: 1, PubKey: refs.FeedRef{ID: bytes.Repeat([]byte{0}, 32), Algo: "fake"}},
	{ID: 2, PubKey: refs.FeedRef{ID: bytes.Repeat([]byte("1312"), 8), Algo: "test"}},
	{ID: 3, PubKey: refs.FeedRef{ID: bytes.Repeat([]byte("acab"), 8), Algo: "true"}},
}
ts.MembersDB.ListReturns(lst, nil)

Checking how often RemoveID was called and with what arguments:

// go-ssb-room/web/handlers/admin/allow_list_test.go:210
 a.Equal(1, ts.MembersDB.RemoveIDCallCount())
 _, theID := ts.MembersDB.RemoveIDArgsForCall(0)
 a.EqualValues(666, theID)

Example test

package handlers

import (
	"fmt"
	"net/http"
	"testing"

	"github.com/ssb-ngi-pointer/go-ssb-room/v2/roomdb"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestNoticeShow(t *testing.T) {
	ts := setup(t)
	a, r := assert.New(t), require.New(t)

	testNotice := roomdb.Notice{
		ID:    123,
		Title: "foo",
	}
	ts.NoticeDB.GetByIDReturns(testNotice, nil)

	html, resp := ts.Client.GetHTML("/notice/show?id=123")
	a.Equal(http.StatusOK, resp.Code)

	r.Equal("foo", html.Find("title").Text())
	fmt.Println(html.Text())
}

Muxrpc room functionality

Go

The folder tests/nodejs contains basic tests of the client<>server functionality for the different aspects of a room.

cd muxrpc/test/go
go test

JavaScript

The folder tests/nodejs contains tests for the JavaScript implementation. To run them, install node and npm and run the following:

cd muxrpc/test/nodejs
npm ci
go test