def test_create_section_existing_view(self): # Test that CreateViewSection works for an existing view. self.load_sample(self.sample) self.assertTables([self.starting_table]) # Create a view + section for the initial table. self.apply_user_action(["CreateViewSection", 1, 0, "record", None]) # Verify that we got a new view, with one section, and three fields. self.assertViews([View(1, sections=[ Section(1, parentKey="record", tableRef=1, fields=[ Field(1, colRef=21), ]) ]) ]) # Create a new section for the same view, check that only a section is added. self.apply_user_action(["CreateViewSection", 1, 1, "record", None]) self.assertTables([self.starting_table]) self.assertViews([View(1, sections=[ Section(1, parentKey="record", tableRef=1, fields=[ Field(1, colRef=21), ]), Section(2, parentKey="record", tableRef=1, fields=[ Field(2, colRef=21), ]) ]) ]) # Create another section for the same view, this time summarized. self.apply_user_action(["CreateViewSection", 1, 1, "record", [21]]) summary_table = Table(2, "GristSummary_7_Address", 0, summarySourceTable=1, columns=[ Column(22, "city", "Text", isFormula=False, formula="", summarySourceCol=21), Column(23, "group", "RefList:Address", isFormula=True, formula="table.getSummarySourceGroup(rec)", summarySourceCol=0), Column(24, "count", "Int", isFormula=True, formula="len($group)", summarySourceCol=0), ]) self.assertTables([self.starting_table, summary_table]) # Check that we still have one view, with sections for different tables. view = View(1, sections=[ Section(1, parentKey="record", tableRef=1, fields=[ Field(1, colRef=21), ]), Section(2, parentKey="record", tableRef=1, fields=[ Field(2, colRef=21), ]), Section(3, parentKey="record", tableRef=2, fields=[ Field(3, colRef=22), Field(4, colRef=24), ]), ]) self.assertTables([self.starting_table, summary_table]) self.assertViews([view]) # Try to create a summary table for an invalid column, and check that it fails. with self.assertRaises(ValueError): self.apply_user_action(["CreateViewSection", 1, 1, "record", [23]]) self.assertTables([self.starting_table, summary_table]) self.assertViews([view])
def test_view_remove(self): # Add a couple of tables and views, to trigger creation of some related items. self.init_views_sample() # Remove a view. Ensure related items, sections, fields get removed. self.apply_user_action(["BulkRemoveRecord", "_grist_Views", [2,3]]) # Verify the new structure of tables and views. self.assertTables([ Table(1, "Schools", 1, 0, columns=[ Column(1, "manualSort", "ManualSortPos", False, "", 0), Column(2, "city", "Text", False, "", 0), Column(3, "state", "Text", False, "", 0), Column(4, "size", "Numeric", False, "", 0), ]), # Note that the summary table is gone. Table(3, 'Table1', 4, 0, columns=[ Column(9, "manualSort", "ManualSortPos", False, "", 0), Column(10, "A", "Any", True, "", 0), Column(11, "B", "Any", True, "", 0), Column(12, "C", "Any", True, "", 0), ]), ]) self.assertViews([ View(1, sections=[ Section(1, parentKey="record", tableRef=1, fields=[ Field(1, colRef=2), Field(2, colRef=3), Field(3, colRef=4), ]), ]), View(4, sections=[ Section(5, parentKey='record', tableRef=3, fields=[ Field(12, colRef=10), Field(13, colRef=11), Field(14, colRef=12), ]), ]), ]) self.assertTableData('_grist_TableViews', data=[ ["id", "tableRef", "viewRef"], ]) self.assertTableData('_grist_TabBar', cols="subset", data=[ ["id", "viewRef"], [1, 1], [4, 4], ]) self.assertTableData('_grist_Pages', cols="subset", data=[ ["id", "viewRef"], [1, 1], [4, 4], ])
def test_create_view_section(self): self.load_sample(self.sample) # Verify the starting table; there should be no views yet. self.assertTables([self.starting_table]) self.assertViews([]) # Create a view + section for the initial table. self.apply_user_action(["CreateViewSection", 1, 0, "record", None]) # Verify that we got a new view, with one section, and three fields. self.assertTables([self.starting_table]) basic_view = View(1, sections=[ Section(1, parentKey="record", tableRef=1, fields=[ Field(1, colRef=11), Field(2, colRef=12), Field(3, colRef=13), ]) ]) self.assertViews([basic_view]) self.assertTableData("Address", self.starting_table_data) # Create a "Totals" section, i.e. a summary with no group-by columns. self.apply_user_action(["CreateViewSection", 1, 0, "record", []]) # Verify that a new table gets created, and a new view, with a section for that table, # and some auto-generated summary fields. summary_table1 = Table(2, "GristSummary_7_Address", primaryViewId=0, summarySourceTable=1, columns=[ Column(14, "group", "RefList:Address", isFormula=True, summarySourceCol=0, formula="table.getSummarySourceGroup(rec)"), Column(15, "count", "Int", isFormula=True, summarySourceCol=0, formula="len($group)"), Column(16, "amount", "Numeric", isFormula=True, summarySourceCol=0, formula="SUM($group.amount)"), ]) summary_view1 = View(2, sections=[ Section(2, parentKey="record", tableRef=2, fields=[ Field(4, colRef=15), Field(5, colRef=16), ]) ]) self.assertTables([self.starting_table, summary_table1]) self.assertViews([basic_view, summary_view1]) # Verify the summarized data. self.assertTableData('GristSummary_7_Address', cols="subset", data=[ [ "id", "count", "amount"], [ 1, 11, 66.0 ], ]) # Create a summary section, grouped by the "State" column. self.apply_user_action(["CreateViewSection", 1, 0, "record", [12]]) # Verify that a new table gets created again, a new view, and a section for that table. # Note that we also check that summarySourceTable and summarySourceCol fields are correct. summary_table2 = Table(3, "GristSummary_7_Address2", primaryViewId=0, summarySourceTable=1, columns=[ Column(17, "state", "Text", isFormula=False, formula="", summarySourceCol=12), Column(18, "group", "RefList:Address", isFormula=True, summarySourceCol=0, formula="table.getSummarySourceGroup(rec)"), Column(19, "count", "Int", isFormula=True, summarySourceCol=0, formula="len($group)"), Column(20, "amount", "Numeric", isFormula=True, summarySourceCol=0, formula="SUM($group.amount)"), ]) summary_view2 = View(3, sections=[ Section(3, parentKey="record", tableRef=3, fields=[ Field(6, colRef=17), Field(7, colRef=19), Field(8, colRef=20), ]) ]) self.assertTables([self.starting_table, summary_table1, summary_table2]) self.assertViews([basic_view, summary_view1, summary_view2]) # Verify more fields of the new column objects. self.assertTableData('_grist_Tables_column', rows="subset", cols="subset", data=[ ['id', 'colId', 'type', 'formula', 'widgetOptions', 'label'], [17, 'state', 'Text', '', 'WidgetOptions1', 'State'], [20, 'amount', 'Numeric', 'SUM($group.amount)', 'WidgetOptions2', 'Amount'], ]) # Verify the summarized data. self.assertTableData('GristSummary_7_Address2', cols="subset", data=[ [ "id", "state", "count", "amount" ], [ 1, "NY", 7, 1.+2+6+7+8+10+11 ], [ 2, "WA", 1, 3. ], [ 3, "IL", 1, 4. ], [ 4, "MA", 2, 5.+9 ], ]) # Create a summary section grouped by two columns ("city" and "state"). self.apply_user_action(["CreateViewSection", 1, 0, "record", [11,12]]) # Verify the new table and views. summary_table3 = Table(4, "GristSummary_7_Address3", primaryViewId=0, summarySourceTable=1, columns=[ Column(21, "city", "Text", isFormula=False, formula="", summarySourceCol=11), Column(22, "state", "Text", isFormula=False, formula="", summarySourceCol=12), Column(23, "group", "RefList:Address", isFormula=True, summarySourceCol=0, formula="table.getSummarySourceGroup(rec)"), Column(24, "count", "Int", isFormula=True, summarySourceCol=0, formula="len($group)"), Column(25, "amount", "Numeric", isFormula=True, summarySourceCol=0, formula="SUM($group.amount)"), ]) summary_view3 = View(4, sections=[ Section(4, parentKey="record", tableRef=4, fields=[ Field(9, colRef=21), Field(10, colRef=22), Field(11, colRef=24), Field(12, colRef=25), ]) ]) self.assertTables([self.starting_table, summary_table1, summary_table2, summary_table3]) self.assertViews([basic_view, summary_view1, summary_view2, summary_view3]) # Verify the summarized data. self.assertTableData('GristSummary_7_Address3', cols="subset", data=[ [ "id", "city", "state", "count", "amount" ], [ 1, "New York", "NY" , 3, 1.+6+11 ], [ 2, "Albany", "NY" , 1, 2. ], [ 3, "Seattle", "WA" , 1, 3. ], [ 4, "Chicago", "IL" , 1, 4. ], [ 5, "Bedford", "MA" , 1, 5. ], [ 6, "Buffalo", "NY" , 1, 7. ], [ 7, "Bedford", "NY" , 1, 8. ], [ 8, "Boston", "MA" , 1, 9. ], [ 9, "Yonkers", "NY" , 1, 10. ], ]) # The original table's data should not have changed. self.assertTableData("Address", self.starting_table_data)
def test_summary_table_reuse(self): # Test that we'll reuse a suitable summary table when already available. self.load_sample(self.sample) # Create a summary section grouped by two columns ("city" and "state"). self.apply_user_action(["CreateViewSection", 1, 0, "record", [11,12]]) # Verify the new table and views. summary_table = Table(2, "GristSummary_7_Address", primaryViewId=0, summarySourceTable=1, columns=[ Column(14, "city", "Text", isFormula=False, formula="", summarySourceCol=11), Column(15, "state", "Text", isFormula=False, formula="", summarySourceCol=12), Column(16, "group", "RefList:Address", isFormula=True, summarySourceCol=0, formula="table.getSummarySourceGroup(rec)"), Column(17, "count", "Int", isFormula=True, summarySourceCol=0, formula="len($group)"), Column(18, "amount", "Numeric", isFormula=True, summarySourceCol=0, formula="SUM($group.amount)"), ]) summary_view = View(1, sections=[ Section(1, parentKey="record", tableRef=2, fields=[ Field(1, colRef=14), Field(2, colRef=15), Field(3, colRef=17), Field(4, colRef=18), ]) ]) self.assertTables([self.starting_table, summary_table]) self.assertViews([summary_view]) # Create twoo other views + view sections with the same breakdown (in different order # of group-by fields, which should still reuse the same table). self.apply_user_action(["CreateViewSection", 1, 0, "record", [12,11]]) self.apply_user_action(["CreateViewSection", 1, 0, "record", [11,12]]) summary_view2 = View(2, sections=[ Section(2, parentKey="record", tableRef=2, fields=[ Field(5, colRef=15), Field(6, colRef=14), Field(7, colRef=17), Field(8, colRef=18), ]) ]) summary_view3 = View(3, sections=[ Section(3, parentKey="record", tableRef=2, fields=[ Field(9, colRef=14), Field(10, colRef=15), Field(11, colRef=17), Field(12, colRef=18), ]) ]) # Verify that we have a new view, but are reusing the table. self.assertTables([self.starting_table, summary_table]) self.assertViews([summary_view, summary_view2, summary_view3]) # Verify the summarized data. self.assertTableData('GristSummary_7_Address', cols="subset", data=[ [ "id", "city", "state", "count", "amount" ], [ 1, "New York", "NY" , 3, 1.+6+11 ], [ 2, "Albany", "NY" , 1, 2. ], [ 3, "Seattle", "WA" , 1, 3. ], [ 4, "Chicago", "IL" , 1, 4. ], [ 5, "Bedford", "MA" , 1, 5. ], [ 6, "Buffalo", "NY" , 1, 7. ], [ 7, "Bedford", "NY" , 1, 8. ], [ 8, "Boston", "MA" , 1, 9. ], [ 9, "Yonkers", "NY" , 1, 10. ], ])
def test_table_removes(self): # Verify table removals triggered by UpdateRecord actions, and related behavior. # Same setup as previous test. self.init_sample_data() # Add one more table, and one more view for tables #1 and #4 (those we are about to delete). self.apply_user_action(["AddEmptyTable"]) out_actions = self.apply_user_action( ["CreateViewSection", 1, 0, 'detail', None]) self.assertEqual(out_actions.retValues[0]["viewRef"], 5) self.apply_user_action(["CreateViewSection", 4, 5, 'detail', None]) # See what's in TableViews and TabBar tables, to verify after we remove a table. self.assertTableData('_grist_TableViews', data=[ ["id", "tableRef", "viewRef"], [1, 1, 3], [2, 1, 5], ]) self.assertTableData('_grist_TabBar', cols="subset", data=[ ["id", "viewRef"], [1, 1], [2, 2], [3, 3], [4, 4], [5, 5], ]) # Remove two tables, ensure certain views get removed. self.apply_user_action(["BulkRemoveRecord", "_grist_Tables", [1, 4]]) # See that some TableViews/TabBar entries disappear, or tableRef gets unset. self.assertTableData('_grist_TableViews', data=[ ["id", "tableRef", "viewRef"], [1, 0, 3], ]) self.assertTableData('_grist_TabBar', cols="subset", data=[ ["id", "viewRef"], [2, 2], [3, 3], ]) # Check that reference columns to this table get removed, with associated fields. self.assertTables([ Table(2, "People", primaryViewId=2, summarySourceTable=0, columns=[ Column(5, "manualSort", "ManualSortPos", False, "", 0), Column(6, "name", "Text", False, "", 0), Column(8, "city", "Any", True, "$address.city", 0), ]), # Note that the summary table is also gone. ]) self.assertViews([ View(2, sections=[ Section(2, parentKey="record", tableRef=2, fields=[ Field(4, colRef=6), Field(6, colRef=8), ]), ]), View(3, sections=[ Section(5, parentKey="record", tableRef=2, fields=[ Field(13, colRef=6), Field(15, colRef=8), ]), ]), ])
def init_sample_data(self): # Add a couple of tables, including references. self.apply_user_action([ "AddTable", "Address", [ { "id": "city", "type": "Text" }, { "id": "state", "type": "Text" }, { "id": "amount", "type": "Numeric" }, ] ]) self.apply_user_action([ "AddTable", "People", [{ "id": "name", "type": "Text" }, { "id": "address", "type": "Ref:Address" }, { "id": "city", "type": "Any", "formula": "$address.city" }] ]) # Populate some data. d = testutil.table_data_from_rows("Address", self.address_table_data[0], self.address_table_data[1:]) self.apply_user_action( ["BulkAddRecord", "Address", d.row_ids, d.columns]) d = testutil.table_data_from_rows("People", self.people_table_data[0], self.people_table_data[1:]) self.apply_user_action( ["BulkAddRecord", "People", d.row_ids, d.columns]) # Add a view with several sections, including a summary table. self.apply_user_action(["CreateViewSection", 1, 0, 'record', None]) self.apply_user_action(["CreateViewSection", 1, 3, 'record', [3]]) self.apply_user_action(["CreateViewSection", 2, 3, 'record', None]) # Verify the new structure of tables and views. self.assertTables([ Table(1, "Address", primaryViewId=1, summarySourceTable=0, columns=[ Column(1, "manualSort", "ManualSortPos", False, "", 0), Column(2, "city", "Text", False, "", 0), Column(3, "state", "Text", False, "", 0), Column(4, "amount", "Numeric", False, "", 0), ]), Table(2, "People", primaryViewId=2, summarySourceTable=0, columns=[ Column(5, "manualSort", "ManualSortPos", False, "", 0), Column(6, "name", "Text", False, "", 0), Column(7, "address", "Ref:Address", False, "", 0), Column(8, "city", "Any", True, "$address.city", 0), ]), Table(3, "GristSummary_7_Address", 0, 1, columns=[ Column(9, "state", "Text", False, "", summarySourceCol=3), Column(10, "group", "RefList:Address", True, summarySourceCol=0, formula="table.getSummarySourceGroup(rec)"), Column(11, "count", "Int", True, summarySourceCol=0, formula="len($group)"), Column(12, "amount", "Numeric", True, summarySourceCol=0, formula="SUM($group.amount)"), ]), ]) self.assertViews([ View(1, sections=[ Section(1, parentKey="record", tableRef=1, fields=[ Field(1, colRef=2), Field(2, colRef=3), Field(3, colRef=4), ]), ]), View(2, sections=[ Section(2, parentKey="record", tableRef=2, fields=[ Field(4, colRef=6), Field(5, colRef=7), Field(6, colRef=8), ]), ]), View(3, sections=[ Section(3, parentKey="record", tableRef=1, fields=[ Field(7, colRef=2), Field(8, colRef=3), Field(9, colRef=4), ]), Section(4, parentKey="record", tableRef=3, fields=[ Field(10, colRef=9), Field(11, colRef=11), Field(12, colRef=12), ]), Section(5, parentKey="record", tableRef=2, fields=[ Field(13, colRef=6), Field(14, colRef=7), Field(15, colRef=8), ]), ]), ]) # Verify the data we've loaded. self.assertTableData('Address', cols="subset", data=self.address_table_data) self.assertTableData('People', cols="subset", data=self.people_table_data) self.assertTableData("GristSummary_7_Address", cols="subset", data=[ ["id", "state", "count", "amount"], [1, "NY", 7, 1. + 2 + 6 + 7 + 8 + 10 + 11], [2, "WA", 1, 3.], [3, "IL", 1, 4.], [4, "MA", 2, 5. + 9], ])
def test_section_removes(self): # Add a couple of tables and views, to trigger creation of some related items. self.init_views_sample() # Remove a couple of sections. Ensure their fields get removed. self.apply_user_action(['BulkRemoveRecord', '_grist_Views_section', [3,6]]) self.assertViews([ View(1, sections=[ Section(1, parentKey="record", tableRef=1, fields=[ Field(1, colRef=2), Field(2, colRef=3), Field(3, colRef=4), ]), ]), View(2, sections=[ Section(2, parentKey="detail", tableRef=1, fields=[ Field(4, colRef=2), Field(5, colRef=3), Field(6, colRef=4), ]), ]), View(3, sections=[ Section(4, parentKey="chart", tableRef=1, fields=[ Field(10, colRef=2), Field(11, colRef=3), ]), ]), View(4, sections=[ Section(5, parentKey='record', tableRef=3, fields=[ Field(12, colRef=10), Field(13, colRef=11), Field(14, colRef=12), ]), ]), ])
def init_views_sample(self): # Add a new table and a view, to get some Views/Sections/Fields, and TableView/TabBar items. self.apply_user_action(['AddTable', 'Schools', [ {'id': 'city', 'type': 'Text'}, {'id': 'state', 'type': 'Text'}, {'id': 'size', 'type': 'Numeric'}, ]]) self.apply_user_action(['BulkAddRecord', 'Schools', [1,2,3,4], { 'city': ['New York', 'Colombia', 'New York', ''], 'state': ['NY', 'NY', 'NY', ''], 'size': [1000, 2000, 3000, 4000], }]) # Add a new view; a second section (summary) to it; and a third view. self.apply_user_action(['CreateViewSection', 1, 0, 'detail', None]) self.apply_user_action(['CreateViewSection', 1, 2, 'record', [3]]) self.apply_user_action(['CreateViewSection', 1, 0, 'chart', None]) self.apply_user_action(['CreateViewSection', 0, 2, 'record', None]) # Verify the new structure of tables and views. self.assertTables([ Table(1, "Schools", 1, 0, columns=[ Column(1, "manualSort", "ManualSortPos", False, "", 0), Column(2, "city", "Text", False, "", 0), Column(3, "state", "Text", False, "", 0), Column(4, "size", "Numeric", False, "", 0), ]), Table(2, "GristSummary_7_Schools", 0, 1, columns=[ Column(5, "state", "Text", False, "", 3), Column(6, "group", "RefList:Schools", True, "table.getSummarySourceGroup(rec)", 0), Column(7, "count", "Int", True, "len($group)", 0), Column(8, "size", "Numeric", True, "SUM($group.size)", 0), ]), Table(3, 'Table1', 4, 0, columns=[ Column(9, "manualSort", "ManualSortPos", False, "", 0), Column(10, "A", "Any", True, "", 0), Column(11, "B", "Any", True, "", 0), Column(12, "C", "Any", True, "", 0), ]), ]) self.assertViews([ View(1, sections=[ Section(1, parentKey="record", tableRef=1, fields=[ Field(1, colRef=2), Field(2, colRef=3), Field(3, colRef=4), ]), ]), View(2, sections=[ Section(2, parentKey="detail", tableRef=1, fields=[ Field(4, colRef=2), Field(5, colRef=3), Field(6, colRef=4), ]), Section(3, parentKey="record", tableRef=2, fields=[ Field(7, colRef=5), Field(8, colRef=7), Field(9, colRef=8), ]), Section(6, parentKey='record', tableRef=3, fields=[ Field(15, colRef=10), Field(16, colRef=11), Field(17, colRef=12), ]), ]), View(3, sections=[ Section(4, parentKey="chart", tableRef=1, fields=[ Field(10, colRef=2), Field(11, colRef=3), ]), ]), View(4, sections=[ Section(5, parentKey='record', tableRef=3, fields=[ Field(12, colRef=10), Field(13, colRef=11), Field(14, colRef=12), ]), ]), ]) self.assertTableData('_grist_TableViews', data=[ ["id", "tableRef", "viewRef"], [1, 1, 2], [2, 1, 3], ]) self.assertTableData('_grist_TabBar', cols="subset", data=[ ["id", "viewRef"], [1, 1], [2, 2], [3, 3], [4, 4], ]) self.assertTableData('_grist_Pages', cols="subset", data=[ ["id", "viewRef"], [1, 1], [2, 2], [3, 3], [4, 4] ])
def test_creates_section_new_table(self): # Test that CreateViewSection works for adding a new table. self.load_sample(self.sample) self.assertTables([self.starting_table]) self.assertViews([]) # When we create a section/view for new table, we get both a primary view, and the new view we # are creating. self.apply_user_action(["CreateViewSection", 0, 0, "record", None]) new_table = Table(2, "Table1", primaryViewId=1, summarySourceTable=0, columns=[ Column(22, "manualSort", "ManualSortPos", isFormula=False, formula="", summarySourceCol=0), Column(23, "A", "Any", isFormula=True, formula="", summarySourceCol=0), Column(24, "B", "Any", isFormula=True, formula="", summarySourceCol=0), Column(25, "C", "Any", isFormula=True, formula="", summarySourceCol=0), ]) primary_view = View(1, sections=[ Section(1, parentKey="record", tableRef=2, fields=[ Field(1, colRef=23), Field(2, colRef=24), Field(3, colRef=25), ]) ]) new_view = View(2, sections=[ Section(2, parentKey="record", tableRef=2, fields=[ Field(4, colRef=23), Field(5, colRef=24), Field(6, colRef=25), ]) ]) self.assertTables([self.starting_table, new_table]) self.assertViews([primary_view, new_view]) # Create another section in an existing view for a new table. self.apply_user_action(["CreateViewSection", 0, 2, "record", None]) new_table2 = Table(3, "Table2", primaryViewId=3, summarySourceTable=0, columns=[ Column(26, "manualSort", "ManualSortPos", isFormula=False, formula="", summarySourceCol=0), Column(27, "A", "Any", isFormula=True, formula="", summarySourceCol=0), Column(28, "B", "Any", isFormula=True, formula="", summarySourceCol=0), Column(29, "C", "Any", isFormula=True, formula="", summarySourceCol=0), ]) primary_view2 = View(3, sections=[ Section(3, parentKey="record", tableRef=3, fields=[ Field(7, colRef=27), Field(8, colRef=28), Field(9, colRef=29), ]) ]) new_view.sections.append( Section(4, parentKey="record", tableRef=3, fields=[ Field(10, colRef=27), Field(11, colRef=28), Field(12, colRef=29), ]) ) # Check that we have a new table, only the primary view as new view; and a new section. self.assertTables([self.starting_table, new_table, new_table2]) self.assertViews([primary_view, new_view, primary_view2]) # Check that we can't create a summary of a table grouped by a column that doesn't exist yet. with self.assertRaises(ValueError): self.apply_user_action(["CreateViewSection", 0, 2, "record", [31]]) self.assertTables([self.starting_table, new_table, new_table2]) self.assertViews([primary_view, new_view, primary_view2]) # But creating a new table and showing totals for it is possible though dumb. self.apply_user_action(["CreateViewSection", 0, 2, "record", []]) # We expect a new table. new_table3 = Table(4, "Table3", primaryViewId=4, summarySourceTable=0, columns=[ Column(30, "manualSort", "ManualSortPos", isFormula=False, formula="", summarySourceCol=0), Column(31, "A", "Any", isFormula=True, formula="", summarySourceCol=0), Column(32, "B", "Any", isFormula=True, formula="", summarySourceCol=0), Column(33, "C", "Any", isFormula=True, formula="", summarySourceCol=0), ]) # A summary of it. summary_table = Table(5, "GristSummary_6_Table3", 0, summarySourceTable=4, columns=[ Column(34, "group", "RefList:Table3", isFormula=True, formula="table.getSummarySourceGroup(rec)", summarySourceCol=0), Column(35, "count", "Int", isFormula=True, formula="len($group)", summarySourceCol=0), ]) # The primary view of the new table. primary_view3 = View(4, sections=[ Section(5, parentKey="record", tableRef=4, fields=[ Field(13, colRef=31), Field(14, colRef=32), Field(15, colRef=33), ]) ]) # And a new view section for the summary. new_view.sections.append(Section(6, parentKey="record", tableRef=5, fields=[ Field(16, colRef=35) ])) self.assertTables([self.starting_table, new_table, new_table2, new_table3, summary_table]) self.assertViews([primary_view, new_view, primary_view2, primary_view3])
def test_summary_column_removals(self): # Verify that when we remove a column used for summary-table group-by, it updates summary # tables appropriately. self.init_sample_data() # Test that we cannot remove group-by columns from summary tables directly. with self.assertRaisesRegex(ValueError, "cannot remove .* group-by"): self.apply_user_action( ["BulkRemoveRecord", '_grist_Tables_column', [20, 18]]) # Test that group-by columns in summary tables get removed. self.apply_user_action( ["BulkRemoveRecord", '_grist_Tables_column', [11, 12, 16]]) # Verify the new structure of tables and views. self.assertTables([ Table(1, "Address", primaryViewId=0, summarySourceTable=0, columns=[ Column(13, "amount", "Numeric", False, "", 0), ]), Table(2, "Table1", 2, 0, columns=[ Column(14, "manualSort", "ManualSortPos", False, "", 0), Column(15, "A", "Text", False, "", 0), Column(17, "C", "Text", False, "", 0), ]), # Note that the summary table here switches to a new one, without the deleted group-by. Table(4, "GristSummary_7_Address2", 0, 1, columns=[ Column(22, "count", "Int", True, summarySourceCol=0, formula="len($group)"), Column(23, "amount", "Numeric", True, summarySourceCol=0, formula="SUM($group.amount)"), Column(24, "group", "RefList:Address", True, summarySourceCol=0, formula="table.getSummarySourceGroup(rec)"), ]), ]) self.assertViews([ View(1, sections=[ Section(1, parentKey="record", tableRef=1, fields=[ Field(3, colRef=13), ]), Section(4, parentKey="record", tableRef=2, fields=[ Field(10, colRef=15), Field(12, colRef=17), ]), Section(5, parentKey="record", tableRef=4, fields=[ Field(14, colRef=22), Field(15, colRef=23), ]), ]), View(2, sections=[ Section(2, parentKey="record", tableRef=2, fields=[ Field(4, colRef=15), Field(6, colRef=17), ]), ]) ]) # Verify the data itself. self.assertTableData('Address', data=[ ["id", "amount"], [21, 1.], [22, 2.], [23, 3.], [24, 4.], [25, 5.], [26, 6.], [27, 7.], [28, 8.], [29, 9.], [30, 10.], [31, 11.], ]) self.assertTableData('Table1', data=[ ["id", "A", "C", "manualSort"], [1, "a", "", 1.0], [2, "b", "", 2.0], [3, "c", "", 3.0], ]) self.assertTableData("GristSummary_7_Address2", cols="subset", data=[ ["id", "count", "amount"], [ 1, 7 + 1 + 1 + 2, 1. + 2 + 6 + 7 + 8 + 10 + 11 + 3 + 4 + 5 + 9 ], ])
def test_column_removals(self): # Verify removal of fields when columns are removed. self.init_sample_data() # Add link{Src,Target}ColRef to ViewSections. These aren't actually meaningful links, but they # should still get cleared automatically when columns get removed. self.apply_user_action([ 'UpdateRecord', '_grist_Views_section', 2, { 'linkSrcSectionRef': 1, 'linkSrcColRef': 11, 'linkTargetColRef': 16 } ]) self.assertTableData('_grist_Views_section', cols="subset", rows="subset", data=[ [ "id", "linkSrcSectionRef", "linkSrcColRef", "linkTargetColRef" ], [2, 1, 11, 16], ]) # Test that we can remove multiple columns using BulkUpdateRecord. self.apply_user_action( ["BulkRemoveRecord", '_grist_Tables_column', [11, 16]]) # Test that link{Src,Target}colRef back-references get unset. self.assertTableData('_grist_Views_section', cols="subset", rows="subset", data=[ [ "id", "linkSrcSectionRef", "linkSrcColRef", "linkTargetColRef" ], [2, 1, 0, 0], ]) # Test that columns and section fields got removed. self.assertTables([ Table(1, "Address", primaryViewId=0, summarySourceTable=0, columns=[ Column(12, "state", "Text", False, "", 0), Column(13, "amount", "Numeric", False, "", 0), ]), Table(2, "Table1", 2, 0, columns=[ Column(14, "manualSort", "ManualSortPos", False, "", 0), Column(15, "A", "Text", False, "", 0), Column(17, "C", "Text", False, "", 0), ]), Table(3, "GristSummary_7_Address", 0, 1, columns=[ Column(18, "state", "Text", False, "", summarySourceCol=12), Column(19, "group", "RefList:Address", True, summarySourceCol=0, formula="table.getSummarySourceGroup(rec)"), Column(20, "count", "Int", True, summarySourceCol=0, formula="len($group)"), Column(21, "amount", "Numeric", True, summarySourceCol=0, formula="SUM($group.amount)"), ]), ]) self.assertViews([ View(1, sections=[ Section(1, parentKey="record", tableRef=1, fields=[ Field(2, colRef=12), Field(3, colRef=13), ]), Section(4, parentKey="record", tableRef=2, fields=[ Field(10, colRef=15), Field(12, colRef=17), ]), Section(5, parentKey="record", tableRef=3, fields=[ Field(13, colRef=18), Field(14, colRef=20), Field(15, colRef=21), ]), ]), View(2, sections=[ Section(2, parentKey="record", tableRef=2, fields=[ Field(4, colRef=15), Field(6, colRef=17), ]), ]) ])
def init_sample_data(self): # Add a new view with a section, and a new table to that view, and a summary table. self.load_sample(self.sample2) self.apply_user_action(["CreateViewSection", 1, 0, "record", None]) self.apply_user_action(["CreateViewSection", 0, 1, "record", None]) self.apply_user_action(["CreateViewSection", 1, 1, "record", [12]]) self.apply_user_action([ "BulkAddRecord", "Table1", [None] * 3, { "A": ["a", "b", "c"], "B": ["d", "e", "f"], "C": ["", "", ""] } ]) # Verify the new structure of tables and views. self.assertTables([ Table(1, "Address", primaryViewId=0, summarySourceTable=0, columns=[ Column(11, "city", "Text", False, "", 0), Column(12, "state", "Text", False, "", 0), Column(13, "amount", "Numeric", False, "", 0), ]), Table(2, "Table1", 2, 0, columns=[ Column(14, "manualSort", "ManualSortPos", False, "", 0), Column(15, "A", "Text", False, "", 0), Column(16, "B", "Text", False, "", 0), Column(17, "C", "Text", False, "", 0), ]), Table(3, "GristSummary_7_Address", 0, 1, columns=[ Column(18, "state", "Text", False, "", summarySourceCol=12), Column(19, "group", "RefList:Address", True, summarySourceCol=0, formula="table.getSummarySourceGroup(rec)"), Column(20, "count", "Int", True, summarySourceCol=0, formula="len($group)"), Column(21, "amount", "Numeric", True, summarySourceCol=0, formula="SUM($group.amount)"), ]), ]) self.assertViews([ View(1, sections=[ Section(1, parentKey="record", tableRef=1, fields=[ Field(1, colRef=11), Field(2, colRef=12), Field(3, colRef=13), ]), Section(4, parentKey="record", tableRef=2, fields=[ Field(10, colRef=15), Field(11, colRef=16), Field(12, colRef=17), ]), Section(5, parentKey="record", tableRef=3, fields=[ Field(13, colRef=18), Field(14, colRef=20), Field(15, colRef=21), ]), ]), View(2, sections=[ Section(2, parentKey="record", tableRef=2, fields=[ Field(4, colRef=15), Field(5, colRef=16), Field(6, colRef=17), ]), ]) ]) self.assertTableData('Address', data=self.address_table_data) self.assertTableData('Table1', data=[ ["id", "A", "B", "C", "manualSort"], [1, "a", "d", "", 1.0], [2, "b", "e", "", 2.0], [3, "c", "f", "", 3.0], ]) self.assertTableData("GristSummary_7_Address", cols="subset", data=[ ["id", "state", "count", "amount"], [1, "NY", 7, 1. + 2 + 6 + 7 + 8 + 10 + 11], [2, "WA", 1, 3.], [3, "IL", 1, 4.], [4, "MA", 2, 5. + 9], ])