/** * Parsing strings as references when importing into an existing table */ import {assert, driver, Key, WebElement} from 'mocha-webdriver'; import * as gu from 'test/nbrowser/gristUtils'; import {openSource as openSourceMenu, waitForColumnMapping} from 'test/nbrowser/importerTestUtils'; import {setupTestSuite} from 'test/nbrowser/testUtils'; describe('ImportReferences', function() { this.timeout(30000); const cleanup = setupTestSuite(); before(async function() { // Log in and import a sample document. const session = await gu.session().teamSite.user('user1').login(); await session.tempDoc(cleanup, 'ImportReferences.grist'); }); afterEach(() => gu.checkForErrors()); it('should convert strings to references', async function() { // Import a CSV file containing strings representing references await gu.importFileDialog('./uploads/name_references.csv'); assert.equal(await driver.findWait('.test-importer-preview', 2000).isPresent(), true); // Change the destination to the existing table await driver.findContent('.test-importer-target-existing-table', /Table1/).click(); await gu.waitForServer(); // Finish import, and verify the import succeeded. await driver.find('.test-modal-confirm').click(); await gu.waitForServer(); // Verify data was imported to Names correctly. assert.deepEqual( await gu.getVisibleGridCells({rowNums: [1, 2, 3, 4, 5], cols: [0, 1, 2]}), [ // Previously existing data in the fixture document 'Alice', '', '', 'Bob', '', '', // Imported data from the CSV file // The second column is references which have been successfully parsed from strings // The third column is a formula equal to the second column to demonstrate the references 'Charlie', 'Alice', 'Table1[1]', 'Dennis', 'Bob', 'Table1[2]', // 'add new' row '', '', '', ] ); // TODO this test relies on the imported data referring to names (Alice,Bob) // already existing in the table before the import, and not being changed by the import }); it('should support importing into any reference columns and show preview', async function() { // Switch to page showing Projects and Tasks. await gu.getPageItem('Projects').click(); await gu.waitForServer(); // wait for table load // Load up a CSV file that matches the structure of the Tasks table. await gu.importFileDialog('./uploads/ImportReferences-Tasks.csv'); // The default import into "New Table" just shows the content of the file. assert.equal(await driver.findWait('.test-importer-preview', 2000).isPresent(), true); assert.deepEqual(await gu.getPreviewContents([0, 1, 2, 3, 4, 5, 6], [1, 2, 3, 4], mapper), [ 'Foo2', 'Clean', '1000', '1,000', '27 Mar 2023', '', '0', 'Bar2', 'Wash', '3000', '2,000', '', 'Projects[2]', '2', 'Baz2', 'Build2', '', '2', '20 Mar 2023', 'Projects[1]', '1', 'Zoo2', 'Clean', '2000', '4,000', '24 Apr 2023', 'Projects[3]', '3', ]); await driver.findContent('.test-importer-target-existing-table', /Tasks/).click(); await gu.waitForServer(); // See that preview works, and cells that should be valid are valid. assert.deepEqual(await gu.getPreviewContents([0, 1, 2, 3, 4], [1, 2, 3, 4], mapper), [ // Label, PName, PIndex, PDate, PRowID 'Foo2', 'Clean', '1,000', '27 Mar 2023', '', 'Bar2', 'Wash', '3,000', '', '!Projects[2]', 'Baz2', '!Build2', '', '!2023-03-20', '!Projects[1]', 'Zoo2', 'Clean', '2,000', '24 Apr 2023', '!Projects[3]', ]); await driver.find('.test-modal-confirm').click(); await gu.waitForServer(); // Verify data was imported to Tasks correctly. assert.deepEqual( await gu.getVisibleGridCells({section: 'TASKS', cols: [0, 1, 2, 3, 4], rowNums: [4, 5, 6, 7, 8, 9], mapper}), [ // Label, PName, PIndex, PDate, PRowID // Previous data in the fixture, in row 4 'Zoo', 'Clean', '2,000', '27 Mar 2023', 'Projects[3]', // New rows (values like "!Project[2]" are invalid, which may be fixed in the future). 'Foo2', 'Clean', '1,000', '27 Mar 2023', '', 'Bar2', 'Wash', '3,000', '', '!Projects[2]', 'Baz2', '!Build2', '', '!2023-03-20', '!Projects[1]', 'Zoo2', 'Clean', '2,000', '24 Apr 2023', '!Projects[3]', // 'Add New' row '', '', '', '', '', ]); await gu.undo(); }); it('should support importing numeric columns as lookups or rowIDs', async function() { // Load up the same CSV file again, with Tasks as the destination. await gu.importFileDialog('./uploads/ImportReferences-Tasks.csv'); await driver.findContent('.test-importer-target-existing-table', /Tasks/).click(); await gu.waitForServer(); await waitForColumnMapping(); // Check that preview works, and cells are valid. assert.deepEqual(await gu.getPreviewContents([0, 1, 2, 3, 4], [1, 2, 3, 4], mapper), [ // Label, PName, PIndex, PDate, PRowID 'Foo2', 'Clean', '1,000', '27 Mar 2023', '', 'Bar2', 'Wash', '3,000', '', '!Projects[2]', 'Baz2', '!Build2', '', '!2023-03-20', '!Projects[1]', 'Zoo2', 'Clean', '2,000', '24 Apr 2023', '!Projects[3]', ]); // Check that dropdown for Label does not include "(as row ID)" entries, but the dropdown for // PName (a reference column) does. await openSourceMenu('Label'); assert.equal(await findColumnMenuItem('PIndex').isPresent(), true); assert.equal(await findColumnMenuItem(/as row ID/).isPresent(), false); await driver.sendKeys(Key.ESCAPE); await openSourceMenu('PName'); assert.equal(await findColumnMenuItem('PIndex').isPresent(), true); assert.equal(await findColumnMenuItem('PIndex (as row ID)').isPresent(), true); await driver.sendKeys(Key.ESCAPE); // Change PIndex column from lookup to row ID. await openSourceMenu('PIndex'); await findColumnMenuItem('PIndex (as row ID)').click(); await gu.waitForServer(); // The values become invalid because there are no such rowIDs. assert.deepEqual(await gu.getPreviewContents([0, 1, 2, 3, 4], [1, 2, 3, 4], mapper), [ // Label, PName, PIndex, PDate, PRowID 'Foo2', 'Clean', '!1000', '27 Mar 2023', '', 'Bar2', 'Wash', '!3000', '', '!Projects[2]', 'Baz2', '!Build2', '', '!2023-03-20', '!Projects[1]', 'Zoo2', 'Clean', '!2000', '24 Apr 2023', '!Projects[3]', ]); // Try a lookup using PIndex2. It is differently formatted, one value is invalid, and one is a // valid row ID (but shouldn't be seen as a rowID for a lookup) await openSourceMenu('PIndex'); await findColumnMenuItem('PIndex2').click(); await gu.waitForServer(); // Note: two PIndex values are different, and two are invalid. assert.deepEqual(await gu.getPreviewContents([0, 1, 2, 3, 4], [1, 2, 3, 4], mapper), [ // Label, PName, PIndex, PDate, PRowID 'Foo2', 'Clean', '1,000', '27 Mar 2023', '', 'Bar2', 'Wash', '2,000', '', '!Projects[2]', 'Baz2', '!Build2', '!2.0', '!2023-03-20', '!Projects[1]', 'Zoo2', 'Clean', '!4000.0', '24 Apr 2023', '!Projects[3]', ]); // Change PRowID column to use "PID (as row ID)". It has 3 valid rowIDs. await openSourceMenu('PRowID'); await findColumnMenuItem('PID (as row ID)').click(); await gu.waitForServer(); // Note: PRowID values are now valid. assert.deepEqual(await gu.getPreviewContents([0, 1, 2, 3, 4], [1, 2, 3, 4], mapper), [ // Label, PName, PIndex, PDate, PRowID 'Foo2', 'Clean', '1,000', '27 Mar 2023', '', 'Bar2', 'Wash', '2,000', '', 'Projects[2]', 'Baz2', '!Build2', '!2.0', '!2023-03-20', 'Projects[1]', 'Zoo2', 'Clean', '!4000.0', '24 Apr 2023', 'Projects[3]', ]); await driver.find('.test-modal-confirm').click(); await gu.waitForServer(); // Verify data was imported to Tasks correctly. assert.deepEqual( await gu.getVisibleGridCells({section: 'TASKS', cols: [0, 1, 2, 3, 4], rowNums: [4, 5, 6, 7, 8, 9], mapper}), [ // Label, PName, PIndex, PDate, PRowID // Previous data in the fixture, in row 4 'Zoo', 'Clean', '2,000', '27 Mar 2023', 'Projects[3]', // New rows; PRowID values are valid. 'Foo2', 'Clean', '1,000', '27 Mar 2023', '', 'Bar2', 'Wash', '2,000', '', 'Projects[2]', 'Baz2', '!Build2', '!2.0', '!2023-03-20', 'Projects[1]', 'Zoo2', 'Clean', '!4000.0', '24 Apr 2023', 'Projects[3]', // 'Add New' row '', '', '', '', '', ]); await gu.undo(); }); }); // mapper for getVisibleGridCells and getPreviewContents to get both text and whether the cell is // invalid (pink). Invalid cells prefixed with "!". async function mapper(el: WebElement) { let text = await el.getText(); if (await el.find(".field_clip").matches(".invalid")) { text = "!" + text; } return text; } function findColumnMenuItem(label: RegExp|string) { return driver.findContent('.test-importer-column-match-menu-item', label); }