Please read through these guidelines when developing for BlattWerkzeug.
Code-formatting for the
client folder is automated and enforced by prettier. You may either run
make format-code in the
client folder manually or setup your IDE or editor of choice to run
prettier automatically: Official guidelines for editor integration.
Typical development setup¶
It is recommended to use four terminal windows when developing, that each show the output from one of the following
- Targets in the
make client-compile-devin the
clientfolder. This will starts a filesystem watcher that rebuilds the client incrementally on any change, which drastically reduces subsequent compile times.
make client-test-watchto continously run the client testcases in the background.
- Targets in the
make reset-live-data dev-make-guest-admin run-devif you have pulled any seed data changes that need to be reflected. The
dev-make-guest-admintarget is optional, but very convenient during development.
make test-watchto continously run the server testcases in the background. This requires a running PostgreSQL database server.
By using this setup you ensure that all tests are run continously, no matter whether you are working on the server or on the client.
Tests, the CI-server and code coverage¶
git push will trigger a build on a CI-server that uses the Docker-images that are part of the repository. But you can (and should!) run the testcases locally, preferably all the time, but at least before a commit.
Client side testing¶
make test in the
client folder will run the tests once against a headless instance of Google Chrome and Firefox. Technically this works by passing the
--headless flag when starting the browser, which suppresses any windows that would normally be shown.
make test-watchwill run the tests continously after every change to the clients code.
- The environment variable
TEST_BROWSERScontrols which browsers will run the test, multiple browsers may be specified using a
,and spaces are not allowed. The following values should be valid:
Chromefor the non-headless variants that open dedicated browser windows.
ChromeHeadlessthat run in the background without any visible window.
After running tests the folder
coverage will contain a navigateable code coverage report:
Server side testing¶
Tests for the server are run in the same fashion: Call
make test in the
server folder to run them once,
make test-watch run them continously. And again the folder
coverage will contain a code coverage report:
Description files and JSON schema¶
The server and the client need to agree on “over the wire”
JSON-objects in order to function properly. As the server is using Ruby on Rails and the client is written in Typescript, this gap is bridged using JSON-schema. All of the relevant schemas live in the
The schemas are generated using an automatic conversion process based on Typescript
interface definitions. By convention every file that ends on
description.ts is a file that is meant to be used as an input for schema generation. If such a file is edited, the affected schemas need to be regenerated by running
make all in the
- They define interfaces that are used when communicating between server and client.
- They must not import complex libraries such as
- Because other parts of the projects may import such complex libraries, the
description.tsfiles may only import other
Using JSON schema to validate client requests¶
When clients want to make a request to the server, they usually need to construct a
object that satisfied the relevant description-
interface. For this part of the request, Typescript ensures just fine that the data that is send over will actually be understood and valid.
On the server a
controller must use
JsonSchemaHelper#ensure_request. As with any helper, the
JsonSchemaHelper must be referenced via
include. If a specific controller requires a request to be made with a
TableDescription document, the source code would read as follows:
table_description = ensure_request("TableDescription", request.body.read)
ensure_request method will take any string, parse it and validate it against the required schema and then return the corresponding hash with the data. If the given string is syntactically valid
JSON but does not conform to the schema, an exception is raised and the request is aborted with a
401 Bad Request response.
This procedure ensures that at least the structure of the passed in document is sound. There should be no need to re-validate the structure on the server or to program defensively in order to mitigate missing keys. Even if somebody sends request with arbitrary garbage, these should be filtered out by
Using JSON schema to validate server responses¶
Because the client is only expected to work with a conforming server, there is no response-validation infrastructure in place during the “nomal” execution of the client. Instead the results of
HTTP-requests are simply casted to the expected
The server side
request tests ensure that the server responds with conforming documents. A custom rspec validator
validate_against should be used with every testcase that expects a specific response.
Using JSON schema to validate models¶
The backing PostgreSQL database uses a few tables that store
jsonb-blobs. After all, PostgreSQL is the best NoSQL database that is available 😉 The
jsonb-columns are used for complex and self contained data structures such as the syntaxtrees for a code resource. To ensure that the database does not degenerate overall, the custom
json_schema validator for Active Model ensures the validity of all stored blobs.
Loading and storing seed data¶
BlattWerkzeug comes with a complex set of required objects to work properly. This includes grammars, block languages, example projects, … The “normal” Rails way of providing those objects via
db/seeds.rb does not work for these structures at all: They are simply to complex to be meaningfully edited by hand.
Makefile therefore exposes the
store-live-data target which stores the current state of the programing languages and projects in the
seed folder. This allows programmers to edit grammars, block languages and projects using the web-IDE and to persist those changes in the git repository.
The YAML-files in the
seed-folder are very prone to merge conflicts. Please make sure to only ever commit as small changes as possible. It is good practive to routinely use
make reset-live-data run-dev when starting the server to ensure that your database-state is always up do date. If you run
store-live-data from an old database state you may override newer changes that are part of the repository already.
The preferred way to figure out the reason for undesired behaviour is by writing testcases: This ensures that the problem does not resurface later as a regression. But if you don’t understand at all why something is going wrong, an interactive debugger is of course helpful.
At least the normal development tools of Firefox and Chrome are capable of debugging the Angular application. Depending on your workflow, the
debugger statement (Documentation at MDN) may be helpful to set breakpoints directyl from your editor of choice.