Skip to content

Code conventions

Tom Gehrke edited this page Apr 27, 2018 · 1 revision

Table of Contents

File naming and repository structure

Files are to be named in lowercase kebab-case (e.g. kebab-case.js).

Repository structure

There are three main directories inside the src directory: config, lib and scenes.

config

Configuration Data. Examples are: The apollo client configuration, the theme.json file and the main route definitions.

lib

Auxiliary files (See Helpers / Auxiliary code).

scenes

The components to display on a certain route. A scene consists of a Header and a Body part, that are displayed when visiting a certain URL. Sub-routes are managed inside the scene if they share the same Header component, otherwise they are a stand-alone scene and need to be inserted into the config/routes.js file.

Examples
  • / uses its own Header and Body (Scene)
  • /some-user uses its own Header and Body (Scene)
  • /some-user/repositories uses the same Header as /some-user (Not a scene)
  • /some-user/some-repository uses its own Header and Body (Scene)
  • /some-user/some-repository/settings uses the same Header as /some-user/some-repository (Not a scene)

Functional components vs. Class components

Use functional components as a default and only use class components if it makes the code significantly easier to write, read, or test (mainly when using lifecycle methods).

Code formatting

Code is to be formatted with prettier before merging. There are plugins for most editors to automatically format code on save, but it's also possible to run it in a pre-commit hook.

Helpers / Auxiliary code

Auxiliary code can be placed in the same file it is needed (only if it is needed only there), or placed in either of these locations:

/src/lib/

Code that is needed in more than one place and/or is of a very general or isolated nature (the code could go into another package)

Nested directory

If some code is only used in one file, the auxiliary code can be placed inside an adjacent directory of the same name as the importing file.

importing-file.js
importing-file/the-imported-file.js

Containers vs. Components

We don't make this distinction. Splitting a component into a pure version and a non-pure version (e.g. with GraphQL data) is not necessary unless it makes testing significantly easier.

Tests

Testability

Components (and other code) should be written to be as testable as possible. Some hints to make code more testable:

Use Query and Mutation components instead of graphql for ease of stubbing data

it("matches the snapshot", () => {
  mockResponse(query, response);
  expect(render(...)).toMatchSnapshot();
});

Export private functions in the default export with named symbols as key, so they can be imported in tests

export default { [Symbol.for("privateFunc1")]: privateFunc };

import Tested from "...";
const privateFunc1 = Tested[Symbol.for("privateFunc1")];

File location and naming

Test files are to be placed in a __tests__ directory adjacent to the tested file. The name is to be equal to the tested file.

component.js
__tests__/component.js

Exports

Use named exports for everything except for private functions that need to be tested (see Testability).

export const Header = ...;
// or
const Header = ...;
export { Header };