diff --git a/sandbox/grist/useractions.py b/sandbox/grist/useractions.py index 110b1954..4a8ec78e 100644 --- a/sandbox/grist/useractions.py +++ b/sandbox/grist/useractions.py @@ -1178,7 +1178,7 @@ class UserActions(object): # to strings containing comma-separated row IDs. # We need to get the values before changing the column type. table = self._engine.tables[table_id] - new_values = [",".join(map(str, row)) for row in self._get_column_values(col)] + new_values = [",".join(map(str, row or [])) for row in self._get_column_values(col)] self.ModifyColumn(table_id, col_id, dict(type="Text")) self.BulkUpdateRecord(table_id, list(table.row_ids), {col_id: new_values}) return diff --git a/test/nbrowser/ReferenceList.ts b/test/nbrowser/ReferenceList.ts index fe379988..16e1f2f1 100644 --- a/test/nbrowser/ReferenceList.ts +++ b/test/nbrowser/ReferenceList.ts @@ -10,14 +10,40 @@ describe('ReferenceList', function() { before(async function() { session = await gu.session().teamSite.login(); - await session.tempDoc(cleanup, 'Favorite_Films.grist'); + }); + + describe('other', function() { + it('allows to delete document with self reference', async function() { + const docId = await session.tempNewDoc(cleanup); + await gu.sendActions([ + ['AddEmptyTable', 'Table2'], + ['ModifyColumn', 'Table1', 'B', {type: 'RefList:Table1'}], + ['AddRecord', 'Table1', null, {A: 'a'}], + ['AddRecord', 'Table1', null, {A: 'b', B: ["L", 1]}], + ['AddRecord', 'Table1', null, {A: 'c', B: ["L", 2]}], + ]); - await gu.toggleSidePanel('right'); - await driver.find(".test-right-tab-pagewidget").click(); - await driver.find('.test-config-data').click(); + // Now try to delete the table. + await gu.removeTable('Table1'); + await gu.checkForErrors(); + + // Make sure table is deleted. Previously it ended with an engine error + // in the 'a' row which has NULL instead of a list of ids. + const api = session.createHomeApi().getDocAPI(docId); + const tables = await api.getRows('_grist_Tables'); + assert.deepEqual(tables.tableId, ['Table2']); + }); }); describe('transforms', function() { + + before(async function() { + await session.tempDoc(cleanup, 'Favorite_Films.grist'); + await gu.toggleSidePanel('right'); + await driver.find(".test-right-tab-pagewidget").click(); + await driver.find('.test-config-data').click(); + }); + afterEach(() => gu.checkForErrors()); it('should correctly transform references to reference lists', async function() { diff --git a/test/nbrowser/gristUtils.ts b/test/nbrowser/gristUtils.ts index 52b305af..9e64f85d 100644 --- a/test/nbrowser/gristUtils.ts +++ b/test/nbrowser/gristUtils.ts @@ -1016,6 +1016,13 @@ export async function sendActions(actions: UserAction[]) { await driver.manage().setTimeouts({ script: 1000 * 2, /* 2 seconds, default is 0.5s */ }); + + // Make quick test that we have a list of actions not just a single action, by checking + // if the first element is an array. + if (actions.length && !Array.isArray(actions[0])) { + throw new Error('actions argument should be a list of actions, not a single action'); + } + const result = await driver.executeAsyncScript(` const done = arguments[arguments.length - 1]; const prom = gristDocPageModel.gristDoc.get().docModel.docData.sendActions(${JSON.stringify(actions)});