def test_record_removal(self): # Remove a record, make sure that lookup maps get updated. self.load_sample(testsamples.sample_students) out_actions = self.remove_record("Schools", 3) self.assertPartialOutActions( out_actions, { "stored": [ actions.RemoveRecord("Schools", 3), actions.BulkUpdateRecord("Students", [2, 4, 6], { "schoolCities": ["West Haven", "West Haven", "West Haven"] }), actions.BulkUpdateRecord("Students", [2, 4, 6], {"schoolIds": ["4", "4", "4"]}), ], "calls": { "Students": { "schoolIds": 3, "schoolCities": 3 }, # LookupMapColumn is also updated but via a different path (unset() vs method() call), so # it's not included in the count of formula calls. } }) self.assertPartialData( "Students", ["id", "schoolIds", "schoolCities"], [[1, "1:2", "New York:Colombia"], [2, "4", "West Haven"], [3, "1:2", "New York:Colombia"], [4, "4", "West Haven"], [5, "", ""], [6, "4", "West Haven"]])
def test_deletions(self): self.load_sample(self.sample) # Create a summary table summarizing count and total of orders by year. self.apply_user_action(["CreateViewSection", 2, 0, 'record', [10]]) self.assertPartialData("GristSummary_6_Orders", ["id", "year", "count", "amount", "group"], [ [1, 2012, 1, 15.0, [1]], [2, 2013, 2, 30.0, [2, 3]], [3, 2014, 3, 86.0, [4, 5, 6]], [4, 2015, 4, 106.0, [7, 8, 9, 10]], ]) # Update a record so that a new line appears in the summary table. out_actions_update = self.update_record("Orders", 1, year=2007) self.assertPartialData("GristSummary_6_Orders", ["id", "year", "count", "amount", "group"], [ [1, 2012, 0, 0.0, []], [2, 2013, 2, 30.0, [2, 3]], [3, 2014, 3, 86.0, [4, 5, 6]], [4, 2015, 4, 106.0, [7, 8, 9, 10]], [5, 2007, 1, 15.0, [1]], ]) # Undo and ensure that the new line is gone from the summary table. out_actions_undo = self.apply_undo_actions(out_actions_update.undo) self.assertPartialData("GristSummary_6_Orders", ["id", "year", "count", "amount", "group"], [ [1, 2012, 1, 15.0, [1]], [2, 2013, 2, 30.0, [2, 3]], [3, 2014, 3, 86.0, [4, 5, 6]], [4, 2015, 4, 106.0, [7, 8, 9, 10]], ]) self.assertPartialOutActions( out_actions_undo, { "stored": [ actions.UpdateRecord("GristSummary_6_Orders", 1, {"group": [1]}), actions.UpdateRecord("GristSummary_6_Orders", 1, {"count": 1}), actions.UpdateRecord("GristSummary_6_Orders", 1, {"amount": 15.0}), actions.RemoveRecord("GristSummary_6_Orders", 5), actions.UpdateRecord("Orders", 1, {"year": 2012}), ], "calls": { "GristSummary_6_Orders": { "group": 1, "amount": 1, "count": 1 }, "Orders": { "#lookup##summary#GristSummary_6_Orders": 1, "#summary#GristSummary_6_Orders": 1 } } })
def alist(): return [ actions.BulkUpdateRecord("Table1", [1, 2, 3], {'Foo': [10, 20, 30]}), actions.BulkUpdateRecord("Table2", [1, 2, 3], { 'Foo': [10, 20, 30], 'Bar': ['a', 'b', 'c'] }), actions.UpdateRecord("Table1", 17, {'Foo': 10}), actions.UpdateRecord("Table2", 18, { 'Foo': 10, 'Bar': 'a' }), actions.AddRecord("Table1", 17, {'Foo': 10}), actions.BulkAddRecord("Table2", 18, { 'Foo': 10, 'Bar': 'a' }), actions.ReplaceTableData("Table2", 18, { 'Foo': 10, 'Bar': 'a' }), actions.RemoveRecord("Table1", 17), actions.BulkRemoveRecord("Table2", [17, 18]), actions.AddColumn("Table1", "Foo", {"type": "Text"}), actions.RenameColumn("Table1", "Foo", "Bar"), actions.ModifyColumn("Table1", "Foo", {"type": "Text"}), actions.RemoveColumn("Table1", "Foo"), actions.AddTable("THello", [{ "id": "Foo" }, { "id": "Bar" }]), actions.RemoveTable("THello"), actions.RenameTable("THello", "TWorld"), ]
def _do_test_updates(self, source_tbl_name, summary_tbl_name): # This is the main part of test_summary_updates(). It's moved to its own method so that # updates can be verified the same way after a table rename. # Verify the summarized data. self.assertTableData(summary_tbl_name, 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. ], ]) # Change an amount (New York, NY, 6 -> 106), check that the right calc action gets emitted. out_actions = self.update_record(source_tbl_name, 26, amount=106) self.assertPartialOutActions(out_actions, { "stored": [ actions.UpdateRecord(source_tbl_name, 26, {'amount': 106}), actions.UpdateRecord(summary_tbl_name, 1, {'amount': 1.+106+11}), ] }) # Change a groupby value so that a record moves from one summary group to another. # Bedford, NY, 8.0 -> Bedford, MA, 8.0 out_actions = self.update_record(source_tbl_name, 28, state="MA") self.assertPartialOutActions(out_actions, { "stored": [ actions.UpdateRecord(source_tbl_name, 28, {'state': 'MA'}), actions.BulkUpdateRecord(summary_tbl_name, [5,7], {'amount': [5.0 + 8.0, 0.0]}), actions.BulkUpdateRecord(summary_tbl_name, [5,7], {'count': [2, 0]}), actions.BulkUpdateRecord(summary_tbl_name, [5,7], {'group': [[25, 28], []]}), ] }) # Add a record to an existing group (Bedford, MA, 108.0) out_actions = self.add_record(source_tbl_name, city="Bedford", state="MA", amount=108.0) self.assertPartialOutActions(out_actions, { "stored": [ actions.AddRecord(source_tbl_name, 32, {'city': 'Bedford', 'state': 'MA', 'amount': 108.0}), actions.UpdateRecord(summary_tbl_name, 5, {'amount': 5.0 + 8.0 + 108.0}), actions.UpdateRecord(summary_tbl_name, 5, {'count': 3}), actions.UpdateRecord(summary_tbl_name, 5, {'group': [25, 28, 32]}), ] }) # Remove a record (rowId=28, Bedford, MA, 8.0) out_actions = self.remove_record(source_tbl_name, 28) self.assertPartialOutActions(out_actions, { "stored": [ actions.RemoveRecord(source_tbl_name, 28), actions.UpdateRecord(summary_tbl_name, 5, {'amount': 5.0 + 108.0}), actions.UpdateRecord(summary_tbl_name, 5, {'count': 2}), actions.UpdateRecord(summary_tbl_name, 5, {'group': [25, 32]}), ] }) # Change groupby value to create a new combination (rowId 25, Bedford, MA, 5.0 -> Salem, MA). # A new summary record should be added. out_actions = self.update_record(source_tbl_name, 25, city="Salem") self.assertPartialOutActions(out_actions, { "stored": [ actions.UpdateRecord(source_tbl_name, 25, {'city': 'Salem'}), actions.AddRecord(summary_tbl_name, 10, {'city': 'Salem', 'state': 'MA'}), actions.BulkUpdateRecord(summary_tbl_name, [5,10], {'amount': [108.0, 5.0]}), actions.BulkUpdateRecord(summary_tbl_name, [5,10], {'count': [1, 1]}), actions.BulkUpdateRecord(summary_tbl_name, [5,10], {'group': [[32], [25]]}), ] }) # Add a record with a new combination (Amherst, MA, 17) out_actions = self.add_record(source_tbl_name, city="Amherst", state="MA", amount=17.0) self.assertPartialOutActions(out_actions, { "stored": [ actions.AddRecord(source_tbl_name, 33, {'city': 'Amherst', 'state': 'MA', 'amount': 17.}), actions.AddRecord(summary_tbl_name, 11, {'city': 'Amherst', 'state': 'MA'}), actions.UpdateRecord(summary_tbl_name, 11, {'amount': 17.0}), actions.UpdateRecord(summary_tbl_name, 11, {'count': 1}), actions.UpdateRecord(summary_tbl_name, 11, {'group': [33]}), ] }) # Verify the resulting data after all the updates. self.assertTableData(summary_tbl_name, cols="subset", data=[ [ "id", "city", "state", "count", "amount" ], [ 1, "New York", "NY" , 3, 1.+106+11 ], [ 2, "Albany", "NY" , 1, 2. ], [ 3, "Seattle", "WA" , 1, 3. ], [ 4, "Chicago", "IL" , 1, 4. ], [ 5, "Bedford", "MA" , 1, 108. ], [ 6, "Buffalo", "NY" , 1, 7. ], [ 7, "Bedford", "NY" , 0, 0. ], [ 8, "Boston", "MA" , 1, 9. ], [ 9, "Yonkers", "NY" , 1, 10. ], [ 10, "Salem", "MA" , 1, 5.0 ], [ 11, "Amherst", "MA" , 1, 17.0 ], ])
def test_prune_actions(self): # prune_actions is in-place, so we make a new list every time. def alist(): return [ actions.BulkUpdateRecord("Table1", [1, 2, 3], {'Foo': [10, 20, 30]}), actions.BulkUpdateRecord("Table2", [1, 2, 3], { 'Foo': [10, 20, 30], 'Bar': ['a', 'b', 'c'] }), actions.UpdateRecord("Table1", 17, {'Foo': 10}), actions.UpdateRecord("Table2", 18, { 'Foo': 10, 'Bar': 'a' }), actions.AddRecord("Table1", 17, {'Foo': 10}), actions.BulkAddRecord("Table2", 18, { 'Foo': 10, 'Bar': 'a' }), actions.ReplaceTableData("Table2", 18, { 'Foo': 10, 'Bar': 'a' }), actions.RemoveRecord("Table1", 17), actions.BulkRemoveRecord("Table2", [17, 18]), actions.AddColumn("Table1", "Foo", {"type": "Text"}), actions.RenameColumn("Table1", "Foo", "Bar"), actions.ModifyColumn("Table1", "Foo", {"type": "Text"}), actions.RemoveColumn("Table1", "Foo"), actions.AddTable("THello", [{ "id": "Foo" }, { "id": "Bar" }]), actions.RemoveTable("THello"), actions.RenameTable("THello", "TWorld"), ] def prune(table_id, col_id): a = alist() actions.prune_actions(a, table_id, col_id) return a self.assertEqual( prune('Table1', 'Foo'), [ actions.BulkUpdateRecord("Table2", [1, 2, 3], { 'Foo': [10, 20, 30], 'Bar': ['a', 'b', 'c'] }), actions.UpdateRecord("Table2", 18, { 'Foo': 10, 'Bar': 'a' }), actions.BulkAddRecord("Table2", 18, { 'Foo': 10, 'Bar': 'a' }), actions.ReplaceTableData("Table2", 18, { 'Foo': 10, 'Bar': 'a' }), actions.RemoveRecord("Table1", 17), actions.BulkRemoveRecord("Table2", [17, 18]), # It doesn't do anything with column renames; it can be addressed if needed. actions.RenameColumn("Table1", "Foo", "Bar"), # It doesn't do anything with AddTable, which is expected. actions.AddTable("THello", [{ "id": "Foo" }, { "id": "Bar" }]), actions.RemoveTable("THello"), actions.RenameTable("THello", "TWorld"), ]) self.assertEqual(prune('Table2', 'Foo'), [ actions.BulkUpdateRecord("Table1", [1, 2, 3], {'Foo': [10, 20, 30]}), actions.BulkUpdateRecord("Table2", [1, 2, 3], {'Bar': ['a', 'b', 'c']}), actions.UpdateRecord("Table1", 17, {'Foo': 10}), actions.UpdateRecord("Table2", 18, {'Bar': 'a'}), actions.AddRecord("Table1", 17, {'Foo': 10}), actions.BulkAddRecord("Table2", 18, {'Bar': 'a'}), actions.ReplaceTableData("Table2", 18, {'Bar': 'a'}), actions.RemoveRecord("Table1", 17), actions.BulkRemoveRecord("Table2", [17, 18]), actions.AddColumn("Table1", "Foo", {"type": "Text"}), actions.RenameColumn("Table1", "Foo", "Bar"), actions.ModifyColumn("Table1", "Foo", {"type": "Text"}), actions.RemoveColumn("Table1", "Foo"), actions.AddTable("THello", [{ "id": "Foo" }, { "id": "Bar" }]), actions.RemoveTable("THello"), actions.RenameTable("THello", "TWorld"), ])