В современных веб-приложениях элементы <canvas>
часто используются для динамической визуализации, графиков, игр или
сложной анимации. Тестирование таких элементов требует особого подхода,
так как их содержимое нельзя проверить обычными методами, применяемыми к
DOM-элементам. Cypress предоставляет инструменты для работы с canvas
через прямой доступ к его API.
Первый шаг — это доступ к объекту canvas и его контексту:
cy.get('canvas#myCanvas')
.then($canvas => {
const canvas = $canvas[0];
const ctx = canvas.getContext('2d');
// ctx теперь позволяет читать пиксели или проверять отрисовку
});
$canvas[0] возвращает реальный DOM-элемент.getContext('2d') предоставляет интерфейс для работы с
пикселями и графикой.Canvas хранит изображение в виде массива пикселей. Для проверки
конкретного цвета в точке используется метод
getImageData:
cy.get('canvas#myCanvas')
.then($canvas => {
const ctx = $canvas[0].getContext('2d');
const imageData = ctx.getImageData(50, 50, 1, 1); // проверка пикселя (50,50)
const [r, g, b, a] = imageData.data;
expect(r).to.eq(255);
expect(g).to.eq(0);
expect(b).to.eq(0);
expect(a).to.eq(255);
});
getImageData(x, y, width, height) позволяют
выбрать область для проверки.data содержит значения RGBA для каждого
пикселя.Для сложных случаев, когда canvas рисует сложные графики, проще сравнивать его с эталонным изображением:
cy.get('canvas#myCanvas')
.then($canvas => {
const canvas = $canvas[0];
const currentData = canvas.toDataURL();
cy.fixture('expectedCanvas.png', 'base64').then(expectedData => {
expect(currentData.split(',')[1]).to.eq(expectedData);
});
});
toDataURL() возвращает изображение в формате
Base64.Canvas часто изменяется после действий пользователя. Cypress позволяет проверять изменения после событий:
cy.get('button#drawCircle').click();
cy.get('canvas#myCanvas')
.then($canvas => {
const ctx = $canvas[0].getContext('2d');
const pixel = ctx.getImageData(100, 100, 1, 1).data;
expect(pixel[0]).to.eq(0); // красный
});
Иногда для сложной визуализации используют библиотеку
pixelmatch для точного сравнения изображений:
import pixelmatch from 'pixelmatch';
import { PNG } from 'pngjs';
cy.get('canvas#myCanvas')
.then($canvas => {
const canvas = $canvas[0];
const imgData = PNG.sync.read(Buffer.from(canvas.toDataURL().split(',')[1], 'base64'));
cy.fixture('expectedCanvas.png', 'base64').then(expectedBase64 => {
const expectedData = PNG.sync.read(Buffer.from(expectedBase64, 'base64'));
const diff = new PNG({width: imgData.width, height: imgData.height});
const numDiffPixels = pixelmatch(imgData.data, expectedData.data, diff.data, imgData.width, imgData.height, {threshold: 0.1});
expect(numDiffPixels).to.eq(0);
});
});
cy.wait() или
колбэки рендера).devicePixelRatio, так как canvas
может масштабироваться.Работа с <canvas> в Cypress требует прямого
доступа к пикселям или генерации изображений, что делает проверку более
точной и детализированной по сравнению с обычным DOM-тестированием. Эти
методы позволяют создавать надежные автоматические тесты для любых
визуальных компонентов.