gristlabs_grist-core/test/nbrowser/CursorSaving.ts
Dmitry S 527e9670ef (core) Include linking rowIds into remembered cursor position and anchor links.
Summary:
When linking using a Reference List column, there may be multiple source
records that show the same target record. With this change, we remember those
(rather than just pick one that shows the target record).

Test Plan: Added a browser test.

Reviewers: jarek

Reviewed By: jarek

Differential Revision: https://phab.getgrist.com/D4140
2024-01-09 09:50:31 -05:00

224 lines
11 KiB
TypeScript

import {assert, driver} from 'mocha-webdriver';
import * as gu from 'test/nbrowser/gristUtils';
import {cleanupExtraWindows, setupTestSuite} from 'test/nbrowser/testUtils';
describe('CursorSaving', function() {
this.timeout(20000);
cleanupExtraWindows();
const cleanup = setupTestSuite();
const clipboard = gu.getLockableClipboard();
afterEach(() => gu.checkForErrors());
describe('WithRefLists', function() {
before(async function() {
const session = await gu.session().login();
await session.tempDoc(cleanup, "CursorWithRefLists1.grist");
});
it('should remember positions when record is linked from multiple source records', async function() {
// Select Tag 'a' (row 1), and Item 'Apples' (row 1), which has tags 'b' and 'a'.
await clickAndCheck({section: 'Tags', rowNum: 1, col: 0}, 'a');
await clickAndCheck({section: 'Items', rowNum: 1, col: 0}, 'Apple');
await gu.reloadDoc();
assert.deepEqual(await gu.getCursorPosition('Tags'), {rowNum: 1, col: 0});
assert.deepEqual(await gu.getCursorPosition('Items'), {rowNum: 1, col: 0});
assert.equal(await gu.getCardCell('Name', 'Items Card').getText(), 'Apple');
// Now select a different Tag, but the same Item.
await clickAndCheck({section: 'Tags', rowNum: 2, col: 0}, 'b');
await clickAndCheck({section: 'Items', rowNum: 1, col: 0}, 'Apple');
await gu.reloadDoc();
assert.deepEqual(await gu.getCursorPosition('Tags'), {rowNum: 2, col: 0});
assert.deepEqual(await gu.getCursorPosition('Items'), {rowNum: 1, col: 0});
assert.equal(await gu.getCardCell('Name', 'Items Card').getText(), 'Apple');
// Try the third section.
await clickAndCheck({section: 'Items', rowNum: 3, col: 0}, 'Orange');
await clickAndCheckCard({section: 'ITEMS Card', col: 'Name', rowNum: 1}, 'Orange');
await gu.reloadDoc();
assert.deepEqual(await gu.getCursorPosition('Tags'), {rowNum: 2, col: 0});
assert.deepEqual(await gu.getCursorPosition('Items'), {rowNum: 3, col: 0});
assert.equal(await gu.getActiveSectionTitle(), 'ITEMS Card');
assert.equal(await gu.getCardCell('Name', 'ITEMS Card').getText(), 'Orange');
// Try getting to the same card via different selections.
await clickAndCheck({section: 'Tags', rowNum: 1, col: 0}, 'a');
await clickAndCheck({section: 'Items', rowNum: 2, col: 0}, 'Orange');
await clickAndCheckCard({section: 'ITEMS Card', col: 'Name', rowNum: 1}, 'Orange');
await gu.reloadDoc();
assert.deepEqual(await gu.getCursorPosition('Tags'), {rowNum: 1, col: 0});
assert.deepEqual(await gu.getCursorPosition('Items'), {rowNum: 2, col: 0});
assert.equal(await gu.getActiveSectionTitle(), 'ITEMS Card');
assert.equal(await gu.getCardCell('Name', 'ITEMS Card').getText(), 'Orange');
});
it('should remember positions when "new" row is involved', async function() {
// Try a position when when the parent record is on a "new" row.
await clickAndCheck({section: 'Tags', rowNum: 2, col: 0}, 'b');
await clickAndCheck({section: 'Items', rowNum: 4, col: 0}, '');
await clickAndCheckCard({section: 'ITEMS Card', col: 'Tags', rowNum: 1}, '');
await gu.reloadDoc();
assert.deepEqual(await gu.getCursorPosition('Tags'), {rowNum: 2, col: 0});
assert.deepEqual(await gu.getCursorPosition('Items'), {rowNum: 4, col: 0});
assert.equal(await gu.getActiveSectionTitle(), 'ITEMS Card');
assert.equal(await gu.getCardCell('Tags', 'ITEMS Card').getText(), '');
// Try a position when when the grandparent parent record is on a "new" row.
await clickAndCheck({section: 'Tags', rowNum: 4, col: 0}, '');
assert.match(await gu.getSection('Items').find('.disable_viewpane').getText(), /No row selected/);
await clickAndCheckCard({section: 'ITEMS Card', col: 'Tags', rowNum: 1}, '');
await gu.reloadDoc();
assert.deepEqual(await gu.getCursorPosition('Tags'), {rowNum: 4, col: 0});
assert.match(await gu.getSection('Items').find('.disable_viewpane').getText(), /No row selected/);
assert.equal(await gu.getActiveSectionTitle(), 'ITEMS Card');
assert.equal(await gu.getCardCell('Tags', 'ITEMS Card').getText(), '');
});
it('should create anchor links that preserve row positions in linking sources', async function() {
await clickAndCheck({section: 'Tags', rowNum: 1, col: 0}, 'a');
await clickAndCheck({section: 'Items', rowNum: 1, col: 0}, 'Apple');
await gu.openRowMenu(1);
const anchorLinks: string[] = [];
await clipboard.lockAndPerform(async () => { anchorLinks.push(await gu.getAnchor()); });
// Now select a different Tag, but the same Item.
await clickAndCheck({section: 'Tags', rowNum: 2, col: 0}, 'b');
await clickAndCheck({section: 'Items', rowNum: 1, col: 0}, 'Apple');
await clipboard.lockAndPerform(async () => { anchorLinks.push(await gu.getAnchor()); });
// Try the third section.
await clickAndCheck({section: 'Items', rowNum: 3, col: 0}, 'Orange');
await clickAndCheckCard({section: 'ITEMS Card', col: 'Name', rowNum: 1}, 'Orange');
await clipboard.lockAndPerform(async () => { anchorLinks.push(await gu.getAnchor()); });
// A different way to get to the same value in third section.
await clickAndCheck({section: 'Tags', rowNum: 1, col: 0}, 'a');
await clickAndCheck({section: 'Items', rowNum: 2, col: 0}, 'Orange');
await gu.getCardCell('Name', 'ITEMS Card').click();
await clipboard.lockAndPerform(async () => { anchorLinks.push(await gu.getAnchor()); });
// Now go through the anchor links, and make sure each gets us to the expected point.
await driver.get(anchorLinks[0]);
assert.deepEqual(await gu.getCursorPosition('Tags'), {rowNum: 1, col: 0});
assert.deepEqual(await gu.getCursorPosition('Items'), {rowNum: 1, col: 0});
assert.equal(await gu.getCardCell('Name', 'Items Card').getText(), 'Apple');
await driver.get(anchorLinks[1]);
assert.deepEqual(await gu.getCursorPosition('Tags'), {rowNum: 2, col: 0});
assert.deepEqual(await gu.getCursorPosition('Items'), {rowNum: 1, col: 0});
assert.equal(await gu.getCardCell('Name', 'Items Card').getText(), 'Apple');
await driver.get(anchorLinks[2]);
assert.deepEqual(await gu.getCursorPosition('Tags'), {rowNum: 2, col: 0});
assert.deepEqual(await gu.getCursorPosition('Items'), {rowNum: 3, col: 0});
assert.equal(await gu.getActiveSectionTitle(), 'ITEMS Card');
assert.equal(await gu.getCardCell('Name', 'ITEMS Card').getText(), 'Orange');
await driver.get(anchorLinks[3]);
assert.deepEqual(await gu.getCursorPosition('Tags'), {rowNum: 1, col: 0});
assert.deepEqual(await gu.getCursorPosition('Items'), {rowNum: 2, col: 0});
assert.equal(await gu.getActiveSectionTitle(), 'ITEMS Card');
assert.equal(await gu.getCardCell('Name', 'ITEMS Card').getText(), 'Orange');
});
it('should handle anchor links when "new" row is involved', async function() {
const anchorLinks: string[] = [];
// Try a position when when the parent record is on a "new" row.
await clickAndCheck({section: 'Tags', rowNum: 2, col: 0}, 'b');
await clickAndCheck({section: 'Items', rowNum: 4, col: 0}, '');
await clickAndCheckCard({section: 'ITEMS Card', col: 'Tags', rowNum: 1}, '');
await clipboard.lockAndPerform(async () => { anchorLinks.push(await gu.getAnchor()); });
// Try a position when when the grandparent parent record is on a "new" row.
await clickAndCheck({section: 'Tags', rowNum: 4, col: 0}, '');
assert.match(await gu.getSection('Items').find('.disable_viewpane').getText(), /No row selected/);
await clickAndCheckCard({section: 'ITEMS Card', col: 'Tags', rowNum: 1}, '');
await clipboard.lockAndPerform(async () => { anchorLinks.push(await gu.getAnchor()); });
await driver.get(anchorLinks[0]);
assert.deepEqual(await gu.getCursorPosition('Tags'), {rowNum: 2, col: 0});
assert.deepEqual(await gu.getCursorPosition('Items'), {rowNum: 4, col: 0});
assert.equal(await gu.getActiveSectionTitle(), 'ITEMS Card');
assert.equal(await gu.getCardCell('Tags', 'ITEMS Card').getText(), '');
await driver.get(anchorLinks[1]);
assert.deepEqual(await gu.getCursorPosition('Tags'), {rowNum: 4, col: 0});
assert.match(await gu.getSection('Items').find('.disable_viewpane').getText(), /No row selected/);
assert.equal(await gu.getActiveSectionTitle(), 'ITEMS Card');
assert.equal(await gu.getCardCell('Tags', 'ITEMS Card').getText(), '');
});
});
describe('WithRefs', function() {
// This is a similar test to the above, but without RefLists. In particular it checks that
// when a cursor is in the "new" row, enough is remembered to restore positions.
before(async function() {
const session = await gu.session().login();
const doc = await session.tempDoc(cleanup, "World.grist", {load: false});
await session.loadDoc(`/doc/${doc.id}/p/5`, {wait: true});
});
it('should remember row positions in linked sections', async function() {
// Select a country and a city within it.
await clickAndCheck({section: 'Country', rowNum: 2, col: 0}, 'AFG');
await clickAndCheck({section: 'City', rowNum: 4, col: 1}, 'Balkh');
await gu.reloadDoc();
assert.deepEqual(await gu.getCursorPosition('Country'), {rowNum: 2, col: 0});
assert.deepEqual(await gu.getCursorPosition('City'), {rowNum: 4, col: 1});
// Now select a country, and the "new" row in the linked City widget.
await clickAndCheck({section: 'Country', rowNum: 3, col: 0}, 'AGO');
await clickAndCheck({section: 'City', rowNum: 6, col: 1}, '');
await gu.reloadDoc();
assert.deepEqual(await gu.getCursorPosition('Country'), {rowNum: 3, col: 0});
assert.deepEqual(await gu.getCursorPosition('City'), {rowNum: 6, col: 1});
});
it('should create anchor links that preserve row positions in linked sections', async function() {
const anchorLinks: string[] = [];
// Select a country and a city within it.
await clickAndCheck({section: 'Country', rowNum: 2, col: 0}, 'AFG');
await clickAndCheck({section: 'City', rowNum: 4, col: 1}, 'Balkh');
await clipboard.lockAndPerform(async () => { anchorLinks.push(await gu.getAnchor()); });
// Now select a country, and the "new" row in the linked City widget.
await clickAndCheck({section: 'Country', rowNum: 3, col: 0}, 'AGO');
await clickAndCheck({section: 'City', rowNum: 6, col: 1}, '');
await clipboard.lockAndPerform(async () => { anchorLinks.push(await gu.getAnchor()); });
await driver.get(anchorLinks[0]);
assert.deepEqual(await gu.getCursorPosition('Country'), {rowNum: 2, col: 0});
assert.deepEqual(await gu.getCursorPosition('City'), {rowNum: 4, col: 1});
await driver.get(anchorLinks[1]);
assert.deepEqual(await gu.getCursorPosition('Country'), {rowNum: 3, col: 0});
assert.deepEqual(await gu.getCursorPosition('City'), {rowNum: 6, col: 1});
});
});
});
async function clickAndCheck(options: gu.ICellSelect, expectedValue: string) {
const cell = gu.getCell(options);
await cell.click();
assert.equal(await cell.getText(), expectedValue);
}
async function clickAndCheckCard(options: gu.ICellSelect, expectedValue: string) {
const cell = gu.getDetailCell(options);
await cell.click();
assert.equal(await cell.getText(), expectedValue);
}