그리드 테스트하기
@freegridjs/testing은 jsdom, happy-dom, 실제 브라우저에서 사용자처럼 셀 읽기·편집·정렬·키 입력을 합니다. mockLayout으로 jsdom에 행이 그려지고, selectors는 Playwright·Cypress에 씁니다.
그리드가 있는 화면을 테스트하면 그리드 내부 DOM 때문에 깨지거나, jsdom에서는 행이 아예 안 나오기 쉽습니다. @freegridjs/testing은 사용자처럼 그리드를 다루고(더블클릭, 입력, Enter, 헤더 클릭) 화면에 보이는 것을 읽어 줍니다.
npm i -D @freegridjs/testing단위 테스트(Vitest, Jest)
import { beforeAll, expect, it } from 'vitest';
import { createGrid } from '@freegridjs/core';
import { gridHarness, mockLayout } from '@freegridjs/testing';
// jsdom has no layout: without this every element is 0 × 0 and no rows are drawn
beforeAll(() => { mockLayout(); });
it('refuses a quantity over 99 and saves a good one', async () => {
const host = document.createElement('div');
document.body.append(host);
const api = createGrid(host, { columns, data });
const grid = gridHarness(host);
await grid.waitForRows();
expect(grid.headers()).toEqual(['Name', 'Qty', 'City']);
expect(grid.edit(0, 'qty', '500').ok).toBe(false); // the editor stays open with the message
grid.press('Escape');
expect(grid.edit(0, 'qty', '42')).toEqual({ ok: true });
await grid.settle();
expect(grid.cellText(0, 'qty')).toBe('42');
expect(api.getModifiedRows().updated).toHaveLength(1);
grid.clickHeader('qty'); // sort
await grid.settle();
expect(grid.column('qty')).toEqual(['1', '2', '42']);
});| 이름 | 타입 | 설명 |
|---|---|---|
mockLayout({ width?, height? }) | () => void | jsdom / happy-dom에서 요소에 크기를 줌(기본 1024 × 600, 약 20행)과 없는 canvas 경고를 끔. 되돌리는 함수를 돌려줌. |
gridHarness(container) | GridHarness | 요소 안의 그리드를 위한 도우미: createGrid에 준 요소, 컴포넌트의 host, 그리드 루트. |
cell(r, colId) / cellText(r, colId) | HTMLElement | null / string | 그려진 셀과 그 글자. 화면에 없으면 null / 빈 글자. |
rows(colIds?) / column(colId) | string[][] / string[] | 그려진 행의 글자(표시 순서). |
headers() / columnIds() / rowCount() | string[] / string[] / number | 보이는 컬럼의 헤더 글자와 id. 그려진 행 수. |
click / dblclick / clickHeader / press | void | 사용자 같은 포인터·키 이벤트. press는 그리드에 포커스가 있는 것처럼 보냄. |
edit(r, colId, text, finish?) | { ok, message? } | 더블클릭 후 글자를 바꾸고 Enter(또는 'Tab', 'Escape'). 값이 저장됐을 때만 ok true: 'Escape'면 false, 규칙이 거부하면 ok false와 안내. 텍스트·숫자·날짜·서식 편집기용. |
waitForRows(count?, timeout?) / settle() | Promise<void> | 행이 그려질 때까지, 또는 다음 그리기까지 기다림. |
React, Vue, Svelte, Angular와 함께
컴포넌트를 평소처럼 렌더링하고, 그 바깥 요소를 gridHarness에 넘기세요.
import { render } from '@testing-library/react';
import { FreeGrid } from '@freegridjs/react';
import { gridHarness, mockLayout } from '@freegridjs/testing';
beforeAll(() => { mockLayout(); });
it('shows the orders', async () => {
const { container } = render(<FreeGrid columns={columns} data={orders} />);
const grid = gridHarness(container);
await grid.waitForRows(3);
expect(grid.column('customer.name')).toEqual(['Kim', 'Lee', 'Park']);
});브라우저 테스트(Playwright, Cypress)
실제 브라우저에서는 selectors를 쓰세요. 그리드 내부 구조가 바뀌어도 맞춰 바뀝니다.
import { selectors } from '@freegridjs/testing';
await page.locator(selectors.cell(0, 'qty')).dblclick();
await page.keyboard.type('42');
await page.keyboard.press('Enter');
await expect(page.locator(selectors.cell(0, 'qty'))).toHaveText('42');
await page.locator(selectors.header('qty')).click(); // sort
// Cypress
cy.get(selectors.cell(0, 'name')).should('have.text', 'Kim');| selectors. | 대상 |
|---|---|
| root | 그리드 루트 |
| cell(rowIndex, colId) / row(rowIndex) | 본문 셀 / 행. rowIndex는 표시 위치 |
| header(colId) / headerLabel | 헤더 셀 / 그 안의 글자 |
| editor / editorMessage | 열린 편집기 상자 / 그 안내 |
| filterInput(colId) / overlay | 필터 행 입력칸 / "행 없음"·로딩 표시 |
테스트에서도 화면에 보이는 행만 그려집니다. 아래쪽 데이터는 API(getDisplayedRows, getCellValue)로 읽거나 먼저 scrollToRow로 스크롤하세요. 선택형 편집기(select, combo, 달력)는 단위 테스트에서 api.setCellValue로 넣는 것이 가장 쉽고, 브라우저에서는 옵션을 클릭하세요.
이 페이지에 대한 질문
Jest나 Vitest 테스트에서 그리드에 행이 하나도 안 나오는 이유는?
jsdom에는 레이아웃이 없어 모든 요소의 높이가 0이라 그리드가 행을 그리지 않습니다. 테스트 전에 @freegridjs/testing의 mockLayout()을 부르고(또는 직접 크기를 주고), gridHarness(el).waitForRows()로 행을 기다리세요.
Playwright나 Cypress에서 셀을 찾으려면?
@freegridjs/testing의 selectors.cell(rowIndex, colId)를 쓰세요. 예: page.locator(selectors.cell(0, 'name')). 행 번호는 정렬·필터 뒤의 표시 위치입니다.