def test_simple_json_with_overrides_get(self): # * Harold wants to use Dirigible to run his spreadsheets using # a json-based rest API, and override the formula of some cells # * He logs in to Dirigible and creates a new sheet sheet_id = self.login_and_create_new_sheet() # * He enables json api access for the sheet self.enable_json_api_for_sheet() # * He enters some values and formulae self.enter_cell_text(1, 1, "5") # A1 self.enter_cell_text(1, 2, "abc") # A2 self.enter_cell_text(2, 1, "6") # B1 self.enter_cell_text(3, 1, "=a1 + b1") # C1 self.wait_for_cell_value(3, 1, "11") # * He uses an API call to get the sheet as JSON # but overrides the values of cells using GET params: # B1=11 # C2=A1 + 1 # this also causes cell C1 to change value, since it # depends on B1 get_params = urlencode({"2,1": "11", "C2": "=A1 + 1", "api_key": self.get_my_username()}) url = "%s?%s" % (Url.api_url(self.get_my_username(), sheet_id), get_params) try: sheet_content = json.load(urlopen(url)) except Exception, e: self.fail(str(e))
def test_simple_json_with_overrides_get(self): # * Harold wants to use Dirigible to run his spreadsheets using # a json-based rest API, and override the formula of some cells # * He logs in to Dirigible and creates a new sheet sheet_id = self.login_and_create_new_sheet() # * He enables json api access for the sheet self.enable_json_api_for_sheet() # * He enters some values and formulae self.enter_cell_text(1, 1, '5') # A1 self.enter_cell_text(1, 2, 'abc') # A2 self.enter_cell_text(2, 1, '6') # B1 self.enter_cell_text(3, 1, '=a1 + b1') # C1 self.wait_for_cell_value(3, 1, '11') # * He uses an API call to get the sheet as JSON # but overrides the values of cells using GET params: # B1=11 # C2=A1 + 1 # this also causes cell C1 to change value, since it # depends on B1 get_params = urlencode({'2,1':'11', 'C2':'=A1 + 1', 'api_key': self.get_my_username()}) url = '%s?%s' % (Url.api_url(self.get_my_username(), sheet_id), get_params) try: sheet_content = json.load(urlopen(url)) except Exception, e: self.fail(str(e))
def test_simple_json_with_error(self): # * Harold wants to use Dirigible to run his spreadsheets using # a json-based rest API, and wants the error-handling to be # well-defined (if perhaps not ideal from a debugging perspective) # * He logs in to Dirigible and creates a new sheet sheet_id = self.login_and_create_new_sheet() # * He enables json api access for the sheet self.enable_json_api_for_sheet() # * He enters a single formula operating on a single value self.enter_cell_text(1, 1, '5') self.enter_cell_text(1, 2, '=1/A1') self.wait_for_cell_value(1, 2, '0.2') # * He uses an API call to get the sheet as JSON, passing in an override # value that he knows will cause an error get_params = urlencode({'A1':'0', 'api_key': self.get_my_username()}) url = '%s?%s' % (Url.api_url(self.get_my_username(), sheet_id), get_params) try: sheet_content = json.load(urlopen(url)) except Exception, e: self.fail(str(e))
def test_simple_json(self): # * Harold wants to use Dirigible to run his spreadsheets using # a json-based rest API # * He logs in to Dirigible and creates a new sheet sheet_id = self.login_and_create_new_sheet() # * He enables json api access for the sheet self.enable_json_api_for_sheet() # * He enters some values and formulae self.enter_cell_text(1, 1, '5') self.enter_cell_text(1, 2, 'abc') self.enter_cell_text(2, 1, '6') self.enter_cell_text(3, 1, '=a1 + b1') self.wait_for_cell_value(3, 1, '11') # * He uses an API call to get the sheet as JSON sheet_content = json.load(urlopen(Url.api_url(self.get_my_username(), sheet_id), data=urlencode({'api_key': self.get_my_username()}))) expected = { 'name' : 'Sheet %s' % (sheet_id,), '1': { '1': 5, '2': 'abc' }, '2': { '1': 6, }, '3': { '1': 11 }, } self.assertEquals(sheet_content, expected)
def assert_copy_and_paste(self, operation, source_sheet, dest_sheet=None, dest_location=None, to_set='formula'): if dest_sheet is None: dest_sheet = source_sheet # he populates some cells using usercode (because the test runs faster) orig_usercode = self.get_usercode() self.prepend_usercode( dedent(''' for row in range(3, 6): for col in 'BC': worksheet[col, row].%s = '%%s%%d' %% (col, row) ''' % (to_set, ))) self.wait_for_cell_value(2, 3, 'B3') if to_set == 'formula': self.enter_usercode(orig_usercode) self.wait_for_spinner_to_stop() # he copies (or cuts) a region from one place operation((2, 3), (3, 5)) # If he's cutting, it disappears if operation == self.cut_range: self.wait_for_cell_value(2, 3, '') self.wait_for_cell_value(3, 3, '') self.wait_for_cell_value(2, 4, '') self.wait_for_cell_value(3, 4, '') self.wait_for_cell_value(2, 5, '') self.wait_for_cell_value(3, 5, '') # ...and pastes it elsewhere if dest_sheet != source_sheet: self.go_to_url(Url.sheet_page(self.get_my_username(), dest_sheet)) self.wait_for_grid_to_appear() self.paste_range(dest_location) # the destination is populated c, r = dest_location self.wait_for_cell_value(c, r, 'B3') self.wait_for_cell_value(1 + c, r, 'C3') self.wait_for_cell_value(c, 1 + r, 'B4') self.wait_for_cell_value(1 + c, 1 + r, 'C4') self.wait_for_cell_value(c, 2 + r, 'B5') self.wait_for_cell_value(1 + c, 2 + r, 'C5')
def assert_copy_and_paste(self, operation, source_sheet, dest_sheet=None, dest_location=None, to_set="formula"): if dest_sheet is None: dest_sheet = source_sheet # he populates some cells using usercode (because the test runs faster) orig_usercode = self.get_usercode() self.prepend_usercode( dedent( """ for row in range(3, 6): for col in 'BC': worksheet[col, row].%s = '%%s%%d' %% (col, row) """ % (to_set,) ) ) self.wait_for_cell_value(2, 3, "B3") if to_set == "formula": self.enter_usercode(orig_usercode) self.wait_for_spinner_to_stop() # he copies (or cuts) a region from one place operation((2, 3), (3, 5)) # If he's cutting, it disappears if operation == self.cut_range: self.wait_for_cell_value(2, 3, "") self.wait_for_cell_value(3, 3, "") self.wait_for_cell_value(2, 4, "") self.wait_for_cell_value(3, 4, "") self.wait_for_cell_value(2, 5, "") self.wait_for_cell_value(3, 5, "") # ...and pastes it elsewhere if dest_sheet != source_sheet: self.go_to_url(Url.sheet_page(self.get_my_username(), dest_sheet)) self.wait_for_grid_to_appear() self.paste_range(dest_location) # the destination is populated c, r = dest_location self.wait_for_cell_value(c, r, "B3") self.wait_for_cell_value(1 + c, r, "C3") self.wait_for_cell_value(c, 1 + r, "B4") self.wait_for_cell_value(1 + c, 1 + r, "C4") self.wait_for_cell_value(c, 2 + r, "B5") self.wait_for_cell_value(1 + c, 2 + r, "C5")
def test_copy_and_paste_to_new_sheet(self): # * Harold logs in to Dirigible and creates a new sheet dest_sheet = self.login_and_create_new_sheet() source_sheet = self.create_new_sheet() self.assert_copy_and_paste(self.copy_range, source_sheet, dest_sheet, dest_location=(3, 4)) # the cells in the original sheet are all still there self.go_to_url(Url.sheet_page(self.get_my_username(), source_sheet)) self.wait_for_grid_to_appear() self.wait_for_cell_value(2, 3, "B3") self.wait_for_cell_value(2, 4, "B4") self.wait_for_cell_value(2, 5, "B5") self.wait_for_cell_value(3, 3, "C3") self.wait_for_cell_value(3, 4, "C4") self.wait_for_cell_value(3, 5, "C5")
def test_access_sheet_with_incorrect_user_id(self): ## Create sheet as user 1, for the rest of the test harriet = self.get_my_usernames()[1] harold = self.get_my_username() sheet_id = self.login_and_create_new_sheet(username=harriet) self.logout() harolds_broken_sheet_url = Url.sheet_page(harold, sheet_id) # Before logging in, Harold tries to access one of Harriet's sheets # using the wrong direct URL, with his username but the correct sheet ID. # He gets a 404 self.assert_HTTP_error(harolds_broken_sheet_url, 404) # After logging in, Harold tries to access one of Harriet's sheets # using the wrong direct URL, with his username but the correct sheet ID. # He gets a 404. self.login(username=harold) self.assert_HTTP_error(harolds_broken_sheet_url, 404)
def test_copy_and_paste_to_new_sheet(self): # * Harold logs in to Dirigible and creates a new sheet dest_sheet = self.login_and_create_new_sheet() source_sheet = self.create_new_sheet() self.assert_copy_and_paste(self.copy_range, source_sheet, dest_sheet, dest_location=(3, 4)) # the cells in the original sheet are all still there self.go_to_url(Url.sheet_page(self.get_my_username(), source_sheet)) self.wait_for_grid_to_appear() self.wait_for_cell_value(2, 3, 'B3') self.wait_for_cell_value(2, 4, 'B4') self.wait_for_cell_value(2, 5, 'B5') self.wait_for_cell_value(3, 3, 'C3') self.wait_for_cell_value(3, 4, 'C4') self.wait_for_cell_value(3, 5, 'C5')
def test_simple_json(self): # * Harold wants to use Dirigible to run his spreadsheets using # a json-based rest API # * He logs in to Dirigible and creates a new sheet sheet_id = self.login_and_create_new_sheet() # * He enables json api access for the sheet self.enable_json_api_for_sheet() # * He enters some values and formulae self.enter_cell_text(1, 1, "5") self.enter_cell_text(1, 2, "abc") self.enter_cell_text(2, 1, "6") self.enter_cell_text(3, 1, "=a1 + b1") self.wait_for_cell_value(3, 1, "11") # * He uses an API call to get the sheet as JSON sheet_content = json.load( urlopen(Url.api_url(self.get_my_username(), sheet_id), data=urlencode({"api_key": self.get_my_username()})) ) expected = {"name": "Sheet %s" % (sheet_id,), "1": {"1": 5, "2": "abc"}, "2": {"1": 6}, "3": {"1": 11}} self.assertEquals(sheet_content, expected)
def test_simple_json_with_error(self): # * Harold wants to use Dirigible to run his spreadsheets using # a json-based rest API, and wants the error-handling to be # well-defined (if perhaps not ideal from a debugging perspective) # * He logs in to Dirigible and creates a new sheet sheet_id = self.login_and_create_new_sheet() # * He enables json api access for the sheet self.enable_json_api_for_sheet() # * He enters a single formula operating on a single value self.enter_cell_text(1, 1, "5") self.enter_cell_text(1, 2, "=1/A1") self.wait_for_cell_value(1, 2, "0.2") # * He uses an API call to get the sheet as JSON, passing in an override # value that he knows will cause an error get_params = urlencode({"A1": "0", "api_key": self.get_my_username()}) url = "%s?%s" % (Url.api_url(self.get_my_username(), sheet_id), get_params) try: sheet_content = json.load(urlopen(url)) except Exception, e: self.fail(str(e))
def test_json_api_auth(self): # Harold wants to make sure that people only have JSON access to his sheets # when he has explicitly granted it. # * He logs in to Dirigible and creates a new sheet sheet_id = self.login_and_create_new_sheet() base_json_url = urljoin(self.browser.current_url, 'v0.1/json/') # * He enters some values and formulae self.enter_cell_text(1, 1, '5') # * He tries to use an API call to get the sheet as JSON, but gets a 403 error. with self.assertRaises(HTTPError) as mngr: urlopen(base_json_url) self.assertEquals(mngr.exception.code, 403) # * Looking around at the sheet page, he notices a "Security" button. self.wait_for_element_to_appear('id=id_security_button') # * He sees that the mouseover text on the button indicates that the JSON API is not enabled self.assertTrue( 'JSON API disabled' in self.selenium.get_attribute('css=#id_security_button@title') ) self.assertTrue( 'JSON API disabled' in self.selenium.get_attribute('css=#id_security_button@alt') ) # * He clicks the button. self.selenium.click('id=id_security_button') # * A dialog appears; there is an unchecked toggle saying "Allow JSON API access" self.wait_for_element_visibility('id=id_security_form', True) self.wait_for_element_visibility('id=id_security_form_save_error', False) self.wait_for_element_visibility('id=id_security_form_json_enabled_checkbox', True) self.wait_for_element_visibility('id=id_security_form_json_api_key', True) self.wait_for_element_visibility('id=id_security_form_json_api_url', True) self.assertFalse(self.is_element_enabled('id_security_form_json_api_key')) self.assertFalse(self.is_element_enabled('id_security_form_json_api_url')) self.assertEquals( self.get_text('css=label[for="id_security_form_json_enabled_checkbox"]'), 'Allow JSON API access' ) self.assertEquals(self.selenium.get_value('id=id_security_form_json_enabled_checkbox'), 'off') # * ... and OK and Cancel buttons self.wait_for_element_visibility('id=id_security_form_ok_button', True) self.wait_for_element_visibility('id=id_security_form_cancel_button', True) # * He checks it. He notices a textbox giving him an "API key", self.selenium.click('id=id_security_form_json_enabled_checkbox') self.assertTrue(self.is_element_enabled('id_security_form_json_api_key')) api_key = self.selenium.get_value('id=id_security_form_json_api_key') api_url = self.selenium.get_value('id=id_security_form_json_api_url') # * He also notices that when he clicks on the URL text field, the entire field is selected ## The focus call is to appease Chrome self.selenium.focus('id=id_security_form_json_api_url') self.selenium.click('id=id_security_form_json_api_url') # our 'caret' plugin appears to have a problem getting the selection # range for fields that are not editable, such as the json api url. # Consequently, we have to check the selection by copying this # text, and checking the clipboard content. with self.key_down(key_codes.CTRL): self.human_key_press(key_codes.LETTER_C) def get_clipboard_text(): OpenClipboard() text = GetClipboardData(win32con.CF_TEXT) CloseClipboard() return text self.wait_for( lambda: get_clipboard_text() == api_url, lambda: 'bad clipboard text, was: %s' % (get_clipboard_text(),) ) # * nothing appears outside the JSON API dialog box yet though. self.assertTrue( 'JSON API disabled' in self.selenium.get_attribute('css=#id_security_button@title') ) self.assertTrue( 'JSON API disabled' in self.selenium.get_attribute('css=#id_security_button@alt') ) # * He ignores all of the key stuff, presses Cancel self.selenium.click('id=id_security_form_cancel_button') # * He notices that the form disappears and that the icon still indicates that the JSON API is disabled self.wait_for_element_visibility('id=id_security_form', False) self.assertTrue( 'JSON API disabled' in self.selenium.get_attribute('css=#id_security_button@title') ) self.assertTrue( 'JSON API disabled' in self.selenium.get_attribute('css=#id_security_button@alt') ) # but he just tries accessing the JSON URL without a key again # * He gets 403 again. with self.assertRaises(HTTPError) as mngr: urlopen(base_json_url) self.assertEquals(mngr.exception.code, 403) # * and he also gets 403 when he uses the API Key that was displayed with self.assertRaises(HTTPError) as mngr: urlopen(base_json_url, urlencode({'api_key': api_key})) self.assertEquals(mngr.exception.code, 403) # * He half-realises what the problem is, opens the dialog again, checks the box, and presses OK self.selenium.click('id=id_security_button') self.wait_for_element_visibility('id=id_security_form', True) self.wait_for_element_visibility('id=id_security_form_save_error', False) self.assertEquals(self.selenium.get_value('id=id_security_form_json_enabled_checkbox'), 'off') self.selenium.click('id=id_security_form_json_enabled_checkbox') self.assertTrue(self.is_element_enabled('id_security_form_json_api_key')) self.assertTrue(self.is_element_enabled('id_security_form_json_api_url')) api_url = self.selenium.get_value('css=#id_security_form_json_api_url') self.selenium.click('id=id_security_form_ok_button') self.wait_for_element_visibility('id=id_security_form', False) #* He now sees the toolbar indicates that the JSON API is enabled for this sheet self.assertTrue( 'JSON API enabled' in self.selenium.get_attribute('css=#id_security_button@title') ) self.assertTrue( 'JSON API enabled' in self.selenium.get_attribute('css=#id_security_button@alt') ) # * Not trusting the memory of his browser, he opens the dialog again self.selenium.click('id=id_security_button') self.wait_for_element_visibility('id=id_security_form', True) self.wait_for_element_visibility('id=id_security_form_save_error', False) self.assertEquals(self.selenium.get_value('id=id_security_form_json_enabled_checkbox'), 'on') # * and immediately presses Cancel self.selenium.click('id=id_security_form_cancel_button') # * He is surprised and delighted to see that his sheet is still JSON-enabled self.assertTrue( 'JSON API enabled' in self.selenium.get_attribute('css=#id_security_button@title') ) self.assertTrue( 'JSON API enabled' in self.selenium.get_attribute('css=#id_security_button@alt') ) expected_url = "%s%s?api_key=%s" % ( self.selenium.browserURL[:-1], urlparse(Url.api_url(self.get_my_username(), sheet_id)).path, api_key ) self.assertEquals(api_url, expected_url) # .. despite this helpful link, he tries again with the wrong API key with self.assertRaises(HTTPError) as mngr: urlopen(base_json_url, urlencode({'api_key': 'abcd1234-123dfe'})) # * He gets a 403 self.assertEquals(mngr.exception.code, 403) # * Frustrated, he tries again with the right API key. response = urlopen(base_json_url, urlencode({'api_key': api_key})) # * He gets the data he expected. json_data = json.load(response) self.assertEquals(json_data['1']['1'], 5) # * He changes the API key in the JSON API dialog. self.selenium.click('id=id_security_button') self.wait_for_element_visibility('id=id_security_form', True) self.wait_for_element_visibility('id=id_security_form_save_error', False) old_api_url = self.selenium.get_value('css=#id_security_form_json_api_url') self.selenium.type('id=id_security_form_json_api_key', 'some_new_api_ke') self.selenium.focus('id=id_security_form_json_api_key') # He sees that the api url is updated with every keystroke self.human_key_press(key_codes.END) # Move IE insert point to the end self.human_key_press(key_codes.LETTER_Y) self.assertEquals( self.selenium.get_value('css=#id_security_form_json_api_url'), old_api_url.replace(api_key, 'some_new_api_key') ) self.selenium.click('id=id_security_form_ok_button') self.wait_for_element_visibility('id=id_security_form', False) # * He tries again, using the old key with self.assertRaises(HTTPError) as mngr: urlopen(base_json_url, urlencode({'api_key': api_key})) # * He gets a 403 self.assertEquals(mngr.exception.code, 403) # * He tries using the right key. response = urlopen(base_json_url, urlencode({'api_key': 'some_new_api_key'})) # * It works. json_data = json.load(response) self.assertEquals(json_data['1']['1'], 5) # * He refreshes the sheet page self.refresh_sheet_page() # * and notes that his setting has been remembered by the server self.selenium.click('id=id_security_button') self.wait_for_element_visibility('id=id_security_form', True) self.wait_for_element_visibility('id=id_security_form_save_error', False) self.assertEquals(self.selenium.get_value('id=id_security_form_json_enabled_checkbox'), 'on') # * He makes the sheet private again. self.selenium.click('id=id_security_button') self.wait_for_element_visibility('id=id_security_form', True) self.wait_for_element_visibility('id=id_security_form_save_error', False) self.selenium.click('id=id_security_form_json_enabled_checkbox') self.selenium.click('id=id_security_form_ok_button') self.wait_for_element_visibility('id=id_security_form', False) # * He tries with the key that worked last time. with self.assertRaises(HTTPError) as mngr: urlopen(base_json_url, urlencode({'api_key': 'some_new_api_key'})) # * He gets a 403 self.assertEquals(mngr.exception.code, 403)
def test_json_api_auth(self): # Harold wants to make sure that people only have JSON access to his sheets # when he has explicitly granted it. # * He logs in to Dirigible and creates a new sheet sheet_id = self.login_and_create_new_sheet() base_json_url = urljoin(self.browser.current_url, 'v0.1/json/') # * He enters some values and formulae self.enter_cell_text(1, 1, '5') # * He tries to use an API call to get the sheet as JSON, but gets a 403 error. with self.assertRaises(HTTPError) as mngr: urlopen(base_json_url) self.assertEquals(mngr.exception.code, 403) # * Looking around at the sheet page, he notices a "Security" button. self.wait_for_element_to_appear('id=id_security_button') # * He sees that the mouseover text on the button indicates that the JSON API is not enabled self.assertTrue('JSON API disabled' in self.selenium.get_attribute( 'css=#id_security_button@title')) self.assertTrue('JSON API disabled' in self.selenium.get_attribute( 'css=#id_security_button@alt')) # * He clicks the button. self.selenium.click('id=id_security_button') # * A dialog appears; there is an unchecked toggle saying "Allow JSON API access" self.wait_for_element_visibility('id=id_security_form', True) self.wait_for_element_visibility('id=id_security_form_save_error', False) self.wait_for_element_visibility( 'id=id_security_form_json_enabled_checkbox', True) self.wait_for_element_visibility('id=id_security_form_json_api_key', True) self.wait_for_element_visibility('id=id_security_form_json_api_url', True) self.assertFalse( self.is_element_enabled('id_security_form_json_api_key')) self.assertFalse( self.is_element_enabled('id_security_form_json_api_url')) self.assertEquals( self.get_text( 'css=label[for="id_security_form_json_enabled_checkbox"]'), 'Allow JSON API access') self.assertEquals( self.selenium.get_value( 'id=id_security_form_json_enabled_checkbox'), 'off') # * ... and OK and Cancel buttons self.wait_for_element_visibility('id=id_security_form_ok_button', True) self.wait_for_element_visibility('id=id_security_form_cancel_button', True) # * He checks it. He notices a textbox giving him an "API key", self.selenium.click('id=id_security_form_json_enabled_checkbox') self.assertTrue( self.is_element_enabled('id_security_form_json_api_key')) api_key = self.selenium.get_value('id=id_security_form_json_api_key') api_url = self.selenium.get_value('id=id_security_form_json_api_url') # * He also notices that when he clicks on the URL text field, the entire field is selected ## The focus call is to appease Chrome self.selenium.focus('id=id_security_form_json_api_url') self.selenium.click('id=id_security_form_json_api_url') # our 'caret' plugin appears to have a problem getting the selection # range for fields that are not editable, such as the json api url. # Consequently, we have to check the selection by copying this # text, and checking the clipboard content. with self.key_down(key_codes.CTRL): self.human_key_press(key_codes.LETTER_C) def get_clipboard_text(): OpenClipboard() text = GetClipboardData(win32con.CF_TEXT) CloseClipboard() return text self.wait_for( lambda: get_clipboard_text() == api_url, lambda: 'bad clipboard text, was: %s' % (get_clipboard_text(), )) # * nothing appears outside the JSON API dialog box yet though. self.assertTrue('JSON API disabled' in self.selenium.get_attribute( 'css=#id_security_button@title')) self.assertTrue('JSON API disabled' in self.selenium.get_attribute( 'css=#id_security_button@alt')) # * He ignores all of the key stuff, presses Cancel self.selenium.click('id=id_security_form_cancel_button') # * He notices that the form disappears and that the icon still indicates that the JSON API is disabled self.wait_for_element_visibility('id=id_security_form', False) self.assertTrue('JSON API disabled' in self.selenium.get_attribute( 'css=#id_security_button@title')) self.assertTrue('JSON API disabled' in self.selenium.get_attribute( 'css=#id_security_button@alt')) # but he just tries accessing the JSON URL without a key again # * He gets 403 again. with self.assertRaises(HTTPError) as mngr: urlopen(base_json_url) self.assertEquals(mngr.exception.code, 403) # * and he also gets 403 when he uses the API Key that was displayed with self.assertRaises(HTTPError) as mngr: urlopen(base_json_url, urlencode({'api_key': api_key})) self.assertEquals(mngr.exception.code, 403) # * He half-realises what the problem is, opens the dialog again, checks the box, and presses OK self.selenium.click('id=id_security_button') self.wait_for_element_visibility('id=id_security_form', True) self.wait_for_element_visibility('id=id_security_form_save_error', False) self.assertEquals( self.selenium.get_value( 'id=id_security_form_json_enabled_checkbox'), 'off') self.selenium.click('id=id_security_form_json_enabled_checkbox') self.assertTrue( self.is_element_enabled('id_security_form_json_api_key')) self.assertTrue( self.is_element_enabled('id_security_form_json_api_url')) api_url = self.selenium.get_value('css=#id_security_form_json_api_url') self.selenium.click('id=id_security_form_ok_button') self.wait_for_element_visibility('id=id_security_form', False) #* He now sees the toolbar indicates that the JSON API is enabled for this sheet self.assertTrue('JSON API enabled' in self.selenium.get_attribute( 'css=#id_security_button@title')) self.assertTrue('JSON API enabled' in self.selenium.get_attribute( 'css=#id_security_button@alt')) # * Not trusting the memory of his browser, he opens the dialog again self.selenium.click('id=id_security_button') self.wait_for_element_visibility('id=id_security_form', True) self.wait_for_element_visibility('id=id_security_form_save_error', False) self.assertEquals( self.selenium.get_value( 'id=id_security_form_json_enabled_checkbox'), 'on') # * and immediately presses Cancel self.selenium.click('id=id_security_form_cancel_button') # * He is surprised and delighted to see that his sheet is still JSON-enabled self.assertTrue('JSON API enabled' in self.selenium.get_attribute( 'css=#id_security_button@title')) self.assertTrue('JSON API enabled' in self.selenium.get_attribute( 'css=#id_security_button@alt')) expected_url = "%s%s?api_key=%s" % ( self.selenium.browserURL[:-1], urlparse(Url.api_url(self.get_my_username(), sheet_id)).path, api_key) self.assertEquals(api_url, expected_url) # .. despite this helpful link, he tries again with the wrong API key with self.assertRaises(HTTPError) as mngr: urlopen(base_json_url, urlencode({'api_key': 'abcd1234-123dfe'})) # * He gets a 403 self.assertEquals(mngr.exception.code, 403) # * Frustrated, he tries again with the right API key. response = urlopen(base_json_url, urlencode({'api_key': api_key})) # * He gets the data he expected. json_data = json.load(response) self.assertEquals(json_data['1']['1'], 5) # * He changes the API key in the JSON API dialog. self.selenium.click('id=id_security_button') self.wait_for_element_visibility('id=id_security_form', True) self.wait_for_element_visibility('id=id_security_form_save_error', False) old_api_url = self.selenium.get_value( 'css=#id_security_form_json_api_url') self.selenium.type('id=id_security_form_json_api_key', 'some_new_api_ke') self.selenium.focus('id=id_security_form_json_api_key') # He sees that the api url is updated with every keystroke self.human_key_press(key_codes.END) # Move IE insert point to the end self.human_key_press(key_codes.LETTER_Y) self.assertEquals( self.selenium.get_value('css=#id_security_form_json_api_url'), old_api_url.replace(api_key, 'some_new_api_key')) self.selenium.click('id=id_security_form_ok_button') self.wait_for_element_visibility('id=id_security_form', False) # * He tries again, using the old key with self.assertRaises(HTTPError) as mngr: urlopen(base_json_url, urlencode({'api_key': api_key})) # * He gets a 403 self.assertEquals(mngr.exception.code, 403) # * He tries using the right key. response = urlopen(base_json_url, urlencode({'api_key': 'some_new_api_key'})) # * It works. json_data = json.load(response) self.assertEquals(json_data['1']['1'], 5) # * He refreshes the sheet page self.refresh_sheet_page() # * and notes that his setting has been remembered by the server self.selenium.click('id=id_security_button') self.wait_for_element_visibility('id=id_security_form', True) self.wait_for_element_visibility('id=id_security_form_save_error', False) self.assertEquals( self.selenium.get_value( 'id=id_security_form_json_enabled_checkbox'), 'on') # * He makes the sheet private again. self.selenium.click('id=id_security_button') self.wait_for_element_visibility('id=id_security_form', True) self.wait_for_element_visibility('id=id_security_form_save_error', False) self.selenium.click('id=id_security_form_json_enabled_checkbox') self.selenium.click('id=id_security_form_ok_button') self.wait_for_element_visibility('id=id_security_form', False) # * He tries with the key that worked last time. with self.assertRaises(HTTPError) as mngr: urlopen(base_json_url, urlencode({'api_key': 'some_new_api_key'})) # * He gets a 403 self.assertEquals(mngr.exception.code, 403)