- All individual unit tests are independent of each other. We don't use any shared state between tests.
- Test environment includes `sakila` sample database and any change to it by a test is reverted before running other tests.
- While running unit tests, it tries to connect to mysql server running on `localhost:3306` with username `root` and password `password` (which can be configured) and if not found, it will use `sqlite` as a fallback, hence no requirement of any sql server to run tests.
### Pre-requisites
- MySQL is preferred - however tests can fallback on SQLite too
### Setup
```bash
pnpm --filter=-nocodb install
# add a .env file
cp tests/unit/.env.sample tests/unit/.env
# open .env file
open tests/unit/.env
```
Configure the following variables
> DB_HOST : host
> DB_PORT : port
> DB_USER : username
> DB_PASSWORD : password
### Run Tests
``` bash
pnpm run test:unit
```
### Folder Structure
The root folder for unit tests is `packages/nocodb/tests/unit`
-`rest` folder contains all the test suites for rest apis.
-`model` folder contains all the test suites for models.
-`factory` folder contains all the helper functions to create test data.
-`init` folder contains helper functions to configure test environment.
-`index.test.ts` is the root test suite file which imports all the test suites.
-`TestDbMngr.ts` is a helper class to manage test databases (i.e. creating, dropping, etc.).
### Factory Pattern
- Use factories for create/update/delete data. No data should be directly create/updated/deleted in the test.
- While writing a factory make sure that it can be used with as less parameters as possible and use default values for other parameters.
- Use named parameters for factories.
```ts
createUser({ email, password})
```
- Use one file per factory.
### Walk through of writing a Unit Test
We will create an `Table` test suite as an example.
#### Configure test
We will configure `beforeEach` which is called before each test is executed. We will use `init` function from `nocodb/packages/nocodb/tests/unit/init/index.ts`, which is a helper function which configures the test environment(i.e resetting state, etc.).
`init` does the following things -
- It initializes a `Noco` instance(reused in all tests).
- Restores `meta` and `sakila` database to its initial state.
- Creates the root user.
- Returns `context` which has `auth token` for the created user, node server instance(`app`), and `dbConfig`.
We will use `createProject` and `createProject` factories to create a project and a table.
```typescript
let context;
beforeEach(async function () {
context = await init();
project = await createProject(context);
table = await createTable(context, project);
});
```
#### Test case
We will use `it` function to create a test case. We will use `supertest` to make a request to the server. We use `expect`(`chai`) to assert the response.
We can then import the `Table` test suite to `Rest` test suite in `packages/nocodb/tests/unit/rest/index.test.ts` file(`Rest` test suite is imported in the root test suite file which is `packages/nocodb/tests/unit/index.test.ts`).