def test_mystdout_pushes_print_commands_to_worksheet(self): ws = Worksheet() mso = MyStdout(ws) mso.write('weeeeeee!') ws2 = Worksheet() ws2.add_console_text('weeeeeee!', log_type='output') self.assertEquals(ws._console_text, ws2._console_text)
def test_calculate_clears_previous_worksheet_console_text_and_reports_time_when_theres_an_error( self, mock_time, mock_execute_usercode): recalc_times = [1.3245, 0] def mock_time_fn(): return recalc_times.pop() mock_time.side_effect = mock_time_fn def throw_error(_, __): raise Exception('argh') mock_execute_usercode.side_effect = throw_error worksheet = Worksheet() worksheet._console_text = 'previous errors\n' worksheet.add_console_text = Mock() calculate(worksheet, sentinel.usercode, sentinel.private_key) self.assertNotIn('previous errors', worksheet._console_text) self.assertEquals( worksheet.add_console_text.call_args_list[-1], (('Took 1.32s', ), { 'log_type': 'system' }), )
def test_recalc_cell_catches_cell_errors_and_adds_them_to_console(self): cell = Cell() cell.formula = "=123" cell.python_formula = '_raise(Exception("OMGWTFBBQ"))' cell.error = 'old error, just hanging around...' worksheet = Worksheet() location = (1, 11) worksheet[location] = cell # Mocked out to avoid explosion -- tested in another unit test. node = Mock() node.parents = [] graph = {location: node} context = {'worksheet': worksheet, "_raise": _raise} worksheet.add_console_text = Mock() recalculate_cell(location, Mock(), graph, context) self.assertEqual(worksheet[location].error, 'Exception: OMGWTFBBQ') expected_error_text = "Exception: OMGWTFBBQ\n Formula '%s' in A11\n" % ( cell.formula) self.assertCalledOnce(worksheet.add_console_text, expected_error_text) self.assertEquals(worksheet[location].value, undefined)
def test_calculate_should_execute_usercode_with_correct_context_and_curried_evaluate_formulae_in_context( self, mock_evaluate_formulae_in_context, mock_execute_usercode): worksheet = Worksheet() calculate(worksheet, sentinel.usercode, sentinel.private_key) args, kwargs = mock_execute_usercode.call_args self.assertEquals(kwargs, {}) self.assertEquals(args[0], sentinel.usercode) context = args[1] self.assertEquals(context['CellRange'], CellRange) self.assertEquals(context['DateTime'], DateTime) self.assertEquals(context['FormulaError'], FormulaError) self.assertEquals(context['_raise'], _raise) self.assertEquals(context['sys'], sys) self.assertEquals(context['worksheet'], worksheet) self.assertEquals(context['load_constants'], load_constants) self.assertEquals(context['undefined'], undefined) evaluate_formulae = context['evaluate_formulae'] evaluate_formulae(sentinel.worksheet) self.assertEquals(mock_evaluate_formulae_in_context.call_args, ((sentinel.worksheet, context), {}))
def test_sheet_to_value_only_json_with_content(self): worksheet = Worksheet() worksheet[2, 1].formula = 'Row 1, col 2 formula' worksheet[2, 1].value = 'Row 1, col 2 value' worksheet[10, 1].formula = 'Row 1, col 10 formula' worksheet[10, 1].value = 'Row 1, col 10 value' worksheet[1, 5].formula = 'Row 5, col 1 formula' worksheet[1, 5].value = 'Row 5, col 1 value' worksheet[10, 5].formula = u'Row 5, col 10 formula avec un \xe9' worksheet[10, 5].value = u'Row 5, col 10 value avec un autre \xe9' expected_json_contents = { 'name': "Sheet name", '1': { '5': "Row 5, col 1 value", }, '2': { '1': "Row 1, col 2 value", }, '10': { '1': "Row 1, col 10 value", '5': u"Row 5, col 10 value avec un autre \xe9", } } result = _sheet_to_value_only_json("Sheet name", worksheet) self.assertEquals(json.loads(result), expected_json_contents)
def test_should_return_errors_and_no_values_if_unjsonify_worksheet_result_has_errors(self, mock_get_object): mock_sheet = mock_get_object.return_value mock_sheet.owner = self.user worksheet = Worksheet() worksheet[1, 3].formula = '=string' worksheet[1, 3].value = 'test value' worksheet._usercode_error = { "message": "I am an error message", "line": 2 } mock_sheet.unjsonify_worksheet.side_effect = lambda: worksheet mock_sheet.allow_json_api_access = True self.request.method = 'POST' self.request.POST['api_key'] = mock_sheet.api_key = 'key' expected_json = { "usercode_error" : { "message": "I am an error message", "line": "2" } } actual = calculate_and_get_json_for_api(self.request, self.user.username, self.sheet.id) self.assertFalse(mock_sheet.save.called) self.assertTrue(isinstance(actual, HttpResponse)) self.assertEquals(actual.content, json.dumps(expected_json))
def test_should_call_sheet_calculate_with_transaction( self, mock_get_object, mock_transaction ): mock_sheet = mock_get_object.return_value mock_sheet.owner = self.user mock_sheet.allow_json_api_access = True transaction = Mock() def wrapper(view): def inner(*_, **__): view(*_, **__) return inner mock_transaction.commit_manually = wrapper self.request.method = 'POST' self.request.POST['api_key'] = mock_sheet.api_key = 'key' mock_sheet.unjsonify_worksheet.return_value = Worksheet() response = calculate_and_get_json_for_api(self.request, self.user.username, self.sheet.id) self.assertEquals( mock_sheet.calculate.call_args_list, [((), {})] ) self.assertCalledOnce(mock_transaction.commit)
def test_run_worksheet_with_overrides(self, mock_api_json_to_worksheet, mock_urllib2, mock_urlencode): overrides = {'a1': 55} str_overrides = { 'a1': '55', 'dirigible_l337_private_key': sentinel.private_key } mock_api_json_to_worksheet.return_value = Worksheet() worksheet_url = 'ws_url/' target_url = '%sv%s/json/' % (worksheet_url, CURRENT_API_VERSION) result = run_worksheet(worksheet_url, overrides, sentinel.private_key) self.assertCalledOnce(mock_urllib2.build_opener) mock_opener = mock_urllib2.build_opener.return_value self.assertCalledOnce(mock_urlencode, str_overrides) encoded_overrides = mock_urlencode.return_value self.assertCalledOnce(mock_opener.open, target_url, data=encoded_overrides) mock_urlopen_file = mock_opener.open.return_value self.assertCalledOnce(mock_api_json_to_worksheet, mock_urlopen_file.read.return_value) self.assertEquals(result, mock_api_json_to_worksheet.return_value)
def test_should_put_data_into_existing_worksheet_with_offset_for_excel_and_auto( self): for excel_encoding in [True, False]: csv = StringIO() csv.write('abc,123\n') csv.write('def, \n') csv.size = 10 csv.seek(0) existing_worksheet = Worksheet() for row in range(1, 6): for col in range(1, 5): existing_worksheet[col, row].formula = 'old' worksheet = worksheet_from_csv(existing_worksheet, csv, 2, 3, excel_encoding) self.assertEquals(worksheet.A1.formula, 'old') self.assertEquals(worksheet.B1.formula, 'old') self.assertEquals(worksheet.A2.formula, 'old') self.assertEquals(worksheet.B3.formula, 'abc') self.assertEquals(worksheet.C3.formula, '123') self.assertEquals(worksheet.B4.formula, 'def') self.assertEquals(worksheet.C4.formula, ' ') self.assertEquals(worksheet.C5.formula, 'old') self.assertEquals(worksheet.D3.formula, 'old') self.assertEquals(worksheet.B5.formula, 'old')
def test_cut_then_paste_same_sheet(self): sheet = Sheet() worksheet = Worksheet() worksheet.A1.formula = 'safe' worksheet.A2.formula = 'topleft' worksheet.B2.formula = 'topright' worksheet.A3.formula = 'bottomleft' worksheet.B3.formula = 'bottomright' sheet.jsonify_worksheet(worksheet) clipboard = Clipboard() clipboard.cut(sheet, (1, 2), (2, 3)) updated_worksheet = sheet.unjsonify_worksheet() self.assertEquals(updated_worksheet.A1.formula, 'safe') self.assertEquals(updated_worksheet.A2, Cell() ) self.assertEquals(updated_worksheet.B2, Cell() ) self.assertEquals(updated_worksheet.A3, Cell() ) clipboard.paste_to(sheet, (2, 3), (2, 3)) updated_worksheet = sheet.unjsonify_worksheet() self.assertEquals(updated_worksheet.A1.formula, 'safe') self.assertEquals(updated_worksheet.A2, Cell() ) self.assertEquals(updated_worksheet.B2, Cell() ) self.assertEquals(updated_worksheet.A3, Cell() ) self.assertEquals(updated_worksheet.B3.formula, 'topleft') self.assertEquals(updated_worksheet.C3.formula, 'topright') self.assertEquals(updated_worksheet.C4.formula, 'bottomright') self.assertEquals(updated_worksheet.B4.formula, 'bottomleft')
def test_cut_calls_copy_then_cuts_and_remembers_some_stuff(self): clipboard = Clipboard() sheet = Sheet() user = User() user.username = '******' user.save() sheet.owner = user clipboard.copy = Mock(wraps=clipboard.copy) worksheet = Worksheet() worksheet.A1.formula = 'outside' worksheet.A2.formula = 'inside' sheet.jsonify_worksheet(worksheet) sheet.save() clipboard.cut(sheet, (1, 2), (3, 4)) self.assertCalledOnce(clipboard.copy, sheet, (1, 2), (3, 4)) worksheet = sheet.unjsonify_worksheet() self.assertEquals(worksheet.A1.formula, 'outside') self.assertEquals(worksheet.A2, Cell()) self.assertEquals(clipboard.source_left, 1) self.assertEquals(clipboard.source_top, 2) self.assertEquals(clipboard.source_right, 3) self.assertEquals(clipboard.source_bottom, 4) self.assertEquals(clipboard.is_cut, True) self.assertEquals(clipboard.source_sheet, sheet)
def test_getting_bounds_with_two_cells_should_return_bounds(self): ws = Worksheet() ws[5, 3].value = "Top right" ws[3, 11].value = "Bottom left" self.assertEquals(type(ws.bounds), Bounds) self.assertEquals(ws.bounds, (3, 3, 5, 11))
def test_paste_to_for_cut_different_sheet(self): self.user = User() self.user.save() c2 = Cell() c2.formula = 'foo' c2.formatted_value = 'fv' d2 = Cell() d2.formula = 'fv to become formula' d2.formatted_value = d2.formula c3 = Cell() d3 = Cell() c5 = Cell() c5.formula = 'a safe source cell' dest_cells = { (3, 4): c2, (3, 5): c3, (4, 4): d2, (4, 5): d3, } source_sheet = Sheet() source_sheet.owner = self.user source_sheet.save() clipboard = Clipboard() clipboard.to_cells = Mock() clipboard.to_cells.return_value = dest_cells.iteritems() clipboard.is_cut = True clipboard.source_sheet = source_sheet clipboard.source_left = 3 clipboard.source_top = 2 clipboard.source_right = 4 clipboard.source_bottom = 3 destination_sheet = Sheet() destination_sheet.owner = self.user destination_worksheet = Worksheet() destination_worksheet.C4.formula = 'i am in danger!' destination_worksheet.A1.formula = 'i am safe :-)' destination_sheet.jsonify_worksheet(destination_worksheet) destination_sheet.save() clipboard.paste_to(destination_sheet, (3, 4), (3, 4)) updated_worksheet = destination_sheet.unjsonify_worksheet() self.assertEquals(updated_worksheet.A1.formula, 'i am safe :-)') self.assertEquals(updated_worksheet.C4.formula, c2.formula) self.assertEquals(updated_worksheet.D4.formula, d2.formula) self.assertEquals(updated_worksheet.C5.formula, c3.formula) self.assertEquals(updated_worksheet.d5.formula, d3.formula) # paste should reset the clipboard so that future pastes act as # though they came from a copy self.assertEquals(clipboard.source_left, 3) self.assertEquals(clipboard.source_top, 4) self.assertEquals(clipboard.source_right, 4) self.assertEquals(clipboard.source_bottom, 5) self.assertEquals(clipboard.is_cut, False) self.assertEquals(clipboard.source_sheet, None)
def test_two_tuple_parameters(self): ws = Worksheet() cell_range = ws.cell_range((2, 3), (5, 4)) self.assertEquals(cell_range.left, 2) self.assertEquals(cell_range.top, 3) self.assertEquals(cell_range.right, 5) self.assertEquals(cell_range.bottom, 4)
def test_clear_values_deletes_cells_with_empty_formula(self): ws = Worksheet() ws[1, 2].formula = '' ws[1, 2].value = "hello!" ws[1, 2].formatted_value = "Guten Tag!" ws.clear_values() self.assertFalse((1, 2) in ws)
def test_iteration_yields_cells(self): ws = Worksheet() ws[1, 1].formula = 'A1' ws[2, 4].formula = 'B4' ws.name = 'any old name' self.assertEquals(ws.items(), [((1, 1), ws[1, 1]), ((2, 4), ws[2, 4])])
def test_should_handle_empty_worksheet(self, mock_csv): ws = Worksheet() result = worksheet_to_csv(ws, encoding='ascii') mock_writer = mock_csv.writer.return_value self.assertFalse(mock_writer.writerow.called)
def test_clipboad_copy_retrieves_stuff_from_sheet_and_removes_offset(self): self.maxDiff = None clipboard = Clipboard() sheet = Sheet() worksheet = Worksheet() worksheet.C2.formula = 'foo' worksheet.C2.formatted_value = 'fv' worksheet.D2.formatted_value = 'fv to become formula' sheet.jsonify_worksheet(worksheet) start = (3, 2) end = (4, 3) cut_called_previously = True clipboard.is_cut = cut_called_previously clipboard.copy(sheet, start, end) self.assertEquals( json.loads(clipboard.contents_json), { '0,0':{'formula': 'foo', 'formatted_value': 'fv'}, '1,0':{'formula': 'fv to become formula', 'formatted_value': 'fv to become formula'}, '0,1':{'formula': '', 'formatted_value': ''}, '1,1':{'formula': '', 'formatted_value': ''} } ) self.assertEquals(clipboard.source_left, 3) self.assertEquals(clipboard.source_top, 2) self.assertEquals(clipboard.source_right, 4) self.assertEquals(clipboard.source_bottom, 3) self.assertEquals(clipboard.is_cut, False) self.assertEquals(clipboard.source_sheet, None)
def test_should_recursively_call_itself_on_dependencies_before_adding_dependencies_to_graph( self, mock_add_location_dependencies, mock_generate_cell_subgraph): mock_generate_cell_subgraph.copied_call_args_list = [] def mock_recalc_recursive_call(worksheet, context, loc, visited, path): self.assertFalse(mock_add_location_dependencies.called) mock_generate_cell_subgraph.copied_call_args_list.append( (worksheet, context, loc, set(visited), list(path))) mock_generate_cell_subgraph.side_effect = mock_recalc_recursive_call mock_generate_cell_subgraph_was_called_before_add_location_dependencies = [] def add_location_dependencies_side_effect(*_): mock_generate_cell_subgraph_was_called_before_add_location_dependencies.append( mock_generate_cell_subgraph.called) mock_add_location_dependencies.side_effect = add_location_dependencies_side_effect worksheet = Worksheet() worksheet[1, 11].formula = '=formula' worksheet[1, 11].dependencies = [(2, 22), (3, 33)] context = sentinel.context _generate_cell_subgraph(worksheet, context, (1, 11), set(), []) self.assertTrue(mock_add_location_dependencies.called) self.assertTrue( mock_generate_cell_subgraph_was_called_before_add_location_dependencies[ 0]) self.assertItemsEqual( mock_generate_cell_subgraph.copied_call_args_list, [ (worksheet, context, (2, 22), set(), [(1, 11)]), (worksheet, context, (3, 33), set(), [(1, 11)]), ])
def test_raises_on_attempting_to_encode_nonwestern_chars_to_excel_format(self): some_kanji = u'\u30bc\u30ed\u30a6\u30a3\u30f3\u30b0' ws = Worksheet() ws.a1.value = some_kanji self.assertRaises( UnicodeEncodeError, lambda : worksheet_to_csv(ws, encoding='windows-1252') )
def test_setattr_should_not_delegate_to_setitem_if_attr_name_is_not_valid_cell_name(self): ws = Worksheet() ws.__setitem__ = Mock() ws.A1 = 23 self.assertEquals( ws.__setitem__.call_args_list, [] ) self.assertEquals( ws.A1, 23 )
def test_to_ui_json_meta_data_ten_by_five_empty(self): sheet = Sheet(width=10, height=5) expected = dict(width=sheet.width, height=sheet.height, name='Untitled') self.assertEquals( json.loads(sheet_to_ui_json_meta_data(sheet, Worksheet())), expected)
def setUp(self): self.ws = ws = Worksheet() ws[1, 1].value = 'foist' ws[10, 100].value = 'second' ws[2, 3].value = 'middle1' ws[3, 3].value = 'middle2' ws[2, 4].value = 'raster test' ws[100, 100].value = 'way down here'
def test_constant(self): worksheet = Worksheet() worksheet[1, 2].formula = '3' calculate(worksheet, SANITY_CHECK_USERCODE % ('', ''), sentinel.private_key) self.assertEquals(worksheet.keys(), [(1, 2)]) self.assertEquals(worksheet[(1, 2)].formula, '3') self.assertEquals(worksheet[(1, 2)].value, 3)
def test_setitem_on_locations_should_reject_non_cell_instances(self): ws = Worksheet() ws.to_location = Mock(return_value=(1, 2)) expected_message_re = "^Worksheet locations must be Cell objects" with self.assertRaisesRegexp(TypeError, expected_message_re): ws[3, 4] = 123 self.assertEquals(ws.to_location.call_args_list, [(((3, 4),), {})])
def test_getattr_should_delegate_to_getitem(self): ws = Worksheet() ws.__getitem__ = Mock() retval = ws.A1 self.assertEquals( retval, ws.__getitem__.return_value ) self.assertEquals( ws.__getitem__.call_args_list, [(('A1',), {})] )
def test_to_ui_json_meta_data_zero_size(self): sheet = Sheet(width=0, height=0) expected = dict(width=sheet.width, height=sheet.height, name='Untitled') self.assertEquals( json.loads(sheet_to_ui_json_meta_data(sheet, Worksheet())), expected)
def test_run_worksheet_with_overrides(self, mock_urllib2): self.maxDiff = None cellA2 = Cell() cellA2.formula = '1' cellA2.value = 1 cellC3 = Cell() cellC3.formula = '5' cellC3.value = 5 cellE4 = Cell() cellE4.formula = '=A2 + C3' cellE4.value = 6 overrides = { (1, 2): '11', (3, 3): 55, (4, 1): '="abc"', 'dirigible_l337_private_key': sentinel.private_key } result_of_calculation_json = '''{ "name": "Untitled", "1": { "2": 11 }, "3": { "3": 55 }, "4": { "1": "abc" }, "5": { "4": 66 } }''' mock_opener = mock_urllib2.build_opener.return_value mock_urlopen_file = mock_opener.open.return_value mock_urlopen_file.read.return_value = result_of_calculation_json worksheet_url = 'ws_url/' result = run_worksheet(worksheet_url, overrides, sentinel.private_key) target_url = '%sv%s/json/' % (worksheet_url, CURRENT_API_VERSION) self.assertCalledOnce(mock_opener.open, target_url, data=urlencode(overrides)) self.assertEquals(type(result), Worksheet) expected_sheet = Worksheet() expected_sheet.name = 'Untitled' expected_sheet[1, 2].value = 11 expected_sheet[3, 3].value = 55 expected_sheet[4, 1].value = 'abc' expected_sheet[5, 4].value = 66 self.assertEquals(result, expected_sheet)
def test_should_not_reraise_cycle_error_if_its_outside_the_cycle_path( self, mock_report_cell_error, mock_recursive_call): cycle_error = CycleError([(1, 2), (3, 4), (1, 2)]) worksheet = Worksheet() worksheet[1, 3].formula = "=foo" mock_recursive_call.side_effect = die(cycle_error) _generate_cell_subgraph(worksheet, sentinel.graph, (1, 3), set(), []) # should not raise
def test_should_add_cell_to_graph_if_formula_not_set_but_python_formula_is( self, mock_add_location_dependencies): worksheet = Worksheet() worksheet[1, 2].python_formula = 'blerk' _generate_cell_subgraph(worksheet, sentinel.graph, (1, 2), set(), []) self.assertCalledOnce(mock_add_location_dependencies, sentinel.graph, (1, 2), set())