Unit-тесты
Unit-тесты пишутся на Mocha + Chai и запускаются в реальном браузере. Исходный код расширения компилируется и загружается на страницу вместе с тестами — тестируется настоящий бандл, как он будет работать в браузере.
Структура
local/js/vendor/my-extension/
└── test/
└── unit/
├── my-extension.test.ts
└── utils.test.tsБазовый тест
ts
// test/unit/my-extension.test.ts
import { describe, it, beforeEach } from 'mocha';
import { assert } from 'chai';
import { MyExtension } from '../../src/my-extension';
describe('MyExtension', () => {
let instance: MyExtension;
beforeEach(() => {
instance = new MyExtension({ name: 'test' });
});
it('should create instance with name', () => {
assert.equal(instance.getName(), 'test');
});
it('should throw on invalid name', () => {
assert.throws(() => {
new MyExtension({ name: '' });
}, TypeError);
});
});Тестирование DOM
Тесты запускаются в браузере, поэтому доступен полноценный DOM:
ts
import { describe, it, beforeEach, afterEach } from 'mocha';
import { assert } from 'chai';
import { Button } from '../../src/button';
describe('Button', () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
container.remove();
});
it('should render button element', () => {
const button = new Button({ text: 'OK' });
container.appendChild(button.render());
const node = container.querySelector('.ui-btn');
assert.isNotNull(node);
assert.equal(node?.textContent, 'OK');
});
it('should handle click', () => {
let clicked = false;
const button = new Button({
text: 'OK',
onClick: () => { clicked = true; },
});
container.appendChild(button.render());
container.querySelector('.ui-btn')?.click();
assert.isTrue(clicked);
});
});Тестирование асинхронного кода
ts
import { describe, it } from 'mocha';
import { assert } from 'chai';
import { DataLoader } from '../../src/data-loader';
describe('DataLoader', () => {
it('should load data', async () => {
const loader = new DataLoader('/api/items');
const result = await loader.fetch();
assert.isArray(result.items);
assert.isAbove(result.items.length, 0);
});
it('should handle errors', async () => {
const loader = new DataLoader('/api/not-found');
try
{
await loader.fetch();
assert.fail('Expected error');
}
catch (error)
{
assert.instanceOf(error, Error);
}
});
});Тестирование EventEmitter
ts
import { describe, it } from 'mocha';
import { assert } from 'chai';
import { Chat } from '../../src/chat';
describe('Chat', () => {
it('should emit message event', () => {
const chat = new Chat();
const messages: string[] = [];
chat.subscribe('message', (event) => {
messages.push(event.getData().text);
});
chat.sendMessage('hello');
chat.sendMessage('world');
assert.deepEqual(messages, ['hello', 'world']);
});
});