Merge pull request #4838 from meerkat-morecats/test-crud

chore: 补充crud单测
This commit is contained in:
RUNZE LU 2022-07-25 10:47:40 +08:00 committed by GitHub
commit 6df12c8560
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 3064 additions and 1409 deletions

View File

@ -1,11 +1,17 @@
import React = require('react'); import React = require('react');
import {render, waitFor} from '@testing-library/react'; import {cleanup, fireEvent, render, waitFor} from '@testing-library/react';
import '../../src'; import '../../src';
import {render as amisRender} from '../../src'; import {clearStoresCache, render as amisRender} from '../../src';
import {makeEnv, wait} from '../helper'; import {makeEnv, wait} from '../helper';
import rows from '../mockData/rows'; import rows from '../mockData/rows';
const fetcher = async (config: any) => { afterEach(() => {
cleanup();
clearStoresCache();
jest.useRealTimers();
});
async function fetcher(config: any) {
return { return {
status: 200, status: 200,
headers: {}, headers: {},
@ -18,10 +24,11 @@ const fetcher = async (config: any) => {
} }
} }
}; };
}; }
test('Renderer:crud', async () => { test('Renderer:crud basic interval headerToolbar footerToolbar', async () => {
const {container, getByText} = render( const mockFetcher = jest.fn(fetcher);
const {container} = render(
amisRender( amisRender(
{ {
type: 'page', type: 'page',
@ -29,6 +36,10 @@ test('Renderer:crud', async () => {
type: 'crud', type: 'crud',
api: '/api/mock2/sample', api: '/api/mock2/sample',
syncLocation: false, syncLocation: false,
interval: 1000,
perPage: 2,
headerToolbar: ['export-excel', 'statistics'],
footerToolbar: ['pagination', 'export-excel'],
columns: [ columns: [
{ {
name: '__id', name: '__id',
@ -41,34 +52,52 @@ test('Renderer:crud', async () => {
{ {
name: 'browser', name: 'browser',
label: 'Browser' label: 'Browser'
},
{
name: 'platform',
label: 'Platform(s)'
},
{
name: 'version',
label: 'Engine version'
},
{
name: 'grade',
label: 'CSS grade'
} }
] ]
} }
}, },
{}, {},
makeEnv({fetcher}) makeEnv({fetcher: mockFetcher})
) )
); );
await waitFor(() => { await waitFor(() => {
expect(getByText('Internet Explorer 4.0')).toBeInTheDocument(); expect(container.querySelectorAll('tbody>tr').length > 5).toBeTruthy();
expect(
container.querySelector('[data-testid="spinner"]')
).not.toBeInTheDocument();
}); });
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();
await wait(1001);
expect(mockFetcher).toHaveBeenCalledTimes(2);
});
test('Renderer:crud stopAutoRefreshWhen', async () => {
const mockFetcher = jest.fn(fetcher);
render(
amisRender(
{
type: 'page',
body: {
type: 'crud',
api: '/api/mock2/sample',
syncLocation: false,
interval: 1000,
stopAutoRefreshWhen: 'true',
columns: [
{
name: '__id',
label: 'ID'
}
]
}
},
{},
makeEnv({fetcher: mockFetcher})
)
);
await wait(1001);
expect(mockFetcher).toHaveBeenCalledTimes(1);
}); });
test('Renderer:crud loadDataOnce', async () => { test('Renderer:crud loadDataOnce', async () => {
@ -114,7 +143,9 @@ test('Renderer:crud loadDataOnce', async () => {
) )
); );
await wait(300); await waitFor(() => {
expect(container.querySelectorAll('tbody>tr').length > 5).toBeTruthy();
});
expect(container.querySelector('.cxd-Crud-pager')).not.toBeInTheDocument(); expect(container.querySelector('.cxd-Crud-pager')).not.toBeInTheDocument();
}); });
@ -141,7 +172,9 @@ test('Renderer:crud list', async () => {
) )
); );
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();
await wait(300); await waitFor(() => {
expect(container.querySelectorAll('.cxd-ListItem').length > 5).toBeTruthy();
});
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();
}); });
@ -182,12 +215,14 @@ test('Renderer:crud cards', async () => {
); );
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();
await wait(300); await waitFor(() =>
expect(container.querySelector('.cxd-Card-title')).toBeInTheDocument()
);
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();
}); });
test('Renderer:crud [source]', async () => { test('Renderer:crud source & alwaysShowPagination', async () => {
const {container, getByText} = render( const {container} = render(
amisRender( amisRender(
{ {
type: 'page', type: 'page',
@ -197,6 +232,7 @@ test('Renderer:crud [source]', async () => {
body: { body: {
type: 'crud', type: 'crud',
source: 'fields', source: 'fields',
alwaysShowPagination: true,
columns: [ columns: [
{ {
name: '__id', name: '__id',
@ -221,6 +257,7 @@ test('Renderer:crud [source]', async () => {
}); });
test('Renderer:crud filter', async () => { test('Renderer:crud filter', async () => {
const mockFetcher = jest.fn(fetcher);
const {container} = render( const {container} = render(
amisRender( amisRender(
{ {
@ -228,6 +265,9 @@ test('Renderer:crud filter', async () => {
body: { body: {
type: 'crud', type: 'crud',
api: '/api/mock2/sample', api: '/api/mock2/sample',
defaultParams: {defaultValue: 'defaultValue'},
pageField: 'customPageField',
perPageField: 'customPerPageField',
filter: { filter: {
title: '条件搜索', title: '条件搜索',
body: [ body: [
@ -269,15 +309,392 @@ test('Renderer:crud filter', async () => {
} }
}, },
{}, {},
makeEnv({fetcher: mockFetcher})
)
);
await waitFor(() => {
expect(container.querySelectorAll('tbody>tr').length > 5).toBeTruthy();
});
const {query} = mockFetcher.mock.calls[0][0];
expect(query.defaultValue).toBe('defaultValue');
expect(query.keywords).toBe('123');
expect(query.customPageField).toBe(1);
expect(query.customPerPageField).toBe(10);
});
test('Renderer:crud draggable & itemDraggableOn', async () => {
const {container} = render(
amisRender(
{
type: 'page',
body: {
type: 'crud',
api: '/api/mock2/sample',
syncLocation: false,
draggable: true,
itemDraggableOn: '${__id !== 1}',
columns: [
{
name: '__id',
label: 'ID'
},
{
name: 'engine',
label: 'Rendering engine'
},
{
name: 'browser',
label: 'Browser'
},
{
name: 'platform',
label: 'Platform(s)'
},
{
name: 'version',
label: 'Engine version'
},
{
name: 'grade',
label: 'CSS grade'
}
]
}
},
{},
makeEnv({fetcher})
)
);
await waitFor(() => {
expect(container.querySelector('[icon="exchange"]')).toBeInTheDocument();
});
fireEvent.click(container.querySelector('[icon="exchange"]')!);
await waitFor(() => {
expect(container.querySelector('[icon=drag]')).toBeInTheDocument();
});
expect(container.querySelectorAll('[icon=drag]').length).toBe(9);
});
test('Renderer:crud quickEdit quickSaveApi', async () => {
const mockFetcher = jest.fn(fetcher);
const {container, getAllByText} = render(
amisRender(
{
type: 'page',
body: {
type: 'crud',
api: '/api/mock2/sample',
syncLocation: false,
stopAutoRefreshWhen: 'true',
quickSaveApi: '/api/mock2/sample/bulkUpdate',
columns: [
{
name: '__id',
label: 'ID'
},
{
name: 'engine',
label: 'Rendering engine',
quickEdit: true
},
{
name: 'browser',
label: 'Browser',
quickEdit: {
saveImmediately: true
}
}
]
}
},
{},
makeEnv({fetcher: mockFetcher})
)
);
await waitFor(() => {
expect(container.querySelectorAll('tbody>tr').length > 5).toBeTruthy();
});
fireEvent.click(container.querySelector('.cxd-Field-quickEditBtn')!);
await waitFor(() => {
expect(container.querySelector('input[name="engine"]')).toBeInTheDocument();
});
fireEvent.change(container.querySelector('input[name="engine"]')!, {
target: {value: 'xxx'}
});
fireEvent.click(container.querySelector('button[type="submit"]')!);
await waitFor(() => {
expect(
container.querySelector('input[name="engine"]')
).not.toBeInTheDocument();
});
fireEvent.click(getAllByText('提交')[0]!);
await wait(10);
// * 提交后会调用一次 quickSaveApi 和 api
expect(mockFetcher).toBeCalledTimes(3);
});
test('Renderer:crud quickSaveItemApi saveImmediately', async () => {
const mockFetcher = jest.fn(fetcher);
const {container, getAllByText} = render(
amisRender(
{
type: 'page',
body: {
type: 'crud',
api: '/api/mock2/sample',
syncLocation: false,
stopAutoRefreshWhen: 'true',
quickSaveItemApi: '/api/mock2/sample/$id',
hideQuickSaveBtn: true,
columns: [
{
name: '__id',
label: 'ID'
},
{
name: 'browser',
label: 'Browser',
quickEdit: {
saveImmediately: true
}
}
]
}
},
{},
makeEnv({fetcher: mockFetcher})
)
);
await waitFor(() => {
expect(container.querySelectorAll('tbody>tr').length > 5).toBeTruthy();
});
fireEvent.click(container.querySelector('.cxd-Field-quickEditBtn')!);
await waitFor(() => {
expect(
container.querySelector('input[name="browser"]')
).toBeInTheDocument();
});
fireEvent.change(container.querySelector('input[name="browser"]')!, {
target: {value: 'xxx'}
});
fireEvent.click(container.querySelector('button[type="submit"]')!);
await waitFor(() => {
expect(
container.querySelector('input[name="browser"]')
).not.toBeInTheDocument();
});
// * 提交后会调用一次 quickSaveItemApi 和 api
expect(mockFetcher.mock.calls[1][0].url).toBe('/api/mock2/sample/');
expect(mockFetcher).toBeCalledTimes(3);
});
test('Renderer:crud bulkActions', async () => {
const {container} = render(
amisRender(
{
type: 'page',
body: {
type: 'crud',
api: '/api/mock2/sample',
syncLocation: false,
bulkActions: [
{
label: '批量删除',
actionType: 'ajax',
api: 'delete:/amis/api/mock2/sample/${ids|raw}',
confirmText: '确定要批量删除?'
}
],
columns: [
{
name: '__id',
label: 'ID'
},
{
name: 'engine',
label: 'Rendering engine',
quickEdit: true
},
{
name: 'browser',
label: 'Browser',
quickEdit: {
saveImmediately: true
}
}
]
}
},
{},
makeEnv({fetcher}) makeEnv({fetcher})
) )
); );
// await wait(300); await waitFor(() => {
expect(container.querySelectorAll('tbody>tr').length > 5).toBeTruthy();
});
expect(
container.querySelector('.cxd-Button.is-disabled')
).toBeInTheDocument();
fireEvent.click(
container.querySelector('.cxd-Table-checkCell input[type="checkbox"]')!
);
await waitFor(() => { await waitFor(() => {
expect( expect(
container.querySelector('[data-testid="spinner"]') container.querySelector('.cxd-Button.is-disabled')
).not.toBeInTheDocument(); ).not.toBeInTheDocument();
}); });
});
test('Renderer: crud sortable & orderBy & orderDir & orderField', async () => {
const mockFetcher = jest.fn(fetcher);
const {container} = render(
amisRender(
{
type: 'page',
body: {
type: 'crud',
api: '/api/mock2/sample',
orderBy: 'id',
orderDir: 'desc',
syncLocation: false,
orderField: 'xxx',
columns: [
{
name: '__id',
label: 'ID',
sortable: true
},
{
name: 'engine',
label: 'Rendering engine',
quickEdit: true
}
]
}
},
{},
makeEnv({fetcher: mockFetcher})
)
);
await waitFor(() => {
expect(container.querySelectorAll('tbody>tr').length > 5).toBeTruthy();
});
expect(mockFetcher.mock.calls[0][0].query).toEqual({
orderBy: 'id',
orderDir: 'desc',
page: 1,
perPage: 10
});
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();
}); });
test('Renderer: crud keepItemSelectionOnPageChange & maxKeepItemSelectionLength & labelTpl', async () => {
const mockFetcher = jest.fn(fetcher);
const {container} = render(
amisRender(
{
type: 'page',
body: {
type: 'crud',
api: '/api/mock2/sample',
syncLocation: false,
keepItemSelectionOnPageChange: true,
maxKeepItemSelectionLength: 4,
labelTpl: '${id}${engine}',
bulkActions: [
{
label: '批量删除',
actionType: 'ajax',
api: ''
}
],
columns: [
{
name: '__id',
label: 'ID',
sortable: true
},
{
name: 'engine',
label: 'Rendering engine',
quickEdit: true
}
]
}
},
{},
makeEnv({fetcher: mockFetcher})
)
);
await waitFor(() => {
expect(container.querySelectorAll('tbody>tr').length > 5).toBeTruthy();
});
// 点击全部
fireEvent.click(container.querySelector('th input[type="checkbox"]')!);
await waitFor(() => {
expect(
container.querySelectorAll('.cxd-Crud-selection>.cxd-Crud-value').length
).toBe(4);
});
expect(container).toMatchSnapshot();
});
test('Renderer: crud autoGenerateFilter', async () => {
const mockFetcher = jest.fn(fetcher);
const {container} = render(
amisRender(
{
type: 'page',
body: {
type: 'crud',
api: '/api/mock2/sample',
syncLocation: false,
autoGenerateFilter: true,
bulkActions: [
{
label: '批量删除',
actionType: 'ajax',
api: ''
}
],
columns: [
{
name: '__id',
label: 'ID',
sortable: true,
searchable: {
type: 'input-text',
name: 'id',
label: '主键',
placeholder: '输入id'
}
},
{
name: 'engine',
label: 'Rendering engine',
quickEdit: true
}
]
}
},
{},
makeEnv({fetcher: mockFetcher})
)
);
await waitFor(() => {
expect(container.querySelectorAll('tbody>tr').length > 5).toBeTruthy();
});
expect(
container.querySelector('input[name="id"][placeholder="输入id"]')
).toBeInTheDocument();
});

View File

@ -927,11 +927,12 @@ test('Renderer:table list', () => {
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();
}); });
test('Renderer:table selectable', async () => { describe('Renderer:table selectable & itemCheckableOn', () => {
const schema: any = { const schema: any = {
type: 'table', type: 'table',
title: '表格1', title: '表格1',
selectable: true, selectable: true,
itemCheckableOn: '${__id != 1}',
data: { data: {
items: rows items: rows
}, },
@ -947,19 +948,26 @@ test('Renderer:table selectable', async () => {
] ]
}; };
const {container, rerender} = render(amisRender(schema, {}, makeEnv({}))); test('radio style', async () => {
const {container, debug} = render(amisRender(schema, {}, makeEnv({})));
await waitFor(() => {
expect(container.querySelector('[type=radio]')).toBeInTheDocument();
});
await waitFor(() => { expect(
expect(container.querySelector('[type=radio]')).toBeInTheDocument(); container.querySelector('[data-id="1"] [type=radio][disabled=""]')!
).toBeInTheDocument();
}); });
schema.multiple = true; test('checkbox style', async () => {
const {container: multipleContainer} = render( schema.multiple = true;
amisRender(schema, {}, makeEnv({})) const {container} = render(amisRender(schema, {}, makeEnv({})));
); await waitFor(() => {
await waitFor(() => { expect(container.querySelector('[type=checkbox]')).toBeInTheDocument();
});
expect( expect(
multipleContainer.querySelector('[type=checkbox]') container.querySelector('[data-id="1"] [type=checkbox][disabled=""]')!
).toBeInTheDocument(); ).toBeInTheDocument();
}); });
}); });