mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
da323fb741
Summary: Adding a way to detach an editor. Initially only implemented for the formula editor, includes redesign for the AI part. - Initially, the detached editor is tight with the formula assistant and both are behind GRIST_FORMULA_ASSISTANT flag, but this can be relaxed later on, as the detached editor can be used on its own. - Detached editor is only supported in regular fields and on the creator panel. It is not supported yet for conditional styles, due to preview limitations. - Old code for the assistant was removed completely, as it was only a temporary solution, but the AI conversation part was copied to the new one. - Prompting was not modified in this diff, it will be included in the follow-up with more test cases. Test Plan: Added only new tests; existing tests should pass. Reviewers: JakubSerafin Reviewed By: JakubSerafin Differential Revision: https://phab.getgrist.com/D3863
369 lines
15 KiB
TypeScript
369 lines
15 KiB
TypeScript
import {assert, driver, Key} from 'mocha-webdriver';
|
|
import * as gu from 'test/nbrowser/gristUtils';
|
|
import {server, setupTestSuite} from 'test/nbrowser/testUtils';
|
|
|
|
describe('RightPanel', function() {
|
|
this.timeout(20000);
|
|
const cleanup = setupTestSuite();
|
|
|
|
afterEach(() => gu.checkForErrors());
|
|
|
|
it('should focus on the creator panel when chart/custom section is added', async () => {
|
|
const mainSession = await gu.session().teamSite.login();
|
|
await mainSession.tempNewDoc(cleanup);
|
|
|
|
// Reset prefs.
|
|
await driver.executeScript('resetDismissedPopups();');
|
|
await gu.waitForServer();
|
|
|
|
// Refresh for a clean start.
|
|
await gu.reloadDoc();
|
|
|
|
// Close panel and make sure it stays closed.
|
|
await gu.toggleSidePanel('right', 'close');
|
|
|
|
// Add a chart section.
|
|
await gu.addNewSection('Chart', 'Table1', { dismissTips: true});
|
|
assert.isFalse(await gu.isSidePanelOpen('right'));
|
|
await gu.undo();
|
|
|
|
// Add a chart page.
|
|
await gu.addNewPage('Chart', 'Table1');
|
|
assert.isFalse(await gu.isSidePanelOpen('right'));
|
|
await gu.undo();
|
|
|
|
// Add a custom section.
|
|
await gu.addNewSection('Custom', 'Table1');
|
|
assert.isFalse(await gu.isSidePanelOpen('right'));
|
|
await gu.undo();
|
|
|
|
// Add a custom page.
|
|
await gu.addNewPage('Custom', 'Table1');
|
|
assert.isFalse(await gu.isSidePanelOpen('right'));
|
|
await gu.undo();
|
|
|
|
// Now open the panel on the column tab.
|
|
const columnTab = async () => {
|
|
await gu.toggleSidePanel('right', 'open');
|
|
await driver.find('.test-right-tab-field').click();
|
|
};
|
|
|
|
await columnTab();
|
|
|
|
// Add a chart section.
|
|
await gu.addNewSection('Chart', 'Table1');
|
|
assert.isTrue(await gu.isSidePanelOpen('right'));
|
|
assert.isTrue(await driver.find('.test-right-widget-title').isDisplayed());
|
|
await gu.undo();
|
|
|
|
await columnTab();
|
|
|
|
// Add a chart page.
|
|
await gu.addNewPage('Chart', 'Table1');
|
|
assert.isTrue(await gu.isSidePanelOpen('right'));
|
|
assert.isTrue(await driver.find('.test-right-widget-title').isDisplayed());
|
|
await gu.undo();
|
|
|
|
await columnTab();
|
|
|
|
// Add a custom section.
|
|
await gu.addNewSection('Custom', 'Table1');
|
|
assert.isTrue(await gu.isSidePanelOpen('right'));
|
|
assert.isTrue(await driver.find('.test-right-widget-title').isDisplayed());
|
|
await gu.undo();
|
|
|
|
await columnTab();
|
|
|
|
// Add a custom page.
|
|
await gu.addNewPage('Custom', 'Table1');
|
|
assert.isTrue(await gu.isSidePanelOpen('right'));
|
|
assert.isTrue(await driver.find('.test-right-widget-title').isDisplayed());
|
|
await gu.undo();
|
|
});
|
|
|
|
it('should open/close panel, and reflect the current section', async function() {
|
|
// Open a document with multiple views and multiple sections.
|
|
await server.simulateLogin("Chimpy", "chimpy@getgrist.com", 'nasa');
|
|
const doc = await gu.importFixturesDoc('chimpy', 'nasa', 'Horizon', 'World.grist', false);
|
|
await driver.get(`${server.getHost()}/o/nasa/doc/${doc.id}`);
|
|
|
|
// Check current view and section name.
|
|
assert.equal(await gu.getActiveSectionTitle(6000), 'CITY');
|
|
assert.equal(await driver.find('.test-bc-page').getAttribute('value'), 'City');
|
|
|
|
// Open side pane, and check it shows the right section.
|
|
await gu.toggleSidePanel('right', 'open');
|
|
await driver.find('.test-config-widget').click();
|
|
assert.equal(await gu.isSidePanelOpen('right'), true);
|
|
|
|
assert.equal(await driver.find('.test-right-widget-title').value(), 'CITY');
|
|
|
|
// Check that the tab's name reflects suitable text
|
|
assert.equal(await driver.find('.test-right-tab-pagewidget').getText(), 'Table');
|
|
assert.equal(await driver.find('.test-right-tab-field').getText(), 'Column');
|
|
|
|
// Switch to Field tab, check that it shows the right field.
|
|
await driver.find('.test-right-tab-field').click();
|
|
assert.equal(await driver.find('.test-field-label').value(), "Name");
|
|
|
|
// Check to a different field, check a different field is shown.
|
|
await driver.sendKeys(Key.RIGHT);
|
|
assert.equal(await driver.find('.test-field-label').value(), "Country");
|
|
|
|
// Click to a different section, check a different field is shown.
|
|
await gu.getSection('CITY Card List').find('.detail_row_num').click();
|
|
assert.equal(await driver.find('.test-field-label').value(), "Name");
|
|
|
|
// Check that the tab's name reflects suitable text
|
|
assert.equal(await driver.find('.test-right-tab-pagewidget').getText(), 'Card List');
|
|
assert.equal(await driver.find('.test-right-tab-field').getText(), 'Field');
|
|
|
|
// Close panel, check it's hidden.
|
|
await gu.toggleSidePanel('right');
|
|
assert.equal(await gu.isSidePanelOpen('right'), false);
|
|
assert.equal(await driver.find('.config_item').isPresent(), false);
|
|
|
|
// Reopen panel, check it's still right.
|
|
await gu.toggleSidePanel('right');
|
|
assert.equal(await driver.find('.test-field-label').value(), "Name");
|
|
|
|
// Switch to the section tab, check the new section is reflected.
|
|
await driver.find('.test-right-tab-pagewidget').click();
|
|
assert.equal(await driver.find('.test-right-widget-title').value(), 'CITY Card List');
|
|
|
|
// Switch to a different view, check the new section is reflected.
|
|
await driver.findContent('.test-treeview-itemHeader', /Country/).click();
|
|
assert.equal(await driver.find('.test-right-widget-title').value(), 'COUNTRY');
|
|
|
|
// Switch to field tab; check the new field is reflected.
|
|
await driver.find('.test-right-tab-field').click();
|
|
assert.equal(await driver.find('.test-field-label').value(), "Code");
|
|
});
|
|
|
|
it('should not cause errors when switching pages with Field tab open', async () => {
|
|
// There was an error ("this.calcSize is not a function") switching between pages when the
|
|
// active section changes type and Field tab is open, triggered by an unnecessary rebuilding
|
|
// of FieldConfigTab.
|
|
|
|
// Check that the active field tab is called "Column" (since the active section is "Table")
|
|
// and is open to column "Code".
|
|
assert.equal(await driver.find('.test-right-tab-field').getText(), 'Column');
|
|
assert.equal(await driver.find('.test-field-label').value(), "Code");
|
|
|
|
// Switch to the "City" page. Check that the tab is now called "Field" (since the active section is of
|
|
// type "CardList"), and open to the field "Name".
|
|
await driver.findContent('.test-treeview-itemHeader', /City/).click();
|
|
assert.equal(await driver.find('.test-right-tab-field').getText(), 'Field');
|
|
assert.equal(await driver.find('.test-field-label').value(), "Name");
|
|
|
|
// Check that this did not cause client-side errors.
|
|
await gu.checkForErrors();
|
|
|
|
// Now switch back, and check for errors again.
|
|
await driver.findContent('.test-treeview-itemHeader', /Country/).click();
|
|
await gu.checkForErrors();
|
|
});
|
|
|
|
it('should show tools when requested', async function() {
|
|
// Select specific view/section/field. Close side-pane.
|
|
await gu.getCell({col: "Name", rowNum: 3}).click();
|
|
assert.equal(await driver.find('.test-field-label').value(), "Name");
|
|
await gu.toggleSidePanel('right');
|
|
assert.equal(await gu.isSidePanelOpen('right'), false);
|
|
|
|
// Click Activity Log.
|
|
assert.equal(await driver.find('.action_log').isPresent(), false);
|
|
await driver.find('.test-tools-log').click();
|
|
await gu.waitToPass(() => // Click might not work while panel is sliding out to open.
|
|
driver.findContentWait('.test-doc-history-tabs .test-select-button', 'Activity', 500).click());
|
|
|
|
// Check that panel is shown, and correct.
|
|
assert.equal(await gu.isSidePanelOpen('right'), true);
|
|
assert.equal(await driver.find('.test-right-tab-field').isPresent(), false);
|
|
assert.equal(await driver.find('.action_log').isDisplayed(), true);
|
|
|
|
// Click "x", Check expected section config shown.
|
|
await driver.find('.test-right-tool-close').click();
|
|
assert.equal(await driver.find('.test-right-tab-field').getText(), 'Column');
|
|
assert.equal(await driver.find('.test-field-label').value(), "Name");
|
|
|
|
// TODO: polish data validation and then uncomment
|
|
/*
|
|
// Click Validations. Check it's shown and correct.
|
|
await driver.find('.test-tools-validate').click();
|
|
assert.equal(await driver.findContent('.config_item', /Validations/).isDisplayed(), true);
|
|
|
|
// Close panel. Switch to another view.
|
|
await gu.toggleSidePanel('right');
|
|
assert.equal(await gu.isSidePanelOpen('right'), false);
|
|
assert.equal(await driver.findContent('.config_item', /Validations/).isPresent(), false);
|
|
await driver.findContent('.test-treeview-itemHeader', /Country/).click();
|
|
|
|
// Open panel. Check Validations are still shown.
|
|
await gu.toggleSidePanel('right');
|
|
assert.equal(await driver.findContent('.config_item', /Validations/).isDisplayed(), true);
|
|
await driver.find('.test-right-tool-close').click();
|
|
*/
|
|
});
|
|
|
|
it('should keep panel state on reload', async function() {
|
|
// Check the panel is currently open and showing Field options.
|
|
assert.equal(await gu.isSidePanelOpen('right'), true);
|
|
assert.equal(await driver.find('.test-field-label').value(), "Name");
|
|
|
|
// Reload the page, and click the same cell as before.
|
|
await driver.navigate().refresh();
|
|
assert.equal(await gu.getActiveSectionTitle(3000), 'COUNTRY');
|
|
await gu.waitForServer();
|
|
await gu.getCell({col: "Name", rowNum: 3}).click();
|
|
|
|
// Check the panel is still open and showing the same Field options.
|
|
assert.equal(await gu.isSidePanelOpen('right'), true);
|
|
assert.equal(await driver.find('.test-field-label').value(), "Name");
|
|
});
|
|
|
|
it('\'SELECTOR FOR\' should work correctly', async function() {
|
|
// open the Data tab
|
|
await driver.find('.test-right-tab-pagewidget').click();
|
|
await driver.find('.test-config-data').click();
|
|
|
|
// open a page that has linked section
|
|
await driver.findContent('.test-treeview-itemHeader', /Country/).click();
|
|
|
|
// wait for data to load
|
|
assert(await gu.getActiveSectionTitle(3000));
|
|
await gu.waitForServer();
|
|
|
|
// select a view section that does not select other section
|
|
await gu.getSection('COUNTRY Card List').click();
|
|
|
|
// check that selector-for is not present
|
|
assert.equal(await driver.find('.test-selector-for').isPresent(), false);
|
|
|
|
// select a view section that does select other section
|
|
await gu.getSection('COUNTRY').click();
|
|
|
|
// check that selector-of is present and that all selected section are listed
|
|
assert.equal(await driver.find('.test-selector-for').isPresent(), true);
|
|
assert.deepEqual(await driver.findAll('.test-selector-for-entry', (e) => e.getText()), [
|
|
"CITY",
|
|
"COUNTRYLANGUAGE",
|
|
"COUNTRY Card List",
|
|
]);
|
|
});
|
|
|
|
it('\'Edit Data Selection\' should allow to change link', async () => {
|
|
// select COUNTRY DETAIL
|
|
await gu.getSection('CITY').click();
|
|
|
|
// open page widget picker
|
|
await driver.find('.test-pwc-editDataSelection').click();
|
|
|
|
// remove link
|
|
await driver.find('.test-wselect-selectby').doClick();
|
|
await driver.findContent('.test-wselect-selectby option', /Select Widget/).doClick();
|
|
|
|
// click save
|
|
await driver.find('.test-wselect-addBtn').doClick();
|
|
await gu.waitForServer();
|
|
|
|
// Go to the first record.
|
|
await gu.sendKeys(Key.chord(await gu.modKey(), Key.UP));
|
|
|
|
// Check that link was removed, by going to Aruba.
|
|
await gu.getSection('COUNTRY').click();
|
|
await gu.getCell(0, 1).click();
|
|
// City section should stay where it was
|
|
assert.equal(await gu.getCell(0, 1, 'CITY').getText(), 'Kabul');
|
|
|
|
// re-set the link
|
|
await gu.getSection('CITY').click();
|
|
await driver.find('.test-pwc-editDataSelection').click();
|
|
await driver.find('.test-wselect-selectby').click();
|
|
await driver.findContent('.test-wselect-selectby option', /Country$/).click();
|
|
await driver.find('.test-wselect-addBtn').doClick();
|
|
await gu.waitForServer();
|
|
|
|
// check link is set
|
|
await gu.getSection('COUNTRY').click();
|
|
await gu.getCell(0, 1).click();
|
|
assert.equal(await gu.getCell(0, 1, 'CITY').getText(), 'Oranjestad');
|
|
});
|
|
|
|
it('should not cause errors when switching pages with Table tab open', async () => {
|
|
// There were an error doing eigher one of 1) switching to `Code View`, or 2) removing the
|
|
// active page, when the Table tab was open, because: both caused the activeView to be set to an
|
|
// empty model causes some computed property of the ViewSectionRec to fail. This is what this
|
|
// test is aiming at catching.
|
|
|
|
await gu.toggleSidePanel('right', 'open');
|
|
await driver.find('.test-config-widget').click();
|
|
|
|
assert.deepEqual(await gu.getPageNames(), ['City', 'Country', 'CountryLanguage']);
|
|
|
|
// adds a new page
|
|
await gu.addNewPage(/Table/, /City/);
|
|
|
|
assert.deepEqual(await gu.getPageNames(), ['City', 'Country', 'CountryLanguage', 'New page']);
|
|
|
|
// remove that page
|
|
await gu.openPageMenu(/New page/);
|
|
await driver.find('.grist-floating-menu .test-docpage-remove').click();
|
|
await gu.waitForServer();
|
|
|
|
// check pages were removed and nothing break
|
|
assert.deepEqual(await gu.getPageNames(), ['City', 'Country', 'CountryLanguage']);
|
|
await gu.checkForErrors();
|
|
|
|
// now switch to `Code View`
|
|
await driver.find('.test-tools-code').click();
|
|
assert.equal(await driver.findWait('.g-code-viewer', 1000).isPresent(), true);
|
|
|
|
// check nothing broke
|
|
await gu.checkForErrors();
|
|
|
|
// switch back to City
|
|
await gu.getPageItem(/City/).click();
|
|
});
|
|
|
|
it('should not cause errors when editing summary table with `Change Widget` button', async () => {
|
|
// Changing the grouped by columns using the `Change Widget` used to throw `TypeError: Cannot
|
|
// read property `toUpperCase` of undefined`. The goal of this test is to prevent future
|
|
// regression.
|
|
|
|
// Create a summary table of City groupbed by country
|
|
await gu.addNewPage(/Table/, /City/, {summarize: [/Country/]});
|
|
|
|
// open right panel Widget
|
|
await gu.toggleSidePanel('right', 'open');
|
|
await driver.find('.test-right-tab-pagewidget').click();
|
|
await driver.find('.test-config-widget').click();
|
|
|
|
// click `Change Widget`
|
|
await driver.findContent('.test-right-panel button', /Change Widget/).click();
|
|
|
|
// remove column `Country` and save
|
|
await gu.selectWidget(/Table/, /City/, {summarize: []});
|
|
|
|
// check there were no error
|
|
await gu.checkForErrors();
|
|
});
|
|
|
|
it('should not raise errors when opening with table\'s `Widget Options`', async function() {
|
|
// Open right panel and select 'Column'
|
|
await gu.toggleSidePanel('right', 'open');
|
|
await driver.find('.test-right-tab-field').click();
|
|
|
|
// Close the right panel
|
|
await gu.toggleSidePanel('right', 'close');
|
|
|
|
// Open the right panel using the table's `Widget option`
|
|
await gu.openSectionMenu('viewLayout');
|
|
await driver.find('.test-widget-options').click();
|
|
|
|
await gu.checkForErrors();
|
|
});
|
|
|
|
|
|
});
|