Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vitest: use browser mode #3222

Merged
merged 82 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
da82cf2
Add @vitest/browser
amanmahajan7 May 8, 2023
a7544ef
Enable browser mode
amanmahajan7 May 8, 2023
8e45bf7
Merge branch 'main' into am-vitest-browser
amanmahajan7 May 9, 2023
0674e45
Merge branch 'main' into am-vitest-browser
amanmahajan7 May 16, 2023
d017dc5
Merge branch 'main' into am-vitest-browser
amanmahajan7 May 19, 2023
688da4a
Update vitest
amanmahajan7 May 23, 2023
f89eab6
Use coverage-istanbu
amanmahajan7 May 24, 2023
120dbe8
update deps
amanmahajan7 May 24, 2023
3dfd6be
Merge branch 'main' into am-vitest-browser
nstepien May 26, 2023
6f2dc5f
work around react plugin bugs
nstepien May 26, 2023
fcb3529
bump deps
nstepien May 26, 2023
c139439
remove jest directive
nstepien May 26, 2023
d837de5
uninstall jsdom
nstepien May 26, 2023
58949a5
ternary
nstepien May 26, 2023
3ac17b6
no need for `@rollup/plugin-babel`
nstepien May 27, 2023
0a9f928
Merge branch 'main' into am-vitest-browser
nstepien May 30, 2023
0e01ae7
Merge branch 'main' into am-vitest-browser
amanmahajan7 Jun 1, 2023
32d0b83
update vitest
amanmahajan7 Jun 1, 2023
6bec38a
Remove incorrect test
amanmahajan7 Jun 1, 2023
1fce59e
Revert "Remove incorrect test"
amanmahajan7 Jun 1, 2023
e9f15c1
Merge branch 'main' into am-vitest-browser
amanmahajan7 Jun 1, 2023
3ff5006
Merge branch 'main' into am-vitest-browser
amanmahajan7 Jun 1, 2023
1b01229
Merge branch 'main' into am-vitest-browser
amanmahajan7 Jun 2, 2023
94c3590
Merge branch 'main' into am-vitest-browser
amanmahajan7 Jun 5, 2023
6e3d074
Merge branch 'main' into am-vitest-browser
amanmahajan7 Jun 7, 2023
771fdd5
bump dependencies
amanmahajan7 Jun 7, 2023
958bf48
try v8
amanmahajan7 Jun 7, 2023
fb09afc
Revert "try v8"
amanmahajan7 Jun 7, 2023
180f036
Merge branch 'main' into am-vitest-browser
amanmahajan7 Jun 7, 2023
1414131
update and pin playwright
nstepien Jun 9, 2023
a105d62
fix column resizing tests
nstepien Jun 9, 2023
959952c
update vitest
nstepien Jun 16, 2023
6723185
Merge branch 'main' into am-vitest-browser
nstepien Jun 16, 2023
ac78ceb
Merge branch 'main' into am-vitest-browser
nstepien Jun 20, 2023
f32859d
Merge branch 'main' into am-vitest-browser
amanmahajan7 Jun 26, 2023
c283352
Merge branch 'main' into am-vitest-browser
amanmahajan7 Jun 29, 2023
9518004
Merge branch 'main' into am-vitest-browser
amanmahajan7 Sep 12, 2023
3addf3f
update deps
amanmahajan7 Sep 12, 2023
8b24692
Merge branch 'main' into am-vitest-browser
amanmahajan7 Oct 3, 2023
776b054
Try vitest beta
amanmahajan7 Oct 3, 2023
21e11d7
Merge branch 'main' into am-vitest-browser
amanmahajan7 Oct 9, 2023
d3f07b7
Merge branch 'main' into am-vitest-browser
nstepien Feb 16, 2024
b2544ff
Merge branch 'main' into am-vitest-browser
amanmahajan7 Jul 9, 2024
25bcfc2
Fix some tests
amanmahajan7 Jul 9, 2024
bf428fa
Fix types, 1 test
amanmahajan7 Jul 9, 2024
2721a21
Fix import
amanmahajan7 Jul 9, 2024
2e2bd95
Install playwright
amanmahajan7 Jul 10, 2024
4cef86b
-1
amanmahajan7 Jul 10, 2024
6202567
Fix types
amanmahajan7 Jul 10, 2024
641cee0
Use `userEvent.dragAndDrop`
amanmahajan7 Jul 10, 2024
956652d
Fix test
amanmahajan7 Jul 12, 2024
26c206b
Test report
amanmahajan7 Jul 12, 2024
a413b7f
revert
amanmahajan7 Jul 12, 2024
677bc29
Test auto resize
amanmahajan7 Jul 12, 2024
c98497a
ESLint
amanmahajan7 Jul 12, 2024
3e22579
Fix remaining tests
amanmahajan7 Jul 15, 2024
9413d50
Fix last test
amanmahajan7 Jul 15, 2024
75687c4
Add `px`
amanmahajan7 Jul 15, 2024
5fee759
-1 TODO
amanmahajan7 Jul 15, 2024
8be6552
Move comments
amanmahajan7 Jul 15, 2024
3e8cbfb
Revert "Move comments"
amanmahajan7 Jul 15, 2024
84b8070
bump vitest
amanmahajan7 Jul 15, 2024
6fa2e78
Test scroll to the editor
amanmahajan7 Jul 15, 2024
3f1e40e
Merge branch 'main' into am-vitest-browser
amanmahajan7 Jul 15, 2024
544dbfe
Works now
amanmahajan7 Jul 15, 2024
081cb12
No need to wait for layout to settle
amanmahajan7 Jul 15, 2024
b110135
Merge branch 'main' into am-vitest-browser
amanmahajan7 Jul 15, 2024
c6eaa27
Speed up ci
amanmahajan7 Jul 15, 2024
0204627
Try ` scrollbar-width: none`
amanmahajan7 Jul 15, 2024
9a21141
Address comments
amanmahajan7 Jul 15, 2024
5e56d36
Test scrolling
amanmahajan7 Jul 15, 2024
3d33aea
Address comments
amanmahajan7 Jul 15, 2024
31e4756
Check actual direction using arrow navigation
amanmahajan7 Jul 15, 2024
48335e4
Revert "Check actual direction using arrow navigation"
amanmahajan7 Jul 15, 2024
e9224b8
Add `browser.viewport`
amanmahajan7 Jul 16, 2024
315caed
Update vite.config.ts
amanmahajan7 Jul 16, 2024
e796eeb
Remove `0`
amanmahajan7 Jul 16, 2024
8ec5203
`headless: true`
amanmahajan7 Jul 16, 2024
8035aa6
Use headless in CI
amanmahajan7 Jul 16, 2024
dc7b690
Test `scrollTop`
amanmahajan7 Jul 16, 2024
51b1f30
Delete screenshots
amanmahajan7 Jul 16, 2024
0e17bfc
Check scrollTop before typing
amanmahajan7 Jul 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ jobs:
node --run build:types
- name: Build website
run: node --run build:website
- name: Install Playwright Browsers
run: npx playwright install chromium
- name: Test
run: npm --run test
timeout-minutes: 4
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@
"@typescript-eslint/eslint-plugin": "^7.0.1",
"@typescript-eslint/parser": "^7.0.1",
"@vitejs/plugin-react": "^4.3.1",
"@vitest/coverage-v8": "^2.0.1",
"@vitest/browser": "^2.0.3",
"@vitest/coverage-istanbul": "^2.0.3",
"@wyw-in-js/rollup": "^0.5.0",
"@wyw-in-js/vite": "^0.5.0",
"babel-plugin-optimize-clsx": "^2.6.2",
Expand All @@ -92,10 +93,10 @@
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-sonarjs": "^1.0.3",
"eslint-plugin-testing-library": "^6.2.0",
"jsdom": "^24.1.0",
"jspdf": "^2.5.1",
"jspdf-autotable": "^3.5.23",
"lodash-es": "^4.17.21",
"playwright": "^1.45.1",
"postcss": "^8.4.25",
"prettier": "3.3.3",
"react": "^18.3.1",
Expand All @@ -107,7 +108,7 @@
"rollup-plugin-postcss": "^4.0.2",
"typescript": "~5.5.2",
"vite": "^5.3.3",
"vitest": "^2.0.1"
"vitest": "^2.0.3"
},
"peerDependencies": {
"react": "^18.0 || ^19.0",
Expand Down
40 changes: 15 additions & 25 deletions test/column/draggable.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { fireEvent } from '@testing-library/react';
import { act } from 'react';
import { userEvent } from '@vitest/browser/context';

import type { Column } from '../../src';
import { getHeaderCells, setup } from '../utils';
Expand All @@ -25,7 +26,7 @@ const columns: readonly Column<never>[] = [
}
];

test('draggable columns', () => {
test('draggable columns', async () => {
const onColumnsReorder = vi.fn();
setup({ columns, rows: [], onColumnsReorder });
const [cell1, cell2, cell3, cell4] = getHeaderCells();
Expand All @@ -37,36 +38,25 @@ test('draggable columns', () => {

expect(onColumnsReorder).not.toHaveBeenCalled();

let data: unknown;
let type: unknown;
const event = {
dataTransfer: {
get types() {
return [type];
},
setData(_type: unknown, _data: unknown) {
type = _type;
data = _data;
},
getData() {
return data;
}
}
} as const;

fireEvent.dragStart(cell2, event);
fireEvent.drop(cell4, event);
// eslint-disable-next-line testing-library/no-unnecessary-act
await act(async () => {
await userEvent.dragAndDrop(cell2, cell4);
});

expect(onColumnsReorder).toHaveBeenCalledWith('col2', 'col4');
onColumnsReorder.mockReset();

// should not call `onColumnsReorder` if drag and drop elements are the same
fireEvent.dragStart(cell2, event);
fireEvent.drop(cell2, event);
// eslint-disable-next-line testing-library/no-unnecessary-act
await act(async () => {
await userEvent.dragAndDrop(cell2, cell2);
});
expect(onColumnsReorder).not.toHaveBeenCalled();

// should not drag a column if it is not specified as draggable
fireEvent.dragStart(cell1, event);
fireEvent.drop(cell2, event);
// eslint-disable-next-line testing-library/no-unnecessary-act
await act(async () => {
await userEvent.dragAndDrop(cell1, cell2);
});
expect(onColumnsReorder).not.toHaveBeenCalled();
});
9 changes: 4 additions & 5 deletions test/column/renderEditCell.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import userEvent from '@testing-library/user-event';

import DataGrid from '../../src';
import type { Column, DataGridProps } from '../../src';
import { getCellsAtRowIndex, getSelectedCell, scrollGrid } from '../utils';
import { getCellsAtRowIndex, getGrid, getSelectedCell, scrollGrid } from '../utils';

interface Row {
col1: number;
Expand Down Expand Up @@ -100,15 +100,14 @@ describe('Editor', () => {
render(<EditorTest gridRows={rows} />);
await userEvent.click(getCellsAtRowIndex(0)[0]);
expect(getCellsAtRowIndex(0)).toHaveLength(2);

await scrollGrid({ scrollTop: 2000 });
expect(getCellsAtRowIndex(0)).toHaveLength(1);
expect(screen.queryByRole('spinbutton', { name: 'col1-editor' })).not.toBeInTheDocument();
expect(getGrid().scrollTop).toBe(2000);
await userEvent.keyboard('123');
expect(getCellsAtRowIndex(0)).toHaveLength(2);
expect(screen.getByRole('spinbutton', { name: 'col1-editor' })).toHaveValue(1230);
const spy = vi.spyOn(window.HTMLElement.prototype, 'scrollIntoView');
await userEvent.keyboard('{enter}');
expect(spy).toHaveBeenCalled();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did we remove these checks?

expect(screen.getByRole('spinbutton', { name: 'col1-editor' })).toHaveValue(1230);

this checked that when typing on a cell, it opens the editor and the editor receives focus, and we continue typing in the editor

    const spy = vi.spyOn(window.HTMLElement.prototype, 'scrollIntoView');
    await userEvent.keyboard('{enter}');
    expect(spy).toHaveBeenCalled();

this checked that we scrolled back to the cell even if we had scrolled past it (see await scrollGrid({ scrollTop: 2000 }); above)

Maybe we need more comments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to check the actual row in the view instead of spying on scrollIntoView

expect(getGrid().scrollTop).toBe(0);
amanmahajan7 marked this conversation as resolved.
Show resolved Hide resolved
});

describe('editable', () => {
Expand Down
140 changes: 87 additions & 53 deletions test/column/resizable.test.tsx
Original file line number Diff line number Diff line change
@@ -1,58 +1,41 @@
import { fireEvent } from '@testing-library/react';
import { act } from 'react';
import { commands, userEvent } from '@vitest/browser/context';

import type { Column } from '../../src';
import { resizeHandleClassname } from '../../src/HeaderCell';
import { getGrid, getHeaderCells, setup } from '../utils';

const pointerId = 1;

// TODO: https://github.com/jsdom/jsdom/issues/2527
class PointerEvent extends Event {
pointerId: number | undefined;
clientX: number | undefined;
interface Row {
readonly col1: number;
readonly col2: string;
}

constructor(type: string, { pointerId, clientX, ...rest }: PointerEventInit) {
super(type, rest);
this.pointerId = pointerId;
this.clientX = clientX;
}
interface ResizeArgs {
readonly column: HTMLElement;
readonly resizeBy: number;
}

// @ts-expect-error
globalThis.PointerEvent = PointerEvent;
async function resize({ column, resizeBy }: ResizeArgs) {
const resizeHandle = column.querySelector(`.${resizeHandleClassname}`);
if (resizeHandle === null) return;

interface ResizeEvent<K extends keyof DOMRect> {
column: HTMLElement;
clientXStart: number;
clientXEnd: number;
rect: Pick<DOMRect, K>;
await act(async () => {
// @ts-expect-error
await commands.resizeColumn(resizeBy);
});
}

function resize<K extends keyof DOMRect>({
column,
clientXStart,
clientXEnd,
rect
}: ResizeEvent<K>) {
async function autoResize(column: HTMLElement) {
const resizeHandle = column.querySelector(`.${resizeHandleClassname}`);
if (resizeHandle === null) return;

const original = column.getBoundingClientRect.bind(column);
column.getBoundingClientRect = () => ({
...original(),
...rect
// eslint-disable-next-line testing-library/no-unnecessary-act
await act(async () => {
await userEvent.dblClick(resizeHandle);
});
// eslint-disable-next-line testing-library/prefer-user-event
fireEvent.pointerDown(
resizeHandle,
new PointerEvent('pointerdown', { pointerId, clientX: clientXStart })
);
// eslint-disable-next-line testing-library/prefer-user-event
fireEvent.pointerMove(resizeHandle, new PointerEvent('pointermove', { clientX: clientXEnd }));
fireEvent.lostPointerCapture(resizeHandle, new PointerEvent('lostpointercapture', {}));
}

const columns: readonly Column<never>[] = [
const columns: readonly Column<Row>[] = [
{
key: 'col1',
name: 'col1',
Expand All @@ -68,34 +51,85 @@ const columns: readonly Column<never>[] = [
}
];

test('should not resize column if resizable is not specified', () => {
setup({ columns, rows: [] });
test('should not resize column if resizable is not specified', async () => {
setup<Row, unknown>({ columns, rows: [] });
const [col1] = getHeaderCells();
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 200px' });
resize({ column: col1, clientXStart: 95, clientXEnd: 200, rect: { right: 100, left: 0 } });
await resize({ column: col1, resizeBy: 50 });
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 200px' });
await resize({ column: col1, resizeBy: -50 });
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 200px' });
});

test('should resize column when dragging the handle', () => {
setup({ columns, rows: [] });
test('should resize column when dragging the handle', async () => {
setup<Row, unknown>({ columns, rows: [] });
const [, col2] = getHeaderCells();
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 200px' });
resize({ column: col2, clientXStart: 289, clientXEnd: 250, rect: { right: 300, left: 100 } });
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 161px' });
const grid = getGrid();
expect(grid).toHaveStyle({ gridTemplateColumns: '100px 200px' });
await resize({ column: col2, resizeBy: -50 });
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 150px' });
});

test('should use the maxWidth if specified', () => {
setup({ columns, rows: [] });
test('should use the maxWidth if specified', async () => {
setup<Row, unknown>({ columns, rows: [] });
const [, col2] = getHeaderCells();
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 200px' });
resize({ column: col2, clientXStart: 295, clientXEnd: 1000, rect: { right: 300, left: 100 } });
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 200px ' });
await resize({ column: col2, resizeBy: 1000 });
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 400px' });
});

test('should use the minWidth if specified', () => {
setup({ columns, rows: [] });
test('should use the minWidth if specified', async () => {
setup<Row, unknown>({ columns, rows: [] });
const [, col2] = getHeaderCells();
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 200px' });
resize({ column: col2, clientXStart: 295, clientXEnd: 100, rect: { right: 300, left: 100 } });
await resize({ column: col2, resizeBy: -150 });
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 100px' });
});

test('should not auto resize column if resizable is not specified', async () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we can test auto column

setup<Row, unknown>({
columns,
rows: [
{
col1: 1,
col2: 'a'.repeat(50)
}
]
});
const [col1] = getHeaderCells();
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 200px' });
await autoResize(col1);
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 200px' });
});

test('should auto resize column when resize handle is double clicked', async () => {
setup<Row, unknown>({
columns,
rows: [
{
col1: 1,
col2: 'a'.repeat(50)
}
]
});
const [, col2] = getHeaderCells();
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 200px' });
await autoResize(col2);
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 327.703px' });
});

test('should use the maxWidth if specified on auto resize', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could also test minWidth

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add it in the nest PR
#3547

setup<Row, unknown>({
columns,
rows: [
{
col1: 1,
col2: 'a'.repeat(500)
}
]
});
const [, col2] = getHeaderCells();
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 200px' });
await autoResize(col2);
expect(getGrid()).toHaveStyle({ gridTemplateColumns: '100px 400px' });
});
19 changes: 8 additions & 11 deletions test/rowHeight.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ test('rowHeight is number', async () => {
setupGrid(40);

const grid = screen.getByRole('grid');
expect(grid).toHaveStyle({ 'grid-template-rows': 'repeat(1, 40px) repeat(50, 40px)' });
expect(getRows()).toHaveLength(31);
expect(grid).toHaveStyle({
'grid-template-rows':
'40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px'
amanmahajan7 marked this conversation as resolved.
Show resolved Hide resolved
});
expect(getRows()).toHaveLength(30);

await userEvent.tab();
expect(grid.scrollTop).toBe(0);

// Go to the last cell
const spy = vi.spyOn(window.HTMLElement.prototype, 'scrollIntoView');
await userEvent.keyboard('{Control>}{end}');
expect(spy).toHaveBeenCalled();
expect(grid.scrollTop + grid.clientHeight).toBe(grid.scrollHeight);
});

test('rowHeight is function', async () => {
Expand All @@ -43,15 +43,12 @@ test('rowHeight is function', async () => {
const grid = screen.getByRole('grid');
expect(grid).toHaveStyle({
'grid-template-rows':
'repeat(1, 35px) 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px'
'35px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px 80px 40px 60px'
});
expect(getRows()).toHaveLength(22);

await userEvent.tab();
expect(grid.scrollTop).toBe(0);

const spy = vi.spyOn(window.HTMLElement.prototype, 'scrollIntoView');
// Go to the last cell
await userEvent.keyboard('{Control>}{end}');
expect(spy).toHaveBeenCalled();
expect(grid.scrollTop + grid.clientHeight).toBe(grid.scrollHeight);
});
Loading