import React from 'react'; import {act} from 'react-dom/test-utils'; import TestDriver from '@airtable/blocks-testing'; import {render, screen, waitFor, getByRole} from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import recordListFixture from './fixtures/simple_record_list'; import UpdateRecordsApp from '../frontend/UpdateRecordsApp'; describe('UpdateRecordsApp', () => { const mutations = []; let addMutation = mutation => mutations.push(mutation); let testDriver; beforeEach(() => { testDriver = new TestDriver(recordListFixture); mutations.length = 0; testDriver.watch('mutation', addMutation); render( <testDriver.Container> <UpdateRecordsApp /> </testDriver.Container>, ); }); afterEach(() => { testDriver.unwatch('mutations', addMutation); }); async function clickUpdate(button) { await act(async () => { userEvent.click(button); await waitFor(() => expect(button.disabled).toBe(false), {timeout: 3000}); }); } it('renders a message with no button when another table is active', async () => { testDriver.setActiveCursorModels({table: 'Griddle cakes', view: 'Grid view 2'}); await waitFor(() => expect(document.body.textContent).not.toBe('')); const {textContent} = document.body; expect(textContent).toMatch(/\bswitch\b/i); expect(textContent).toMatch(/\bInventory\b/); expect(screen.queryByRole('button')).toBe(null); }); describe('disabled button', () => { it('correct active table with zero selected records', async () => { const button = await waitFor(() => screen.getByRole('button')); expect(button.disabled).toBe(true); expect(button.textContent).toMatch(/\b0\s+records\b/i); }); it('correct active table with some selected records and underprivileged user', async () => { testDriver.simulatePermissionCheck(mutation => { return mutation.type !== 'setMultipleRecordsCellValues'; }); testDriver.userSelectRecords(['recb', 'recc']); const button = await waitFor(() => screen.getByRole('button')); expect(button.disabled).toBe(true); expect(button.textContent).toMatch(/\b2\s+records\b/i); }); }); it('renders a single enabled button for correct active table with some selected records', async () => { testDriver.userSelectRecords(['reca', 'recc']); const button = await waitFor(() => screen.getByRole('button')); expect(button.disabled).toBe(false); expect(button.textContent).toMatch(/\b2\s+records\b/i); }); it('updates selected records only', async () => { testDriver.userSelectRecords(['recb']); const button = await waitFor(() => screen.getByRole('button')); await clickUpdate(button); expect(mutations).toEqual( expect.arrayContaining([ { type: 'setMultipleRecordsCellValues', tableId: 'tblTable', records: [ { id: 'recb', cellValuesByFieldId: {fldInStock: 15}, }, ], }, ]), ); }); it('batches updates', async () => { const biggerFixture = JSON.parse(JSON.stringify(recordListFixture)); const extraRecords = Array.from(Array(321)).map((_, index) => ({ id: `rec${index}`, commentCount: 0, createdTime: '2020-11-04T23:20:14.000Z', cellValuesByFieldId: { fldName: `crepe #${index}`, fldInStock: 0, }, })); biggerFixture.base.tables[0].records.push(...extraRecords); testDriver = new TestDriver(biggerFixture); testDriver.watch('mutation', addMutation); testDriver.userSelectRecords(extraRecords.map(({id}) => id)); document.body.innerHTML = ''; render( <testDriver.Container> <UpdateRecordsApp /> </testDriver.Container>, ); const button = await waitFor(() => screen.getByRole('button')); await waitFor(() => expect(button.disabled).toBe(false)); await clickUpdate(button); const batchSizes = mutations .filter(({type}) => type === 'setMultipleRecordsCellValues') .map(({records}) => records.length); for (const batchSize of batchSizes) { expect(batchSize).toBeLessThan(51); } expect(batchSizes.reduce((a, b) => a + b)).toBe(321); }); it('maintains selection through multiple updates', async () => { testDriver.userSelectRecords(['recc']); const button = await waitFor(() => screen.getByRole('button')); await clickUpdate(button); expect(mutations).toEqual( expect.arrayContaining([ { type: 'setMultipleRecordsCellValues', tableId: 'tblTable', records: [ { id: 'recc', cellValuesByFieldId: {fldInStock: 9}, }, ], }, ]), ); mutations.length = 0; await clickUpdate(button); expect(mutations).toEqual( expect.arrayContaining([ { type: 'setMultipleRecordsCellValues', tableId: 'tblTable', records: [ { id: 'recc', cellValuesByFieldId: {fldInStock: 10}, }, ], }, ]), ); }); });