(core) Form kanban tasks

Summary:
- Open all links in a new tab
- Excluding not filled columns (to fix trigger formulas)
- Fixed Ref/RefList submission
- Removing redundant type definitions for Box
- Adding header menu item
- Default empty values in select control

Test Plan: Updated

Reviewers: georgegevoian

Reviewed By: georgegevoian

Differential Revision: https://phab.getgrist.com/D4166
This commit is contained in:
Jarosław Sadziński
2024-01-23 21:52:57 +01:00
parent 007c4492dc
commit 95c0441d84
22 changed files with 363 additions and 124 deletions

View File

@@ -60,6 +60,7 @@ describe('FormView', function() {
async function createFormWith(type: string, more = false) {
await gu.addNewSection('Form', 'Table1');
// Make sure column D is not there.
assert.isUndefined(await api.getTable(docId, 'Table1').then(t => t.D));
// Add a text question
@@ -117,10 +118,62 @@ describe('FormView', function() {
assert.deepEqual(await api.getTable(docId, 'Table1').then(t => t.D), [value]);
}
async function expect(values: any[]) {
async function expectInD(values: any[]) {
assert.deepEqual(await api.getTable(docId, 'Table1').then(t => t.D), values);
}
it('updates creator panel when navigated away', async function() {
// Add 2 new pages.
await gu.addNewPage('Form', 'New Table', {tableName: 'TabA'});
await gu.renamePage('TabA');
await gu.addNewPage('Form', 'New Table', {tableName: 'TabB'});
// Open the creator panel on field tab
await gu.openColumnPanel();
// Select A column
await question('A').click();
// Make sure it is selected.
assert.equal(await selectedLabel(), 'A');
// And creator panel reflects it.
assert.equal(await driver.find('.test-field-label').value(), "A");
// Now switch to page TabA.
await gu.openPage('TabA');
// And select B column.
await question('B').click();
assert.equal(await selectedLabel(), 'B');
// Make sure creator panel reflects it (it didn't).
assert.equal(await driver.find('.test-field-label').value(), "B");
await gu.undo(2); // There was a bug with second undo.
await gu.undo();
});
it('triggers trigger formulas', async function() {
const formUrl = await createFormWith('Text');
// Add a trigger formula for this column.
await gu.showRawData();
await gu.getCell('D', 1).click();
await gu.openColumnPanel();
await driver.find(".test-field-set-trigger").click();
await gu.waitAppFocus(false);
await gu.sendKeys('"Hello from trigger"', Key.ENTER);
await gu.waitForServer();
await gu.closeRawTable();
await gu.onNewTab(async () => {
await driver.get(formUrl);
await driver.find('input[type="submit"]').click();
await waitForConfirm();
});
await expectSingle('Hello from trigger');
await removeForm();
});
it('can submit a form with Text field', async function() {
const formUrl = await createFormWith('Text');
// We are in a new window.
@@ -189,7 +242,7 @@ describe('FormView', function() {
await gu.onNewTab(async () => {
await driver.get(formUrl);
// Make sure options are there.
assert.deepEqual(await driver.findAll('select[name="D"] option', e => e.getText()), ['Foo', 'Bar', 'Baz']);
assert.deepEqual(await driver.findAll('select[name="D"] option', e => e.getText()), ['', 'Foo', 'Bar', 'Baz']);
await driver.findWait('select[name="D"]', 1000).click();
await driver.find("option[value='Bar']").click();
await driver.find('input[type="submit"]').click();
@@ -229,7 +282,7 @@ describe('FormView', function() {
await driver.find('input[type="submit"]').click();
await waitForConfirm();
});
await expect([true, false]);
await expectInD([true, false]);
// Remove the additional record added just now.
await gu.sendActions([
@@ -262,6 +315,78 @@ describe('FormView', function() {
await removeForm();
});
it('can submit a form with Ref field', async function() {
const formUrl = await createFormWith('Reference', true);
// Add some options.
await gu.openColumnPanel();
await gu.setRefShowColumn('A');
// Add 3 records to this table (it is now empty).
await gu.sendActions([
['AddRecord', 'Table1', null, {A: 'Foo'}], // id 1
['AddRecord', 'Table1', null, {A: 'Bar'}], // id 2
['AddRecord', 'Table1', null, {A: 'Baz'}], // id 3
]);
await gu.toggleSidePanel('right', 'close');
// We are in a new window.
await gu.onNewTab(async () => {
await driver.get(formUrl);
assert.deepEqual(
await driver.findAll('select[name="D"] option', e => e.getText()),
['', ...['Bar', 'Baz', 'Foo']]
);
assert.deepEqual(
await driver.findAll('select[name="D"] option', e => e.value()),
['', ...['2', '3', '1']]
);
await driver.findWait('select[name="D"]', 1000).click();
await driver.find('option[value="2"]').click();
await driver.find('input[type="submit"]').click();
await waitForConfirm();
});
await expectInD([0, 0, 0, 2]);
// Remove 3 records.
await gu.sendActions([
['BulkRemoveRecord', 'Table1', [1, 2, 3, 4]],
]);
await removeForm();
});
it('can submit a form with RefList field', async function() {
const formUrl = await createFormWith('Reference List', true);
// Add some options.
await gu.openColumnPanel();
await gu.setRefShowColumn('A');
// Add 3 records to this table (it is now empty).
await gu.sendActions([
['AddRecord', 'Table1', null, {A: 'Foo'}], // id 1
['AddRecord', 'Table1', null, {A: 'Bar'}], // id 2
['AddRecord', 'Table1', null, {A: 'Baz'}], // id 3
]);
await gu.toggleSidePanel('right', 'close');
// We are in a new window.
await gu.onNewTab(async () => {
await driver.get(formUrl);
await driver.findWait('input[name="D[]"][value="1"]', 1000).click();
await driver.findWait('input[name="D[]"][value="2"]', 1000).click();
assert.equal(await driver.find('.grist-checkbox:has(input[name="D[]"][value="1"])').getText(), 'Foo');
assert.equal(await driver.find('.grist-checkbox:has(input[name="D[]"][value="2"])').getText(), 'Bar');
assert.equal(await driver.find('.grist-checkbox:has(input[name="D[]"][value="3"])').getText(), 'Baz');
await driver.find('input[type="submit"]').click();
await waitForConfirm();
});
await expectInD([null, null, null, ['L', 2, 1]]);
// Remove 3 records.
await gu.sendActions([
['BulkRemoveRecord', 'Table1', [1, 2, 3, 4]],
]);
await removeForm();
});
it('can unpublish forms', async function() {
const formUrl = await createFormWith('Text');
await driver.find('.test-forms-unpublish').click();

View File

@@ -508,7 +508,7 @@ describe('RawData', function () {
await gu.sendKeys("abc");
await gu.checkTextEditor("abc");
await gu.sendKeys(Key.ESCAPE);
await showRawData();
await gu.showRawData();
assert.equal(await gu.getActiveSectionTitle(), 'City');
assert.deepEqual(await gu.getCursorPosition(), {rowNum: 20, col: 0}); // raw popup is not sorted
await gu.sendKeys("abc");
@@ -530,7 +530,7 @@ describe('RawData', function () {
await gu.sendKeys(Key.ESCAPE);
// Now open popup again, but close it by clicking on the close button.
await showRawData();
await gu.showRawData();
await gu.closeRawTable();
await assertNoPopup();
assert.equal(await gu.getActiveSectionTitle(), 'CITY');
@@ -540,7 +540,7 @@ describe('RawData', function () {
await gu.sendKeys(Key.ESCAPE);
// Now do the same, but close by clicking on a diffrent page
await showRawData();
await gu.showRawData();
await gu.getPageItem('Country').click();
await assertNoPopup();
assert.equal(await gu.getActiveSectionTitle(), 'COUNTRY');
@@ -552,7 +552,7 @@ describe('RawData', function () {
// Now make sure that raw data is available for card view.
await gu.selectSectionByTitle("COUNTRY Card List");
assert.equal(await gu.getActiveSectionTitle(), 'COUNTRY Card List');
await showRawData();
await gu.showRawData();
assert.equal(await gu.getActiveSectionTitle(), 'Country');
assert.deepEqual(await gu.getCursorPosition(), {rowNum: 1, col: 1});
await gu.sendKeys("abc");
@@ -623,7 +623,7 @@ describe('RawData', function () {
// Now open plain raw data for City table.
await gu.selectSectionByTitle("CITY");
assert.equal(await gu.getActiveSectionTitle(), 'CITY'); // CITY is viewSection title
await showRawData();
await gu.showRawData();
assert.equal(await gu.getActiveSectionTitle(), 'City'); // City is now a table title
// Now remove the table.
await api.applyUserActions(doc, [[
@@ -787,12 +787,6 @@ function replaceAnchor(link: string, values: {
return link.replace(anchorRegex, `#a${values.a || a}.s${values.s || s}.r${values.r || r}.c${values.c || c}`);
}
async function showRawData() {
await gu.openSectionMenu('viewLayout');
await driver.find('.test-show-raw-data').click();
await waitForPopup();
}
async function openRawData() {
await driver.find('.test-tools-raw').click();
await waitForRawData();

View File

@@ -1188,7 +1188,12 @@ export async function changeWidget(type: WidgetType) {
/**
* Rename the given page to a new name. The oldName can be a full string name or a RegExp.
*/
export async function renamePage(oldName: string|RegExp, newName: string) {
export async function renamePage(oldName: string|RegExp, newName?: string) {
if (!newName && typeof oldName === 'string') {
newName = oldName;
oldName = await getCurrentPageName();
}
if (newName === undefined) { throw new Error('newName must be specified'); }
await openPageMenu(oldName);
await driver.find('.test-docpage-rename').click();
await driver.find('.test-docpage-editor').sendKeys(newName, Key.ENTER);
@@ -1570,6 +1575,15 @@ export async function openSectionMenu(which: 'sortAndFilter'|'viewLayout', secti
return await driver.findWait('.grist-floating-menu', 100);
}
/**
* Opens Raw data view for current section.
*/
export async function showRawData(section?: string|WebElement) {
await openSectionMenu('viewLayout', section);
await driver.find('.test-show-raw-data').click();
assert.isTrue(await driver.findWait('.test-raw-data-overlay', 100).isDisplayed());
}
// Mapping from column menu option name to dom element selector to wait for, or null if no need to wait.
const ColumnMenuOption: { [id: string]: string; } = {
Filter: '.test-filter-menu-wrapper'