mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
863 lines
35 KiB
TypeScript
863 lines
35 KiB
TypeScript
import {assert, driver, Key, stackWrapFunc} from 'mocha-webdriver';
|
|
import * as gu from 'test/nbrowser/gristUtils';
|
|
import {server, setupTestSuite} from 'test/nbrowser/testUtils';
|
|
import {Session} from 'test/nbrowser/gristUtils';
|
|
|
|
describe('ReferenceList', function() {
|
|
this.timeout(20000);
|
|
setupTestSuite();
|
|
let session: Session;
|
|
const cleanup = setupTestSuite({team: true});
|
|
|
|
before(async function() {
|
|
session = await gu.session().teamSite.login();
|
|
await session.tempDoc(cleanup, 'Favorite_Films.grist');
|
|
|
|
await gu.toggleSidePanel('right');
|
|
await driver.find('.test-config-data').click();
|
|
});
|
|
|
|
describe('transforms', function() {
|
|
afterEach(() => gu.checkForErrors());
|
|
|
|
it('should correctly transform references to reference lists', async function() {
|
|
// Open the Friends page.
|
|
await driver.findContentWait('.test-treeview-itemHeader', /Friends/, 2000).click();
|
|
await gu.waitForDocToLoad();
|
|
|
|
// Change the column type of Favorite Film to Reference List.
|
|
await gu.getCell({col: 'Favorite Film', rowNum: 1}).doClick();
|
|
await gu.setType(/Reference List/);
|
|
|
|
// Check that the column preview shows valid reference lists.
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6, 7]),
|
|
[
|
|
'Forrest Gump',
|
|
'Toy Story',
|
|
'Avatar',
|
|
'The Dark Knight',
|
|
'Forrest Gump',
|
|
'Alien',
|
|
''
|
|
]
|
|
);
|
|
|
|
// Apply the conversion.
|
|
await driver.findContent('.type_transform_prompt button', /Apply/).click();
|
|
await gu.waitForServer();
|
|
|
|
// Check that Favorite Film now contains reference lists of length 1.
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6, 7]),
|
|
[
|
|
'Forrest Gump',
|
|
'Toy Story',
|
|
'Avatar',
|
|
'The Dark Knight',
|
|
'Forrest Gump',
|
|
'Alien',
|
|
''
|
|
]
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('rendering', function() {
|
|
afterEach(() => gu.checkForErrors());
|
|
|
|
it('should reflect the current values from the referenced column', async function() {
|
|
// Open the All page.
|
|
await driver.findContentWait('.test-treeview-itemHeader', /All/, 2000).click();
|
|
await gu.waitForDocToLoad();
|
|
|
|
// Add additional favorite films to a few rows in Friends.
|
|
await gu.getCell('Favorite Film', 1, 'Friends record').doClick();
|
|
await gu.sendKeys(Key.ENTER, 'Alien', Key.ENTER, Key.ENTER);
|
|
await gu.sendKeys(Key.ENTER, 'Avatar', Key.ENTER, 'The Avengers', Key.ENTER, Key.ENTER);
|
|
await gu.sendKeys(Key.ARROW_DOWN, Key.ENTER, 'The Avengers', Key.ENTER, Key.ENTER);
|
|
|
|
// Check that the cells are rendered correctly.
|
|
assert.deepEqual(await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6]),
|
|
[
|
|
'Forrest Gump\nAlien',
|
|
'Toy Story\nAvatar\nThe Avengers',
|
|
'Avatar',
|
|
'The Dark Knight\nThe Avengers',
|
|
'Forrest Gump',
|
|
'Alien'
|
|
]
|
|
);
|
|
|
|
// Change a few of the film titles.
|
|
await gu.getCell('Title', 1, 'Films record').doClick();
|
|
await gu.sendKeys('Toy Story 2', Key.ENTER);
|
|
await gu.sendKeys(Key.ARROW_DOWN, 'Aliens', Key.ENTER);
|
|
await gu.sendKeys(Key.ARROW_DOWN, 'The Dark Knight Rises', Key.ENTER);
|
|
|
|
// Check that the Favorite Film column reflects the new titles.
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6], 'Friends record'),
|
|
[
|
|
'Forrest Gump\nAliens',
|
|
'Toy Story 2\nAvatar\nThe Avengers',
|
|
'Avatar',
|
|
'The Dark Knight Rises\nThe Avengers',
|
|
'Forrest Gump',
|
|
'Aliens'
|
|
]
|
|
);
|
|
});
|
|
|
|
it(`should show '[Blank]' if the referenced item is blank`, async function() {
|
|
// Clear the cell in Films record containing Avatar.
|
|
await gu.getCell('Title', 4, 'Films record').doClick();
|
|
await gu.sendKeys(Key.BACK_SPACE);
|
|
await gu.waitForServer();
|
|
|
|
// Check that all references to Avatar now show '[Blank]'.
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6], 'Friends record'),
|
|
[
|
|
'Forrest Gump\nAliens',
|
|
'Toy Story 2\n[Blank]\nThe Avengers',
|
|
'[Blank]',
|
|
'The Dark Knight Rises\nThe Avengers',
|
|
'Forrest Gump',
|
|
'Aliens'
|
|
]
|
|
);
|
|
|
|
// Check that a '[Blank]' token is shown when the reference list editor is open.
|
|
await gu.getCell('Favorite Film', 2, 'Friends record').doClick();
|
|
await gu.sendKeys(Key.ENTER);
|
|
assert.deepEqual(
|
|
await driver.findAll('.cell_editor .test-tokenfield .test-tokenfield-token', el => el.getText()),
|
|
['Toy Story 2', '[Blank]', 'The Avengers']
|
|
);
|
|
await gu.sendKeys(Key.ESCAPE);
|
|
|
|
// Undo, and check that it shows Avatar again.
|
|
await gu.undo();
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6], 'Friends record'),
|
|
[
|
|
'Forrest Gump\nAliens',
|
|
'Toy Story 2\nAvatar\nThe Avengers',
|
|
'Avatar',
|
|
'The Dark Knight Rises\nThe Avengers',
|
|
'Forrest Gump',
|
|
'Aliens'
|
|
]
|
|
);
|
|
|
|
// Now delete the row containing Avatar.
|
|
await gu.getCell('Title', 4, 'Films record').doClick();
|
|
await gu.sendKeys(Key.chord(await gu.modKey(), '-'));
|
|
await gu.waitForServer();
|
|
|
|
// Check that all references to Avatar are deleted.
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6], 'Friends record'),
|
|
[
|
|
'Forrest Gump\nAliens',
|
|
'Toy Story 2\nThe Avengers',
|
|
'',
|
|
'The Dark Knight Rises\nThe Avengers',
|
|
'Forrest Gump',
|
|
'Aliens'
|
|
]
|
|
);
|
|
|
|
await gu.undo();
|
|
});
|
|
|
|
it('should still work after renaming visible column', async function() {
|
|
// Check that we have a Ref:Films column displaying Title.
|
|
await gu.getCell({section: 'Friends record', col: 'Favorite Film', rowNum: 2}).doClick();
|
|
assert.equal(await driver.find('.test-fbuilder-ref-table-select .test-select-row').getText(), 'Films');
|
|
assert.equal(await driver.find('.test-fbuilder-ref-col-select .test-select-row').getText(), 'Title');
|
|
|
|
// Rename the Title column in Films, to TitleX.
|
|
// In browser tests, first record is hidden, we need to scroll first.
|
|
await gu.selectSectionByTitle('Films record');
|
|
await gu.scrollActiveView(0, -100);
|
|
await gu.getCell({section: 'Films record', col: 'Title', rowNum: 1}).doClick();
|
|
await driver.find('.test-field-label').click();
|
|
await gu.sendKeys(await gu.selectAllKey(), 'TitleX', Key.ENTER);
|
|
await gu.waitForServer();
|
|
|
|
// Check that the Ref:Films column shows TitleX and is still correct.
|
|
await gu.getCell({section: 'Friends record', col: 'Favorite Film', rowNum: 2}).doClick();
|
|
await driver.find('.test-fbuilder-ref-table-select').click();
|
|
assert.equal(await driver.find('.test-fbuilder-ref-table-select .test-select-row').getText(), 'Films');
|
|
assert.equal(await driver.find('.test-fbuilder-ref-col-select .test-select-row').getText(), 'TitleX');
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6]),
|
|
[
|
|
'Forrest Gump\nAliens',
|
|
'Toy Story 2\nAvatar\nThe Avengers',
|
|
'Avatar',
|
|
'The Dark Knight Rises\nThe Avengers',
|
|
'Forrest Gump',
|
|
'Aliens'
|
|
]
|
|
);
|
|
|
|
// Undo and verify again.
|
|
await gu.undo();
|
|
await gu.getCell({section: 'Friends record', col: 'Favorite Film', rowNum: 2}).doClick();
|
|
assert.equal(await driver.find('.test-fbuilder-ref-col-select .test-select-row').getText(), 'Title');
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6]),
|
|
[
|
|
'Forrest Gump\nAliens',
|
|
'Toy Story 2\nAvatar\nThe Avengers',
|
|
'Avatar',
|
|
'The Dark Knight Rises\nThe Avengers',
|
|
'Forrest Gump',
|
|
'Aliens'
|
|
]
|
|
);
|
|
});
|
|
|
|
it('should switch to rowId if the selected visible column is deleted', async function() {
|
|
// Delete the Title column from Films.
|
|
await gu.getCell({section: 'Films record', col: 'Title', rowNum: 1}).doClick();
|
|
await gu.sendKeys(Key.chord(Key.ALT, '-'));
|
|
await gu.waitForServer();
|
|
|
|
// Check that Favorite Film switched to showing RowID.
|
|
await gu.getCell({section: 'Friends record', col: 'Favorite Film', rowNum: 2}).doClick();
|
|
assert.equal(await driver.find('.test-fbuilder-ref-table-select .test-select-row').getText(), 'Films');
|
|
assert.equal(await driver.find('.test-fbuilder-ref-col-select .test-select-row').getText(), 'Row ID');
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6]),
|
|
[
|
|
'Films[2]\nFilms[3]',
|
|
'Films[1]\nFilms[4]\nFilms[6]',
|
|
'Films[4]',
|
|
'Films[5]\nFilms[6]',
|
|
'Films[2]',
|
|
'Films[3]'
|
|
]
|
|
);
|
|
|
|
await gu.undo();
|
|
});
|
|
|
|
it('should render Row ID values as TableId[RowId]', async function() {
|
|
await driver.findContentWait('.test-treeview-itemHeader', /Friends/, 2000).click();
|
|
await gu.waitForDocToLoad();
|
|
|
|
// Create a new Reference List column.
|
|
await driver.find('.test-right-tab-field').click();
|
|
await driver.find('.mod-add-column').click();
|
|
await gu.waitForServer();
|
|
await gu.setType(/Reference List/);
|
|
await gu.waitForServer();
|
|
|
|
// Populate the first few rows of the new column with some references.
|
|
await gu.getCell({rowNum: 1, col: 'A'}).click();
|
|
await driver.sendKeys('1', Key.ENTER, '2', Key.ENTER, Key.ENTER);
|
|
await driver.sendKeys('2', Key.ENTER, Key.ENTER);
|
|
await driver.sendKeys('3', Key.ENTER, '4', Key.ENTER, '5', Key.ENTER, Key.ENTER);
|
|
|
|
// Check that the cells render their tokens as TableId[RowId].
|
|
assert.deepEqual(await gu.getVisibleGridCells(3, [1, 2, 3, 4, 5, 6]),
|
|
['Friends[1]\nFriends[2]', 'Friends[2]', 'Friends[3]\nFriends[4]\nFriends[5]', '', '', '']);
|
|
|
|
// Check that switching Shown Column to Name works correctly.
|
|
await driver.find('.test-fbuilder-ref-col-select').click();
|
|
await driver.findContent('.test-select-row', /Name/).click();
|
|
await gu.waitForServer();
|
|
assert.deepEqual(await gu.getVisibleGridCells(3, [1, 2, 3, 4, 5, 6]),
|
|
['Roger\nTom', 'Tom', 'Sydney\nBill\nEvan', '', '', '']);
|
|
|
|
// Add a new reference.
|
|
await gu.getCell(3, 5).click();
|
|
await driver.sendKeys('Roger');
|
|
await driver.sendKeys(Key.ENTER, Key.ENTER);
|
|
await gu.waitForServer();
|
|
|
|
// Check that switching between Row ID and Name still works correctly.
|
|
assert.deepEqual(await gu.getVisibleGridCells(3, [1, 2, 3, 4, 5, 6]),
|
|
['Roger\nTom', 'Tom', 'Sydney\nBill\nEvan', '', 'Roger', '']);
|
|
await driver.find('.test-fbuilder-ref-col-select').click();
|
|
await driver.findContent('.test-select-row', /Row ID/).click();
|
|
await gu.waitForServer();
|
|
assert.deepEqual(await gu.getVisibleGridCells(3, [1, 2, 3, 4, 5, 6]),
|
|
['Friends[1]\nFriends[2]', 'Friends[2]', 'Friends[3]\nFriends[4]\nFriends[5]', '', 'Friends[1]', '']);
|
|
await driver.find('.test-fbuilder-ref-col-select').click();
|
|
await driver.findContent('.test-select-row', /Name/).click();
|
|
await gu.waitForServer();
|
|
assert.deepEqual(await gu.getVisibleGridCells(3, [1, 2, 3, 4, 5, 6]),
|
|
['Roger\nTom', 'Tom', 'Sydney\nBill\nEvan', '', 'Roger', '']);
|
|
|
|
await gu.undo();
|
|
});
|
|
|
|
it('should allow entering numeric id before target table is loaded', async function() {
|
|
// Refresh the document.
|
|
await driver.navigate().refresh();
|
|
await gu.waitForDocToLoad();
|
|
|
|
// Now pause the server.
|
|
const cell = gu.getCell({col: 'A', rowNum: 1});
|
|
await server.pauseUntil(async () => {
|
|
assert.equal(await cell.getText(), 'Friends[1]\nFriends[2]');
|
|
await cell.click();
|
|
await gu.sendKeys('5');
|
|
// Check that the autocomplete has no items yet.
|
|
assert.isEmpty(await driver.findAll('.test-autocomplete .test-ref-editor-new-item'));
|
|
await gu.sendKeys(Key.ENTER, Key.ENTER);
|
|
});
|
|
await gu.waitForServer();
|
|
assert.equal(await cell.getText(), 'Friends[5]');
|
|
|
|
await gu.undo();
|
|
assert.equal(await cell.getText(), 'Friends[1]\nFriends[2]');
|
|
|
|
// Once server is responsive, a valid value should not offer a "new item".
|
|
await cell.click();
|
|
await gu.sendKeys('5');
|
|
await driver.findWait('.test-ref-editor-item', 500);
|
|
assert.isFalse(await driver.find('.test-ref-editor-new-item').isPresent());
|
|
await gu.sendKeys(Key.ENTER, Key.ENTER);
|
|
await gu.waitForServer();
|
|
assert.equal(await cell.getText(), 'Friends[5]');
|
|
});
|
|
});
|
|
|
|
describe('sorting', function() {
|
|
afterEach(() => gu.checkForErrors());
|
|
|
|
it('should sort by the display values of the referenced column', async function() {
|
|
this.timeout(10000);
|
|
await driver.findContentWait('.test-treeview-itemHeader', /All/, 2000).click();
|
|
await gu.waitForDocToLoad();
|
|
await gu.getCell('Favorite Film', 1, 'Friends record').doClick();
|
|
|
|
await driver.find('.test-right-tab-pagewidget').click();
|
|
await driver.find('.test-config-sortAndFilter').click();
|
|
|
|
// Sort the Favorite Film column.
|
|
await driver.find('.test-vconfigtab-sort-add').click();
|
|
await driver.findContent('.test-vconfigtab-sort-add-menu-row', /Favorite_Film/).click();
|
|
await driver.find('.test-vconfigtab-sort-save').click();
|
|
|
|
// Check that the records are sorted by display value.
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6], 'Friends record'),
|
|
[
|
|
'Aliens',
|
|
'Avatar',
|
|
'Forrest Gump',
|
|
'Forrest Gump\nAliens',
|
|
'The Dark Knight Rises\nThe Avengers',
|
|
'Toy Story 2\nAvatar\nThe Avengers'
|
|
]
|
|
);
|
|
});
|
|
|
|
it("should update sort when display column is changed", async function() {
|
|
// Change a film title to cause the sort order to change.
|
|
await gu.getCell('Title', 5, 'Films record').doClick();
|
|
await gu.sendKeys('Batman Begins', Key.ENTER);
|
|
await gu.waitForServer();
|
|
|
|
// Check that the updated sort order is correct.
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6], 'Friends record'),
|
|
[
|
|
'Aliens',
|
|
'Avatar',
|
|
'Batman Begins\nThe Avengers',
|
|
'Forrest Gump',
|
|
'Forrest Gump\nAliens',
|
|
'Toy Story 2\nAvatar\nThe Avengers'
|
|
]
|
|
);
|
|
|
|
// Clear a film title to cause the sort order to change.
|
|
await gu.getCell('Title', 2, 'Films record').doClick();
|
|
await gu.sendKeys(Key.BACK_SPACE);
|
|
await gu.waitForServer();
|
|
|
|
// Check that the updated sort order is correct.
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6], 'Friends record'),
|
|
[
|
|
'[Blank]',
|
|
'[Blank]\nAliens',
|
|
'Aliens',
|
|
'Avatar',
|
|
'Batman Begins\nThe Avengers',
|
|
'Toy Story 2\nAvatar\nThe Avengers'
|
|
]
|
|
);
|
|
|
|
// Clear a film reference to cause the sort order to change.
|
|
await gu.getCell('Favorite Film', 4, 'Friends record').doClick();
|
|
await gu.sendKeys(Key.BACK_SPACE);
|
|
await gu.waitForServer();
|
|
|
|
// Check that the updated sort order is correct.
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6], 'Friends record'),
|
|
[
|
|
'',
|
|
'[Blank]',
|
|
'[Blank]\nAliens',
|
|
'Aliens',
|
|
'Batman Begins\nThe Avengers',
|
|
'Toy Story 2\nAvatar\nThe Avengers'
|
|
]
|
|
);
|
|
});
|
|
|
|
it("should sort consistently when column contains AltText", async function() {
|
|
// Enter an invalid reference in Favorite Film.
|
|
await gu.getCell('Favorite Film', 4, 'Friends record').doClick();
|
|
await gu.sendKeys('Aliens 4', Key.ENTER, Key.ENTER);
|
|
await gu.waitForServer();
|
|
|
|
// Check that the updated sort order is correct.
|
|
// Accept '[u\'Aliens 4\']' as a py2 variant of '[\'Aliens 4\']'
|
|
const variant = await gu.getCell('Favorite Film', 1, 'Friends record').getText();
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6], 'Friends record'),
|
|
[
|
|
variant.startsWith('[u') ? '[u\'Aliens 4\']' : '[\'Aliens 4\']',
|
|
'',
|
|
'[Blank]',
|
|
'[Blank]\nAliens',
|
|
'Batman Begins\nThe Avengers',
|
|
'Toy Story 2\nAvatar\nThe Avengers'
|
|
]
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('autocomplete', function() {
|
|
const getACOptions = stackWrapFunc(async (limit?: number) => {
|
|
await driver.findWait('.test-ref-editor-item', 1000);
|
|
return (await driver.findAll('.test-ref-editor-item', el => el.getText())).slice(0, limit);
|
|
});
|
|
|
|
before(async function() {
|
|
await session.tempDoc(cleanup, 'Ref-List-AC-Test.grist');
|
|
await gu.toggleSidePanel('right', 'close');
|
|
});
|
|
|
|
afterEach(() => gu.checkForErrors());
|
|
|
|
it('should render first items when opening empty cell', async function() {
|
|
await driver.sendKeys(Key.HOME);
|
|
|
|
let cell = await gu.getCell({section: 'References', col: 'Colors', rowNum: 4}).doClick();
|
|
assert.equal(await cell.getText(), '');
|
|
await driver.sendKeys(Key.ENTER);
|
|
// Check the first few items.
|
|
assert.deepEqual(await getACOptions(3), ["Alice Blue", "Añil", "Aqua"]);
|
|
// No item is selected.
|
|
assert.equal(await driver.find('.test-ref-editor-item.selected').isPresent(), false);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
|
|
cell = await gu.getCell({section: 'References', col: 'Schools', rowNum: 6}).doClick();
|
|
assert.equal(await cell.getText(), '');
|
|
await driver.sendKeys(Key.ENTER);
|
|
// Check the first few items; should be sorted alphabetically.
|
|
assert.deepEqual(await getACOptions(3),
|
|
["2 SCHOOL", "4 SCHOOL", "47 AMER SIGN LANG & ENG LOWER "]);
|
|
// No item is selected.
|
|
assert.equal(await driver.find('.test-ref-editor-item.selected').isPresent(), false);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
});
|
|
|
|
it('should save correct item on click', async function() {
|
|
await driver.sendKeys(Key.HOME);
|
|
|
|
// Edit a cell by double-clicking.
|
|
let cell = await gu.getCell({section: 'References', col: 'Colors', rowNum: 2}).doClick();
|
|
await driver.withActions(a => a.doubleClick(cell));
|
|
|
|
// Scroll to another item and click it.
|
|
await gu.sendKeys('ro');
|
|
let item = driver.findContent('.test-ref-editor-item', 'Rosy Brown');
|
|
await gu.scrollIntoView(item);
|
|
await item.click();
|
|
|
|
// It should get added; and undo should revert adding it.
|
|
assert.deepEqual(
|
|
await driver.findAll('.cell_editor .test-tokenfield .test-tokenfield-token', el => el.getText()),
|
|
['Red', 'Rosy Brown']
|
|
);
|
|
await gu.sendKeys(Key.chord(await gu.modKey(), 'z'));
|
|
assert.deepEqual(
|
|
await driver.findAll('.cell_editor .test-tokenfield .test-tokenfield-token', el => el.getText()),
|
|
['Red']
|
|
);
|
|
await gu.sendKeys(Key.ESCAPE);
|
|
assert.equal(await cell.getText(), 'Red');
|
|
|
|
// Edit another cell by starting to type.
|
|
cell = await gu.getCell({section: 'References', col: 'Colors', rowNum: 4}).doClick();
|
|
await driver.sendKeys("gr");
|
|
await driver.findWait('.test-ref-editor-item', 1000);
|
|
item = driver.findContent('.test-ref-editor-item', 'Medium Sea Green');
|
|
await gu.scrollIntoView(item);
|
|
await item.click();
|
|
await gu.sendKeys(Key.ENTER);
|
|
|
|
// It should get saved; and undo should restore the previous value.
|
|
await gu.waitForServer();
|
|
assert.equal(await cell.getText(), 'Medium Sea Green');
|
|
await gu.undo();
|
|
assert.equal(await cell.getText(), '');
|
|
});
|
|
|
|
it('should save correct item after selecting with arrow keys', async function() {
|
|
// Same as the previous test, but instead of clicking items, select item using arrow keys.
|
|
|
|
// Edit a cell by double-clicking.
|
|
let cell = await gu.getCell({section: 'References', col: 'Colors', rowNum: 2}).doClick();
|
|
await driver.withActions(a => a.doubleClick(cell));
|
|
|
|
// Move to another item and hit Enter
|
|
await gu.sendKeys('pa');
|
|
await driver.sendKeys(Key.DOWN, Key.DOWN, Key.DOWN);
|
|
assert.equal(await driver.findWait('.test-ref-editor-item.selected', 1000).getText(), 'Pale Violet Red');
|
|
await driver.sendKeys(Key.ENTER);
|
|
|
|
// It should get added; and undo should revert adding it.
|
|
assert.deepEqual(
|
|
await driver.findAll('.cell_editor .test-tokenfield .test-tokenfield-token', el => el.getText()),
|
|
['Red', 'Pale Violet Red']
|
|
);
|
|
await gu.sendKeys(Key.chord(await gu.modKey(), 'z'));
|
|
assert.deepEqual(
|
|
await driver.findAll('.cell_editor .test-tokenfield .test-tokenfield-token', el => el.getText()),
|
|
['Red']
|
|
);
|
|
await gu.sendKeys(Key.ESCAPE);
|
|
assert.equal(await cell.getText(), 'Red');
|
|
|
|
// Edit another cell by starting to type.
|
|
cell = await gu.getCell({section: 'References', col: 'Colors', rowNum: 4}).doClick();
|
|
await driver.sendKeys("gr");
|
|
await driver.findWait('.test-ref-editor-item', 1000);
|
|
await driver.sendKeys(Key.UP, Key.UP, Key.UP, Key.UP, Key.UP);
|
|
assert.equal(await driver.findWait('.test-ref-editor-item.selected', 1000).getText(), 'Chocolate');
|
|
await driver.sendKeys(Key.ENTER, Key.ENTER);
|
|
|
|
// It should get saved; and undo should restore the previous value.
|
|
await gu.waitForServer();
|
|
assert.equal(await cell.getText(), 'Chocolate');
|
|
await gu.undo();
|
|
assert.equal(await cell.getText(), '');
|
|
});
|
|
|
|
it('should return to text-as-typed when nothing is selected', async function() {
|
|
const cell = await gu.getCell({section: 'References', col: 'Colors', rowNum: 2}).doClick();
|
|
await driver.sendKeys("da");
|
|
assert.deepEqual(await getACOptions(2), ["Dark Blue", "Dark Cyan"]);
|
|
|
|
// Check that the first item is highlighted by default.
|
|
assert.equal(await driver.find('.cell_editor .test-tokenfield .test-tokenfield-input').value(), 'da');
|
|
assert.equal(await driver.find('.test-ref-editor-item.selected').getText(), 'Dark Blue');
|
|
|
|
// Select second item. Both the textbox and the dropdown show the selection.
|
|
await driver.sendKeys(Key.DOWN);
|
|
assert.equal(await driver.find('.cell_editor .test-tokenfield .test-tokenfield-input').value(), 'Dark Cyan');
|
|
assert.equal(await driver.find('.test-ref-editor-item.selected').getText(), 'Dark Cyan');
|
|
|
|
// Move back to no-selection state.
|
|
await driver.sendKeys(Key.UP, Key.UP);
|
|
assert.equal(await driver.find('.cell_editor .test-tokenfield .test-tokenfield-input').value(), 'da');
|
|
assert.equal(await driver.find('.test-ref-editor-item.selected').isPresent(), false);
|
|
|
|
// Mouse over an item.
|
|
await driver.findContent('.test-ref-editor-item', /Dark Gray/).mouseMove();
|
|
assert.equal(await driver.find('.cell_editor .test-tokenfield .test-tokenfield-input').value(), 'Dark Gray');
|
|
assert.equal(await driver.find('.test-ref-editor-item.selected').getText(), 'Dark Gray');
|
|
|
|
// Mouse back out of the dropdown
|
|
await driver.find('.cell_editor .test-tokenfield .test-tokenfield-input').mouseMove();
|
|
assert.equal(await driver.find('.cell_editor .test-tokenfield .test-tokenfield-input').value(), 'da');
|
|
assert.equal(await driver.find('.test-ref-editor-item.selected').isPresent(), false);
|
|
|
|
// Click away and check the cell is now empty since no reference items were added.
|
|
await gu.getCell({section: 'References', col: 'Colors', rowNum: 1}).doClick();
|
|
await gu.waitForServer();
|
|
assert.equal(await cell.getText(), "");
|
|
assert.equal(await cell.find('.field_clip').matches('.invalid'), false);
|
|
|
|
await gu.undo();
|
|
assert.equal(await cell.getText(), "Red");
|
|
assert.equal(await cell.find('.field_clip').matches('.invalid'), false);
|
|
});
|
|
|
|
it('should save text as typed when nothing is selected', async function() {
|
|
const cell = await gu.getCell({section: 'References', col: 'Colors', rowNum: 1}).doClick();
|
|
await driver.sendKeys("lavender ", Key.ENTER, Key.ENTER);
|
|
await gu.waitForServer();
|
|
assert.equal(await cell.getText(), "Lavender");
|
|
await gu.undo();
|
|
assert.equal(await cell.getText(), "Dark Slate Blue");
|
|
});
|
|
|
|
it('should offer an add-new option when no good match', async function() {
|
|
const cell = await gu.getCell({section: 'References', col: 'Colors', rowNum: 2}).doClick();
|
|
await driver.sendKeys("pinkish");
|
|
// There are inexact matches.
|
|
assert.deepEqual(await getACOptions(3),
|
|
["Pink", "Deep Pink", "Hot Pink"]);
|
|
// Nothing is selected, and the "add new" item is present.
|
|
assert.equal(await driver.find('.test-ref-editor-item.selected').isPresent(), false);
|
|
assert.equal(await driver.find('.test-ref-editor-new-item').getText(), "pinkish");
|
|
|
|
// Click the "add new" item. The new value should be added, and should not appear invalid.
|
|
await driver.find('.test-ref-editor-new-item').click();
|
|
assert.deepEqual(
|
|
await driver.findAll('.cell_editor .test-tokenfield .test-tokenfield-token', el => el.getText()),
|
|
['pinkish']
|
|
);
|
|
assert.deepEqual(
|
|
await driver.findAll(
|
|
'.cell_editor .test-tokenfield .test-tokenfield-token',
|
|
el => el.matches('[class*=-invalid]')
|
|
),
|
|
[false]
|
|
);
|
|
|
|
// Add another new item (with the keyboard), and check that it also appears correctly.
|
|
await driver.sendKeys("almost pink", Key.ARROW_UP, Key.ENTER);
|
|
assert.deepEqual(
|
|
await driver.findAll('.cell_editor .test-tokenfield .test-tokenfield-token', el => el.getText()),
|
|
['pinkish', 'almost pink']
|
|
);
|
|
assert.deepEqual(
|
|
await driver.findAll(
|
|
'.cell_editor .test-tokenfield .test-tokenfield-token',
|
|
el => el.matches('[class*=-invalid]')
|
|
),
|
|
[false, false]
|
|
);
|
|
|
|
// Save the changes to the cell.
|
|
await gu.sendKeys(Key.ENTER);
|
|
await gu.waitForServer();
|
|
assert.equal(await cell.getText(), "pinkish\nalmost pink");
|
|
|
|
// Check that the referenced table now has "pinkish" and "almost pink".
|
|
await driver.findContentWait('.test-treeview-itemHeader', /Colors/, 2000).click();
|
|
await gu.waitForDocToLoad();
|
|
await gu.sendKeys(Key.chord(await gu.modKey(), Key.ARROW_DOWN));
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('Color Name', [146, 147]),
|
|
['pinkish', 'almost pink']
|
|
);
|
|
assert.deepEqual(
|
|
await gu.getVisibleGridCells('C2', [146, 147]),
|
|
['pinkish', 'almost pink']
|
|
);
|
|
|
|
// Requires 2 undos, because adding the "pinkish" and "almost pink" records is a separate action. TODO these
|
|
// actions should be bundled.
|
|
await gu.undo(2);
|
|
assert.equal(await gu.getCell({section: 'References', col: 'Colors', rowNum: 2}).getText(), 'Red');
|
|
});
|
|
|
|
it('should not offer an add-new option when target is a formula', async function() {
|
|
// Click on an alt-text cell.
|
|
const cell = await gu.getCell({section: 'References', col: 'Colors', rowNum: 3}).doClick();
|
|
assert.equal(await cell.getText(), "hello");
|
|
assert.equal(await cell.find('.field_clip').matches('.invalid'), true);
|
|
|
|
await driver.sendKeys(Key.ENTER, 'hello');
|
|
assert.equal(await driver.find('.test-ref-editor-new-item').getText(), "hello");
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
|
|
// Change the visible column to the formula column "C2".
|
|
await gu.toggleSidePanel('right', 'open');
|
|
await driver.find('.test-right-tab-field').click();
|
|
await driver.find('.test-fbuilder-ref-col-select').click();
|
|
await driver.findContent('.test-select-row', /C2/).click();
|
|
await gu.waitForServer();
|
|
|
|
// Check that for the same cell, the dropdown no longer has an "add new" option.
|
|
await cell.click();
|
|
await driver.sendKeys(Key.ENTER, 'hello');
|
|
await driver.findWait('.test-ref-editor-item', 1000);
|
|
assert.equal(await driver.find('.test-ref-editor-item.selected').isPresent(), false);
|
|
assert.equal(await driver.find('.test-ref-editor-new-item').isPresent(), false);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
|
|
await gu.undo();
|
|
await gu.toggleSidePanel('right', 'close');
|
|
});
|
|
|
|
it('should offer items ordered by best match', async function() {
|
|
let cell = await gu.getCell({section: 'References', col: 'Colors', rowNum: 1}).doClick();
|
|
assert.equal(await cell.getText(), 'Dark Slate Blue');
|
|
await driver.sendKeys(Key.ENTER, 'Dark Slate Blue');
|
|
assert.deepEqual(await getACOptions(4),
|
|
['Dark Slate Blue', 'Dark Slate Gray', 'Slate Blue', 'Medium Slate Blue']);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
|
|
await driver.sendKeys('blac');
|
|
assert.deepEqual(await getACOptions(6),
|
|
['Black', 'Blanched Almond', 'Blue', 'Blue Violet', 'Alice Blue', 'Cadet Blue']);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
|
|
cell = await gu.getCell({section: 'References', col: 'Colors', rowNum: 3}).doClick();
|
|
assert.equal(await cell.getText(), 'hello'); // Alt-text
|
|
await driver.sendKeys('hello');
|
|
assert.deepEqual(await getACOptions(2),
|
|
['Honeydew', 'Hot Pink']);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
|
|
cell = await gu.getCell({section: 'References', col: 'ColorCodes', rowNum: 2}).doClick();
|
|
assert.equal(await cell.getText(), '#808080');
|
|
await driver.sendKeys('#808080');
|
|
assert.deepEqual(await getACOptions(5),
|
|
['#808080', '#808000', '#800000', '#800080', '#87CEEB']);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
|
|
cell = await gu.getCell({section: 'References', col: 'XNums', rowNum: 2}).doClick();
|
|
assert.equal(await cell.getText(), '2019-04-29');
|
|
await driver.sendKeys('2019-04-29');
|
|
assert.deepEqual(await getACOptions(4),
|
|
['2019-04-29', '2020-04-29', '2019-11-05', '2020-04-28']);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
});
|
|
|
|
it('should update choices as user types into textbox', async function() {
|
|
let cell = await gu.getCell({section: 'References', col: 'Schools', rowNum: 1}).doClick();
|
|
assert.equal(await cell.getText(), 'TECHNOLOGY, ARTS AND SCIENCES STUDIO');
|
|
await driver.sendKeys('TECHNOLOGY, ARTS AND SCIENCES STUDIO');
|
|
assert.deepEqual(await getACOptions(3), [
|
|
'TECHNOLOGY, ARTS AND SCIENCES STUDIO',
|
|
'SCIENCE AND TECHNOLOGY ACADEMY',
|
|
'SCHOOL OF SCIENCE AND TECHNOLOGY',
|
|
]);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
cell = await gu.getCell({section: 'References', col: 'Schools', rowNum: 2}).doClick();
|
|
await driver.sendKeys('stuy');
|
|
assert.deepEqual(await getACOptions(3), [
|
|
'STUYVESANT HIGH SCHOOL',
|
|
'BEDFORD STUY COLLEGIATE CHARTER SCH',
|
|
'BEDFORD STUY NEW BEGINNINGS CHARTER',
|
|
]);
|
|
await driver.sendKeys(Key.BACK_SPACE);
|
|
assert.deepEqual(await getACOptions(3), [
|
|
'STUART M TOWNSEND MIDDLE SCHOOL',
|
|
'STUDIO SCHOOL (THE)',
|
|
'STUYVESANT HIGH SCHOOL',
|
|
]);
|
|
await driver.sendKeys(' bre');
|
|
assert.equal(await driver.find('.cell_editor .test-tokenfield .test-tokenfield-input').value(), 'stu bre');
|
|
assert.deepEqual(await getACOptions(3), [
|
|
'ST BRENDAN SCHOOL',
|
|
'BRONX STUDIO SCHOOL-WRITERS-ARTISTS',
|
|
'BROOKLYN STUDIO SECONDARY SCHOOL',
|
|
]);
|
|
|
|
await driver.sendKeys(Key.DOWN, Key.ENTER, Key.ENTER);
|
|
await gu.waitForServer();
|
|
assert.equal(await cell.getText(), 'ST BRENDAN SCHOOL');
|
|
await gu.undo();
|
|
assert.equal(await cell.getText(), '');
|
|
});
|
|
|
|
it('should highlight matching parts of items', async function() {
|
|
await driver.sendKeys(Key.HOME);
|
|
|
|
let cell = await gu.getCell({section: 'References', col: 'Colors', rowNum: 2}).doClick();
|
|
assert.equal(await cell.getText(), 'Red');
|
|
await driver.sendKeys(Key.ENTER, 'Red');
|
|
await driver.findWait('.test-ref-editor-item', 1000);
|
|
assert.deepEqual(
|
|
await driver.findContent('.test-ref-editor-item', /Dark Red/).findAll('span', e => e.getText()),
|
|
['Red']);
|
|
assert.deepEqual(
|
|
await driver.findContent('.test-ref-editor-item', /Rebecca Purple/).findAll('span', e => e.getText()),
|
|
['Re']);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
|
|
cell = await gu.getCell({section: 'References', col: 'Schools', rowNum: 1}).doClick();
|
|
await driver.sendKeys('br tech');
|
|
assert.deepEqual(
|
|
await driver.findContentWait('.test-ref-editor-item', /BROOKLYN TECH/, 1000).findAll('span', e => e.getText()),
|
|
['BR', 'TECH']);
|
|
assert.deepEqual(
|
|
await driver.findContent('.test-ref-editor-item', /BUFFALO.*TECHNOLOGY/).findAll('span', e => e.getText()),
|
|
['B', 'TECH']);
|
|
assert.deepEqual(
|
|
await driver.findContent('.test-ref-editor-item', /ENERGY TECH/).findAll('span', e => e.getText()),
|
|
['TECH']);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
});
|
|
|
|
it('should reflect changes to the target column', async function() {
|
|
await driver.sendKeys(Key.HOME);
|
|
|
|
const cell = await gu.getCell({section: 'References', col: 'Colors', rowNum: 4}).doClick();
|
|
assert.equal(await cell.getText(), '');
|
|
await driver.sendKeys(Key.ENTER);
|
|
assert.deepEqual(await getACOptions(2), ['Alice Blue', 'Añil']);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
|
|
// Change a color
|
|
await gu.getCell({section: 'Colors', col: 'Color Name', rowNum: 1}).doClick();
|
|
await driver.sendKeys('HAZELNUT', Key.ENTER);
|
|
await gu.waitForServer();
|
|
|
|
// See that the old value is gone from the autocomplete, and the new one is present.
|
|
await cell.click();
|
|
await driver.sendKeys(Key.ENTER);
|
|
assert.deepEqual(await getACOptions(2), ['Añil', 'Aqua']);
|
|
await driver.sendKeys('H');
|
|
assert.deepEqual(await getACOptions(2), ['HAZELNUT', 'Honeydew']);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
|
|
// Delete a row.
|
|
await gu.getCell({section: 'Colors', col: 'Color Name', rowNum: 1}).doClick();
|
|
await driver.find('body').sendKeys(Key.chord(await gu.modKey(), '-'));
|
|
await gu.waitForServer();
|
|
|
|
// See that the value is gone from the autocomplete.
|
|
await cell.click();
|
|
await driver.sendKeys('H');
|
|
assert.deepEqual(await getACOptions(2), ['Honeydew', 'Hot Pink']);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
|
|
// Add a row.
|
|
await gu.getCell({section: 'Colors', col: 'Color Name', rowNum: 1}).doClick();
|
|
await driver.find('body').sendKeys(Key.chord(await gu.modKey(), '='));
|
|
await gu.waitForServer();
|
|
await driver.sendKeys('HELIOTROPE', Key.ENTER);
|
|
await gu.waitForServer();
|
|
|
|
// See that the new value is visible in the autocomplete.
|
|
await cell.click();
|
|
await driver.sendKeys('H');
|
|
assert.deepEqual(await getACOptions(2), ['HELIOTROPE', 'Honeydew']);
|
|
await driver.sendKeys(Key.BACK_SPACE);
|
|
assert.deepEqual(await getACOptions(2), ['Añil', 'Aqua']);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
|
|
// Undo all the changes.
|
|
await gu.undo(4);
|
|
|
|
await cell.click();
|
|
await driver.sendKeys('H');
|
|
assert.deepEqual(await getACOptions(2), ['Honeydew', 'Hot Pink']);
|
|
await driver.sendKeys(Key.BACK_SPACE);
|
|
assert.deepEqual(await getACOptions(2), ['Alice Blue', 'Añil']);
|
|
await driver.sendKeys(Key.ESCAPE);
|
|
});
|
|
});
|
|
});
|