def test_sheet_name_not_set_on_save_if_name_is_not_default(self): user = User(username='******') user.save() sheet = Sheet(owner=user) sheet.name = 'new sheet name' sheet.save() self.assertEquals(sheet.name, 'new sheet name')
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_jsonify_worksheet_should_write_json_to_contents_json_field(self, mock_worksheet_to_json): sheet = Sheet() sheet.jsonify_worksheet(sentinel.worksheet) self.assertCalledOnce(mock_worksheet_to_json, sentinel.worksheet) self.assertEquals(sheet.contents_json, mock_worksheet_to_json.return_value)
def test_uuid_stays_constant_between_reads(self): sheet = Sheet() user = User(username='******') user.save() sheet.owner = user sheet.save() sheet2 = Sheet.objects.get(pk=sheet.id) self.assertEquals(sheet.api_key, sheet2.api_key)
def test_unjsonify_worksheet_should_return_worksheet(self, mock_worksheet_from_json): sheet = Sheet() sheet.contents_json = sentinel.contents_json worksheet = sheet.unjsonify_worksheet() self.assertEquals(worksheet, mock_worksheet_from_json.return_value) self.assertCalledOnce(mock_worksheet_from_json, sentinel.contents_json)
def test_to_ui_json_meta_data_includes_columns_widths(self): sheet = Sheet(width=10, height=5) sheet.column_widths = {u'1': 1, u'2': 22, u'3': 333} expected = dict( width=sheet.width, height=sheet.height, name='Untitled', column_widths=sheet.column_widths, ) self.assertEquals(json.loads(sheet_to_ui_json_meta_data(sheet, Worksheet())), expected)
def test_to_ui_json_meta_data_includes_columns_widths(self): sheet = Sheet(width=10, height=5) sheet.column_widths = {u'1': 1, u'2': 22, u'3': 333} expected = dict( width=sheet.width, height=sheet.height, name='Untitled', column_widths=sheet.column_widths, ) self.assertEquals( json.loads(sheet_to_ui_json_meta_data(sheet, Worksheet())), expected)
def test_unicode(self): user = User(username='******') user.save() sheet = Sheet(owner=user, name='sheet to feature') sheet.save() description = 'twas brillig and the slithy toves' more_info_url = 'http://far.away/' fs = FeaturedSheet(sheet=sheet, description=description, more_info_url=more_info_url) fs.save() self.assertEquals(unicode(fs), u'Feature: %s' % (sheet.name,))
def edit_sheet(request, sheet_id=None): """ If sheet_id != None it edit the sheet otherwise it create a new one. """ c = {} if sheet_id: if request.method == "GET": form = SheetForm(request.GET) if form.is_valid(): this_sheet = Sheet.objects.get(id=sheet_id) this_sheet.title = form.cleaned_data['title'] this_sheet.description = form.cleaned_data['description'] this_sheet.s_public = form.cleaned_data['is_public'] this_sheet.save() if int(request.GET.get('show', False)): return HttpResponseRedirect('../{0}'.format(sheet_id)) else: return HttpResponseRedirect('../res') else: c['sheet_id'] = sheet_id this_sheet = Sheet.objects.get(id=sheet_id) init = {} init['title'] = this_sheet.title init['description'] = this_sheet.description init['is_public'] = this_sheet.is_public form = SheetForm(initial=init) c['form'] = form c['show'] = int(request.GET.get('show', False)) else: if request.method == "GET": form = SheetForm(request.GET) if form.is_valid(): this_sheet = Sheet(title=form.cleaned_data['title'], description=form.cleaned_data['description'], is_public=form.cleaned_data['is_public']) this_sheet.save() this_user = User.objects.get(username=request.user.username) this_sheet.user.add(this_user) this_sheet.save() return HttpResponseRedirect(str(this_sheet.id)) else: form = SheetForm() c['form'] = form c['show'] = int(request.GET.get('show', False)) if request.is_ajax(): t = 'edit.html' else: t = 'home.html' try: c['sm_user'] = request.session['sm_user'] except: pass c['content'] = 'edit.html' return render_to_response(t, c)
def test_can_construct_without_more_info_url(self): user = User(username='******') user.save() sheet = Sheet(owner=user, name='sheet to feature') sheet.save() description = 'twas brillig and the slithy toves' fs = FeaturedSheet(sheet=sheet, description=description) fs.save() self.assertEquals(fs.sheet, sheet) self.assertEquals(fs.description, description) self.assertEquals(fs.more_info_url, '')
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_can_construct_with_more_info_url(self): user = User(username='******') user.save() sheet = Sheet(owner=user, name='sheet to feature') sheet.save() description = 'twas brillig and the slithy toves' more_info_url = 'http://far.away/' fs = FeaturedSheet(sheet=sheet, description=description, more_info_url=more_info_url) fs.save() self.assertEquals(fs.sheet, sheet) self.assertEquals(fs.description, description) self.assertEquals(fs.more_info_url, more_info_url)
def test_calculate_always_deletes_private_key_in_finally_block( self, mock_calculate ): def raiser(*a, **kw): raise Exception() mock_calculate.side_effect = raiser sheet = Sheet() user = User(username='******') user.save() sheet.owner = user sheet._delete_private_key = Mock() self.assertRaises(Exception, sheet.calculate) self.assertCalledOnce(sheet._delete_private_key)
def test_merge_non_calc_attrs_should_copy_some_attrs(self): s1 = Sheet() s1.name = 's1' s1.column_widths = {'s1': 0} s1.contents_json = sentinel.sheet1 s2 = Sheet() s2.name = 's2' s2.column_widths = {'s2': 0} s2.contents_json = sentinel.sheet2 s1.merge_non_calc_attrs(s2) self.assertEquals(s1.name, 's2') self.assertEquals(s1.column_widths, {'s2': 0}) self.assertEquals(s1.contents_json, sentinel.sheet1)
def test_formulae_are_rewritten(self, mock_rewrite): mock_rewrite.return_value = '=C8' sheet = Sheet() worksheet = Worksheet() worksheet.A1.formula = '=B6' sheet.jsonify_worksheet(worksheet) clipboard = Clipboard() clipboard.copy(sheet, (1, 1), (1, 1)) clipboard.paste_to(sheet, (2, 3), (2, 3)) self.assertCalledOnce( mock_rewrite, '=B6', 1, 2, False, (1, 1, 1, 1) )
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 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_sheet_organization(self): campaigns = Sheet.get_by_campaign(self.admin) self.assertListEqual([u"FRP", u"MR"], [campaign.name for campaign in campaigns]) self.assertListEqual([u"Martel", u"Yukaghir", u"Asa"], [ sheet.character.name for campaign in campaigns for sheet in campaign.objects ])
def test_to_ui_json_meta_data_includes_worksheet_console_text(self): sheet = Sheet(width=10, height=5) worksheet = Worksheet() worksheet._console_text = ['error1', 'error2'] expected = dict(width=sheet.width, height=sheet.height, name='Untitled', console_text=worksheet._console_text) self.assertEquals( json.loads(sheet_to_ui_json_meta_data(sheet, worksheet)), expected)
def test_paste_to_should_tile_clipboard_contents_across_selected_range(self): sheet = Sheet() worksheet = Worksheet() worksheet.A1.formula = '=c1' worksheet.B1.formula = '=d1' worksheet.A2.formula = '=c2' worksheet.B2.formula = '=d2' sheet.jsonify_worksheet(worksheet) clipboard = Clipboard() clipboard.copy(sheet, (1, 1), (2, 2)) clipboard.paste_to(sheet, (3, 3), (5, 7)) worksheet = sheet.unjsonify_worksheet() self.assertEquals(worksheet.C3.formula, '=E3') self.assertEquals(worksheet.D3.formula, '=F3') self.assertEquals(worksheet.E3.formula, '=G3') self.assertEquals(worksheet.F3.formula, None) self.assertEquals(worksheet.C4.formula, '=E4') self.assertEquals(worksheet.D4.formula, '=F4') self.assertEquals(worksheet.E4.formula, '=G4') self.assertEquals(worksheet.F4.formula, None) self.assertEquals(worksheet.C5.formula, '=E5') self.assertEquals(worksheet.D5.formula, '=F5') self.assertEquals(worksheet.E5.formula, '=G5') self.assertEquals(worksheet.F5.formula, None) self.assertEquals(worksheet.C6.formula, '=E6') self.assertEquals(worksheet.D6.formula, '=F6') self.assertEquals(worksheet.E6.formula, '=G6') self.assertEquals(worksheet.F6.formula, None) self.assertEquals(worksheet.C7.formula, '=E7') self.assertEquals(worksheet.D7.formula, '=F7') self.assertEquals(worksheet.E7.formula, '=G7') self.assertEquals(worksheet.F7.formula, None) self.assertEquals(worksheet.C8.formula, None) self.assertEquals(worksheet.D8.formula, None) self.assertEquals(worksheet.E8.formula, None) self.assertEquals(worksheet.F8.formula, None)
def test_paste_from_copy_does_not_rewrite_source_sheet_formulae( self, mock_rewrite_source_sheet_formulae): source_worksheet = Worksheet() source_worksheet.A1.formula = '=pre-rewrite' source_sheet = Sheet() source_sheet.jsonify_worksheet(source_worksheet) clipboard = Clipboard() clipboard.copy(source_sheet, (1, 2), (3, 5)) clipboard.to_cells = Mock() clipboard.to_cells.return_value = {}.items() def check_to_cells_not_run(*args): self.assertFalse(clipboard.to_cells.call_args_list) mock_rewrite_source_sheet_formulae.side_effect = check_to_cells_not_run clipboard.paste_to(source_sheet, (2, 3), (2, 3)) self.assertFalse( mock_rewrite_source_sheet_formulae.called )
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_paste_to_for_copy(self): 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() cells = { (2, 2): c2, (2, 3): c3, (3, 2): d2, (3, 3): d3, } clipboard = Clipboard() clipboard.source_left = 1 clipboard.source_top = 1 clipboard.source_right = 2 clipboard.source_bottom = 2 clipboard.to_cells = Mock() clipboard.to_cells.return_value = cells.iteritems() sheet = Sheet() worksheet = Worksheet() worksheet.B3.formula = 'i am in danger!' worksheet.A1.formula = 'i am safe :-)' sheet.jsonify_worksheet(worksheet) clipboard.paste_to(sheet, (2, 2), (2, 2)) updated_worksheet = sheet.unjsonify_worksheet() self.assertEquals(updated_worksheet.A1.formula, 'i am safe :-)') self.assertEquals(updated_worksheet.B2.formula, c2.formula) self.assertEquals(updated_worksheet.C2.formula, d2.formula) self.assertEquals(updated_worksheet.B3.formula, c3.formula) self.assertEquals(updated_worksheet.C3.formula, d3.formula)
def test_roundtrip_column_widths_to_db(self, mock_json): COLUMN_WIDTHS = {'1': 11, '2': 22, '3': 33} mock_json.loads.return_value = COLUMN_WIDTHS mock_json.dumps.return_value = sentinel.json user = User(username='******') user.save() sheet = Sheet(owner=user) DEFAULT_COLUMN_WIDTHS_JSON = '{}' self.assertEquals( mock_json.loads.call_args, ((DEFAULT_COLUMN_WIDTHS_JSON,), {}) ) sheet.column_widths = COLUMN_WIDTHS sheet.save() self.assertEqual( mock_json.dumps.call_args, ((COLUMN_WIDTHS,), {}) ) pk = sheet.id sheet2 = Sheet.objects.get(pk=pk) self.assertEquals(sheet2.column_widths, COLUMN_WIDTHS)
def test_run_worksheet_should_return_worksheet_with_calculated_values_only(self, mock_urllib2): self.maxDiff = None original_sheet = Worksheet() original_sheet.A2.formula = '1' original_sheet.A2.value = 1 original_sheet.C3.formula = '5' original_sheet.C3.value = 5 original_sheet.E4.formula = '=A2 + C3' original_sheet.E4.value = 6 expected_sheet = Worksheet() expected_sheet.name = 'Untitled' for (col, row), cell in original_sheet.items(): expected_sheet[col, row].value = cell.value foreign_sheet = Sheet() foreign_sheet.owner = User(username='******', password='******') foreign_sheet.owner.save() foreign_sheet.contents_json = worksheet_to_json(original_sheet) foreign_sheet.calculate() mock_opener = mock_urllib2.build_opener.return_value mock_urlopen_file = mock_opener.open.return_value mock_urlopen_file.read.return_value = _sheet_to_value_only_json( foreign_sheet.name, worksheet_from_json(foreign_sheet.contents_json) ) worksheet_url = 'ws_url/' result = run_worksheet(worksheet_url, None, sentinel.private_key) target_url = '%sv%s/json/' % (worksheet_url, CURRENT_API_VERSION) self.assertCalledOnce(mock_opener.open, target_url, data=urlencode({'dirigible_l337_private_key': sentinel.private_key})) self.assertEquals(type(result), Worksheet) self.assertEquals(result, expected_sheet)
def test_calculate_calls_calculate_with_unjsonified_worksheet_and_saves_recalced_json( self, mock_calculate ): sheet = Sheet() sheet.jsonify_worksheet = Mock() sheet.unjsonify_worksheet = Mock() sheet.usercode = sentinel.usercode sheet.timeout_seconds = sentinel.timeout_seconds sheet.create_private_key = Mock() sheet.otp = Mock() sheet.calculate() self.assertCalledOnce( mock_calculate, sheet.unjsonify_worksheet.return_value, sheet.usercode, sheet.timeout_seconds, sheet.create_private_key.return_value ) self.assertCalledOnce(sheet.jsonify_worksheet, sheet.unjsonify_worksheet.return_value)
def test_delete_private_key_does(self): self.assertEquals(len(OneTimePad.objects.all()), 0) sheet = Sheet() user = User(username='******') user.save() sheet.owner = user sheet.create_private_key() self.assertEquals(len(OneTimePad.objects.all()), 1) sheet._delete_private_key() self.assertEquals(len(OneTimePad.objects.all()), 0)
def test_to_ui_json_meta_data_includes_usercode_errors(self): sheet = Sheet(width=10, height=5) worksheet = Worksheet() worksheet._usercode_error = {'message': 'ABC', 'line': 123} expected_json_contents = { 'width': sheet.width, 'height': sheet.height, 'name': sheet.name, 'usercode_error': { 'message': 'ABC', 'line': '123' } } self.assertEquals( json.loads(sheet_to_ui_json_meta_data(sheet, worksheet)), expected_json_contents)
def test_create_private_key_uses_onetimepad(self): sheet = Sheet() sheet.version = 155 user = User(username='******') user.set_password('glurk') user.save() sheet.owner = user self.assertEquals(len(OneTimePad.objects.all()), 0) self.assertEquals( sheet.create_private_key(), OneTimePad.objects.get(user=sheet.owner).guid) sheet._delete_private_key()
def test_should_handle_cell_formula_overrides_from_GET(self, mock_get_object): mock_sheet = mock_get_object.return_value = Sheet() mock_sheet.owner = self.user worksheet = Worksheet() worksheet[1, 1].formula = 'initial-formula1' worksheet[2, 1].formula = '222' worksheet[3, 1].formula = '=B1+111' mock_sheet.jsonify_worksheet(worksheet) mock_sheet.name = 'mysheet' mock_sheet.allow_json_api_access = True mock_sheet.api_key = 'key' mock_sheet.save = self.die self.request.GET = { u'1,1':u'overriddenformula', u'D1':u'=B1+222', 'api_key': 'key' } self.request.method = 'GET' response = calculate_and_get_json_for_api(self.request, self.user.username, self.sheet.id) self.assertTrue(isinstance(response, HttpResponse)) expected_json = { 'name': 'mysheet', '1' : { '1': 'overriddenformula', }, '2': { '1': 222, }, '3': { '1': 333, }, '4': { '1': 444, }, } self.assertEquals(json.loads(response.content), expected_json)
def test_run_worksheet_should_return_worksheet_with_calculated_values_only( self, mock_urllib2): self.maxDiff = None original_sheet = Worksheet() original_sheet.A2.formula = '1' original_sheet.A2.value = 1 original_sheet.C3.formula = '5' original_sheet.C3.value = 5 original_sheet.E4.formula = '=A2 + C3' original_sheet.E4.value = 6 expected_sheet = Worksheet() expected_sheet.name = 'Untitled' for (col, row), cell in original_sheet.items(): expected_sheet[col, row].value = cell.value foreign_sheet = Sheet() foreign_sheet.owner = User(username='******', password='******') foreign_sheet.owner.save() foreign_sheet.contents_json = worksheet_to_json(original_sheet) foreign_sheet.calculate() mock_opener = mock_urllib2.build_opener.return_value mock_urlopen_file = mock_opener.open.return_value mock_urlopen_file.read.return_value = _sheet_to_value_only_json( foreign_sheet.name, worksheet_from_json(foreign_sheet.contents_json)) worksheet_url = 'ws_url/' result = run_worksheet(worksheet_url, None, sentinel.private_key) target_url = '%sv%s/json/' % (worksheet_url, CURRENT_API_VERSION) self.assertCalledOnce(mock_opener.open, target_url, data=urlencode({ 'dirigible_l337_private_key': sentinel.private_key })) self.assertEquals(type(result), Worksheet) self.assertEquals(result, expected_sheet)
def test_copy_sheet_allows_other_users_to_copy_public_sheets(self): user = User(username='******') user.save() worksheet = Worksheet() worksheet.a1.value = 'some-cell-content' sheet = Sheet() sheet.owner = user sheet.is_public = True sheet.jsonify_worksheet(worksheet) sheet.save() original_sheet_id = sheet.id other_user = User(username='******') other_user.save() retval = copy_sheet_to_user(sheet, other_user) other_user_sheets = Sheet.objects.filter(owner=other_user) self.assertEquals(len(other_user_sheets), 1) copied_sheet = other_user_sheets[0] self.assertFalse(copied_sheet.is_public) copied_worksheet = copied_sheet.unjsonify_worksheet() self.assertEquals(copied_worksheet.a1.value, 'some-cell-content') self.assertEquals(copied_sheet.id, retval.id) self.assertNotEquals(retval.id, original_sheet_id)
def test_unicode(self): user = User(username='******') user.save() sheet = Sheet(owner=user, name='the new sheet name') sheet.save() self.assertEquals(unicode(sheet), 'Sheet %d: %s' % (sheet.id, sheet.name))
def test_sheet_name_set_on_save_if_name_is_default(self): user = User(username='******') user.save() sheet = Sheet(owner=user) sheet.save() self.assertEquals(sheet.name, 'Sheet %d' % (sheet.id,))
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_clipboard_remembers_to_close_stingIO_stream(self, mock_stringio): sheet = Sheet() clipboard = Clipboard() mock_stringio.StringIO.return_value = Mock() clipboard.copy(sheet, (1, 1), (1, 1)) self.assertCalledOnce(mock_stringio.StringIO.return_value.close)