NocoBase 0.18: Establish a sound testing system

NocoBase 0.18 enhances robustness with comprehensive E2E testing, an optimized auth plugin, and modular decomposition into plugins, improving flexibility and performance.

New Features

To enhance the robustness of NocoBase, we have been supplementing E2E (end-to-end) testing throughout the fourth quarter. Concurrently, we have also been refining the entire testing system.

@nocobase/test

NocoBase test kit, include:

  • @nocobase/test/server server-side testing
    • Integrated supertest for interface testing.
    • mockDatabase and mockServer are built in.
  • @nocobase/test/client Client-side testing
    • @testing-library/react and @testing-library/user-event are integrated.
  • @nocobase/test/e2e E2E testing
    • Integration of @playwright/test.
    • Built-in common mock methods

Testing framework

  • Server-side testing, using the Vitest framework
  • Client-side testing, using the Vitest framework
  • E2E testing, using the Playwright framework

Writing tests

Server-side testing

import { mockDatabase } from '@nocobase/test/server';

describe('my db suite', () => {
  let db;

  beforeEach(async () => {
    db = mockDatabase();
    db.collection({
      name: 'posts',
      fields: [
        {
          type: 'string',
          name: 'title',
        },
      ],
    });
    await db.sync();
  });

  afterEach(async () => {
    await db.close();
  });

  test('my case', async () => {
    const repository = db.getRepository('posts');
    const post = await repository.create({
      values: {
        title: 'hello',
      },
    });

    expect(post.get('title')).toEqual('hello');
  });
});

Client-side testing

import { render, screen, userEvent, waitFor } from '@nocobase/test/client';

it('should display the value of user input', async () => {
  const { container } = render(<App1 />);
  const input = container.querySelector('input');
  await userEvent.type(input, 'Hello World');
  await waitFor(() => {
    expect(screen.getByText('Hello World')).toBeInTheDocument();
  });
});

E2E testing

import { test } from '@nocobase/test/e2e';

test('sign in', async ({ page }) => {
  await page.goto('/');
  await page.getByPlaceholder('Username/Email').click();
  await page.getByPlaceholder('Username/Email').fill('admin@nocobase.com');
  await page.getByPlaceholder('Password').click();
  await page.getByPlaceholder('Password').fill('admin123');
  await page.getByRole('button', { name: 'Sign in' }).click();
  await expect(
      page.getByTestId('user-center-button').getByText('Super Admin')
    ).toBeVisible();
});

Run the Vitest test

# Run all tests with two parallel Vitest processes for both frontend and backend.
yarn test

# Run client test cases.
yarn test --client
# equal to
yarn cross-env TEST_ENV=client-side vitest

# Run server test cases.
yarn test --server
# equal to
yarn cross-env TEST_ENV=server-side vitest

# Specify a directory or file.
yarn test your/path/src/__tests__/test-file.test.ts
# Client-side files must include /client/ 
yarn test your/path/client/src/__tests__/test-file.test.ts

📢 Difference with running vitest directly

  • When you specify the path, you can automatically recognize the front-end and back-end, the front-end must include /client/.
  • Backend test is -single-thread by default, if you want to turn it off, you can add -single-thread=false.
  • Default is --run, if you need to listen, add --watch.

Run the Playwright test

# Install dependencies
yarn e2e install-deps

# Run tests
yarn e2e test

# UI mode
yarn e2e test --ui

# Specify the application's URL
yarn e2e test --url=http://localhost:20000

# Start an app. It reinstalls every time.
yarn e2e start-app

Other changes

Optimization of auth plugin

Modular decomposition into plugins

In order to refine the kernel and make it more streamlined, certain functionalities have undergone a modularized separation. Recently, the plugins that have undergone this modularization include:

Plugin namePackage name
Action - Bulk edit@nocobase/plugin-action-bulk-edit
Action - Bulk update@nocobase/plugin-action-bulk-update
Action - Duplicate@nocobase/plugin-action-duplicate
Kanban@nocobase/plugin-kanban
Gantt@nocobase/plugin-gantt
Workflow - Aggregate@nocobase/plugin-workflow-aggregate
Workflow - Approval@nocobase/plugin-workflow-approval
Workflow - Delay@nocobase/plugin-workflow-delay
Workflow - Dynamic calculation@nocobase/plugin-workflow-dynamic-calculation
Workflow - Form trigger@nocobase/plugin-workflow-form-trigger
Workflow - JSON query@nocobase/plugin-workflow-json-query
Workflow - Loop@nocobase/plugin-workflow-loop
Workflow - Manual@nocobase/plugin-workflow-manual
Workflow - Parallel@nocobase/plugin-workflow-parallel
Workflow - Request@nocobase/plugin-workflow-request
Workflow - SQL@nocobase/plugin-workflow-sql

See complete list of plugins for details. The document is currently under construction, with some content possibly missing or awaiting translation. You can follow nocobase/docs for updates.

× View Image