gristlabs_grist-core/test/nbrowser/ReferenceColumns.ts
2022-08-10 13:10:50 +02:00

567 lines
25 KiB
TypeScript

import {assert, driver, Key, stackWrapFunc} from 'mocha-webdriver';
import * as gu from 'test/nbrowser/gristUtils';
import {Session} from 'test/nbrowser/gristUtils';
import {server, setupTestSuite} from 'test/nbrowser/testUtils';
describe('ReferenceColumns', function() {
this.timeout(20000);
setupTestSuite();
let session: Session;
const cleanup = setupTestSuite({team: true});
describe('rendering', function() {
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();
});
it('should render Row ID values as TableId[RowId]', async function() {
await driver.find('.test-right-tab-field').click();
await driver.find('.mod-add-column').click();
await gu.waitForServer();
await gu.setType(/Reference/);
await gu.waitForServer();
await gu.enterGridRows({col: 3, rowNum: 1}, [['1'], ['2'], ['3'], ['4']]);
assert.deepEqual(await gu.getVisibleGridCells(3, [1, 2, 3, 4, 5, 6]),
['Films[1]', 'Films[2]', 'Films[3]', 'Films[4]', '', '']);
await driver.find('.test-fbuilder-ref-table-select').click();
await driver.findContent('.test-select-row', /Friends/).click();
await gu.waitForServer();
// These are now invalid cells containing AltText such as 'Films[1]'
// We don't simply convert Films[1] -> Friends[1]
assert.deepEqual(await gu.getVisibleGridCells(3, [1, 2, 3, 4, 5, 6]),
['Films[1]', 'Films[2]', 'Films[3]', 'Films[4]', '', '']);
await driver.find('.test-type-transform-apply').click();
await gu.waitForServer();
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]),
['Films[1]', 'Films[2]', 'Films[3]', 'Films[4]', '', '']);
await gu.getCell(3, 5).click();
await driver.sendKeys('Roger');
await driver.sendKeys(Key.ENTER);
await gu.waitForServer();
// 'Roger' is an actual reference
assert.deepEqual(await gu.getVisibleGridCells(3, [1, 2, 3, 4, 5, 6]),
['Films[1]', 'Films[2]', 'Films[3]', 'Films[4]', 'Roger', '']);
await driver.find('.test-fbuilder-ref-col-select').click();
await driver.findContent('.test-select-row', /Row ID/).click();
await gu.waitForServer();
// 'Friends[1]' is an actual reference, the rest are invalid
assert.deepEqual(await gu.getVisibleGridCells(3, [1, 2, 3, 4, 5, 6]),
['Films[1]', 'Films[2]', 'Films[3]', 'Films[4]', '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]),
['Films[1]', 'Films[2]', 'Films[3]', 'Films[4]', '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(), 'Films[1]');
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);
});
await gu.waitForServer();
assert.equal(await cell.getText(), 'Friends[5]');
await gu.undo();
assert.equal(await cell.getText(), 'Films[1]');
// 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);
await gu.waitForServer();
assert.equal(await cell.getText(), 'Friends[5]');
});
it(`should show '[Blank]' if the referenced item is blank`, async function() {
// Open the All page.
await driver.findContentWait('.test-treeview-itemHeader', /All/, 2000).click();
await gu.waitForDocToLoad();
// Clear the cells in Films record containing Avatar and Alien.
await gu.getCell('Title', 3, 'Films record').doClick();
await gu.sendKeys(Key.BACK_SPACE);
await gu.waitForServer();
await gu.sendKeys(Key.ARROW_DOWN, Key.BACK_SPACE);
await gu.waitForServer();
// Check that all references to Avatar and Alien now show '[Blank]'.
assert.deepEqual(
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6], 'Friends record'),
[
'Forrest Gump',
'Toy Story',
'[Blank]',
'The Dark Knight',
'Forrest Gump',
'[Blank]'
]
);
// Check that '[Blank]' is not shown when the reference editor is open.
await gu.getCell('Favorite Film', 3, 'Friends record').doClick();
await gu.sendKeys(Key.ENTER);
assert.equal(await driver.find('.celleditor_text_editor').value(), '');
await gu.sendKeys(Key.ESCAPE);
// Undo (twice), and check that it shows Avatar and Alien again.
await gu.undo(2);
assert.deepEqual(
await gu.getVisibleGridCells('Favorite Film', [1, 2, 3, 4, 5, 6], 'Friends record'),
[
'Forrest Gump',
'Toy Story',
'Avatar',
'The Dark Knight',
'Forrest Gump',
'Alien'
]
);
});
});
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-AC-Test.grist');
await gu.toggleSidePanel('right', 'close');
});
it('should open to correct item selected, and leave it unchanged on Enter', async function() {
const checkRefCell = stackWrapFunc(async (col: string, rowNum: number, expValue: string) => {
// Click cell and open for editing.
const cell = await gu.getCell({section: 'References', col, rowNum}).doClick();
assert.equal(await cell.getText(), expValue);
await driver.sendKeys(Key.ENTER);
// Wait for expected value to appear in the list; check that it's selected.
const match = await driver.findContentWait('.test-ref-editor-item', expValue, 1000);
assert.equal(await match.matches('.selected'), true);
// Save the value.
await driver.sendKeys(Key.ENTER);
await gu.waitForServer();
assert.equal(await cell.getText(), expValue);
// Assert that the undo is disabled, i.e. no action was generated.
assert.equal(await driver.find('.test-undo').matches('[class*=-disabled]'), true);
});
await checkRefCell('Color', 1, 'Dark Slate Blue');
await checkRefCell('ColorCode', 2, '#808080');
await checkRefCell('XNum', 3, '2019-11-05');
await checkRefCell('School', 1, 'TECHNOLOGY, ARTS AND SCIENCES STUDIO');
});
it('should render first items when opening empty cell', async function() {
await driver.sendKeys(Key.HOME);
let cell = await gu.getCell({section: 'References', col: 'Color', 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: 'School', 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: 'Color', rowNum: 2}).doClick();
await driver.withActions(a => a.doubleClick(cell));
assert.equal(await driver.findWait('.test-ref-editor-item.selected', 1000).getText(), 'Red');
// Scroll to another item and click it.
let item = driver.findContent('.test-ref-editor-item', 'Rosy Brown');
await gu.scrollIntoView(item);
await item.click();
// It should get saved; and undo should restore the previous value.
await gu.waitForServer();
assert.equal(await cell.getText(), 'Rosy Brown');
await gu.undo();
assert.equal(await cell.getText(), 'Red');
// Edit another cell by starting to type.
cell = await gu.getCell({section: 'References', col: 'Color', 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();
// 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: 'Color', rowNum: 2}).doClick();
await driver.withActions(a => a.doubleClick(cell));
assert.equal(await driver.findWait('.test-ref-editor-item.selected', 1000).getText(), 'Red');
// Move to another item and hit Enter
await driver.sendKeys(Key.DOWN, Key.DOWN, 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 saved; and undo should restore the previous value.
await gu.waitForServer();
assert.equal(await cell.getText(), 'Pale Violet Red');
await gu.undo();
assert.equal(await cell.getText(), 'Red');
// Edit another cell by starting to type.
cell = await gu.getCell({section: 'References', col: 'Color', 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);
// 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: 'Color', 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('.celleditor_text_editor').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('.celleditor_text_editor').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('.celleditor_text_editor').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('.celleditor_text_editor').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('.celleditor_text_editor').mouseMove();
assert.equal(await driver.find('.celleditor_text_editor').value(), 'da');
assert.equal(await driver.find('.test-ref-editor-item.selected').isPresent(), false);
// Click away to save the typed-in text.
await gu.getCell({section: 'References', col: 'Color', rowNum: 1}).doClick();
await gu.waitForServer();
assert.equal(await cell.getText(), "da");
assert.equal(await cell.find('.field_clip').matches('.invalid'), true);
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: 'Color', rowNum: 1}).doClick();
await driver.sendKeys("lavender ", 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: 'Color', 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 saved, and should not appear invalid.
await driver.find('.test-ref-editor-new-item').click();
await gu.waitForServer();
assert.equal(await cell.getText(), "pinkish");
assert.equal(await cell.find('.field_clip').matches('.invalid'), false);
// Requires 2 undos, because adding the "pinkish" record is a separate action. TODO these
// actions should be bundled.
await gu.undo(2);
assert.equal(await cell.getText(), "Red");
});
it('should offer an add-new option when opening alt-text', async function() {
const cell = await gu.getCell({section: 'References', col: 'Color', rowNum: 2}).doClick();
// Enter and invalid value and save without clicking "add new".
await driver.sendKeys("super pink", Key.ENTER);
// It should be saved but appear invalid (as alt-text).
await gu.waitForServer();
assert.equal(await cell.getText(), "super pink");
assert.equal(await cell.find('.field_clip').matches('.invalid'), true);
// Open the cell again. The "Add New" option should be there.
await driver.withActions(a => a.doubleClick(cell));
assert.equal(await driver.find('.test-ref-editor-new-item').getText(), "super pink");
assert.equal(await driver.find('.test-ref-editor-item.selected').isPresent(), false);
// Select "add new" (this time with arrow keys), and save.
await driver.sendKeys(Key.UP);
assert.equal(await driver.find('.test-ref-editor-new-item').matches('.selected'), true);
await driver.sendKeys(Key.ENTER);
// Once "add new" is clicked, the "super pink" no longer appears as invalid.
await gu.waitForServer();
assert.equal(await cell.getText(), "super pink");
assert.equal(await cell.find('.field_clip').matches('.invalid'), false);
await gu.undo(3);
assert.equal(await cell.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: 'Color', rowNum: 3}).doClick();
assert.equal(await cell.getText(), "hello");
assert.equal(await cell.find('.field_clip').matches('.invalid'), true);
await driver.sendKeys(Key.ENTER);
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);
assert.equal(await driver.find('.celleditor_text_editor').value(), '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: 'Color', rowNum: 1}).doClick();
assert.equal(await cell.getText(), 'Dark Slate Blue');
await driver.sendKeys(Key.ENTER);
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: 'Color', rowNum: 3}).doClick();
assert.equal(await cell.getText(), 'hello'); // Alt-text
await driver.sendKeys(Key.ENTER);
assert.deepEqual(await getACOptions(2),
['Honeydew', 'Hot Pink']);
await driver.sendKeys(Key.ESCAPE);
cell = await gu.getCell({section: 'References', col: 'ColorCode', rowNum: 2}).doClick();
assert.equal(await cell.getText(), '#808080');
await driver.sendKeys(Key.ENTER);
assert.deepEqual(await getACOptions(5),
['#808080', '#808000', '#800000', '#800080', '#87CEEB']);
await driver.sendKeys(Key.ESCAPE);
cell = await gu.getCell({section: 'References', col: 'XNum', rowNum: 2}).doClick();
assert.equal(await cell.getText(), '2019-04-29');
await driver.sendKeys(Key.ENTER);
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: 'School', rowNum: 1}).doClick();
assert.equal(await cell.getText(), 'TECHNOLOGY, ARTS AND SCIENCES STUDIO');
await driver.sendKeys(Key.ENTER);
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: 'School', 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('.celleditor_text_editor').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);
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: 'Color', rowNum: 2}).doClick();
assert.equal(await cell.getText(), 'Red');
await driver.sendKeys(Key.ENTER);
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: 'School', 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: 'Color', 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);
});
});
});