From 8be53704b1526c1210e197844766fcfcfb2bac4b Mon Sep 17 00:00:00 2001 From: Christos Nianiakas <cnianiak@gmail.com> Date: Thu, 21 Jul 2016 16:14:38 +0300 Subject: [PATCH 1/5] Added add/remove/rename file, remove sketch methods in CodebenderSeleniumBot class. Will use the methods accross the tests. --- codebender_testing/utils.py | 68 ++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/codebender_testing/utils.py b/codebender_testing/utils.py index e132d1a..c4077d3 100644 --- a/codebender_testing/utils.py +++ b/codebender_testing/utils.py @@ -20,6 +20,7 @@ from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions from selenium.webdriver.support.ui import WebDriverWait +from selenium.common.exceptions import TimeoutException from codebender_testing.config import BASE_URL from codebender_testing.config import TIMEOUT @@ -893,12 +894,16 @@ def create_sketch(self, privacy, name, description): createBtn = self.get_element(By.ID, 'create-sketch-modal-action-button') createBtn.click() - - WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( - expected_conditions.visibility_of_element_located( - (By.CSS_SELECTOR, "#editor-loading-screen") + # Added in try-except block because if the loading screen disappears too quickly + # the explicit wait will through an exception + try: + WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( + expected_conditions.visibility_of_element_located( + (By.CSS_SELECTOR, "#editor-loading-screen") + ) ) - ) + except TimeoutException: + pass WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( expected_conditions.invisibility_of_element_located( (By.CSS_SELECTOR, "#editor-loading-screen") @@ -1006,6 +1011,59 @@ def switch_into_iframe(self, url): iframe = self.driver.find_elements_by_tag_name('iframe')[index] self.driver.switch_to_frame(iframe) + def create_file(self, filename): + """ Creates a file in editor """ + self.get_element(By.ID, 'newfile').click() + WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( + expected_conditions.visibility_of_element_located( + (By.ID, 'creationModal')) + ) + self.get_element(By.ID, 'createfield').send_keys(filename) + self.get_element(By.ID, 'createfield').send_keys(Keys.ENTER) + WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( + expected_conditions.invisibility_of_element_located( + (By.ID, 'creationModal')) + ) + + def remove_file(self, filename): + self.get_element(By.CSS_SELECTOR, '#files_list .filelist[data-name="{}"] + .delete-file-button'.format(filename)).click() + WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( + expected_conditions.visibility_of_element_located( + (By.ID, 'filedeleteModal')) + ) + self.get_element(By.ID, 'filedeleteButton').click() + WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( + expected_conditions.invisibility_of_element_located( + (By.ID, 'filedeleteModal')) + ) + + def rename_file(self, old_filename, new_filename): + self.get_element(By.CSS_SELECTOR, '#files_list .filelist[data-name="{}"] ~ .rename-file-button'.format(old_filename)).click() + WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( + expected_conditions.visibility_of_element_located( + (By.ID, 'filenameModal')) + ) + filename_input = self.get_element(By.ID, 'newFilename') + filename_input.clear() + filename_input.send_keys(new_filename) + filename_input.send_keys(Keys.ENTER) + WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( + expected_conditions.invisibility_of_element_located( + (By.ID, 'filenameModal')) + ) + + def remove_sketch_editor(self): + """ Removes the sketch from editor page """ + self.get_element(By.ID, 'delete').click() + WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( + expected_conditions.visibility_of_element_located( + (By.ID, 'deletionModal')) + ) + self.get_element(By.ID, 'deleteProjectButton').click() + WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( + expected_conditions.visibility_of_element_located( + (By.ID, 'main-container')) + ) class SeleniumTestCase(CodebenderSeleniumBot): """Base class for all Selenium tests.""" From e7831e92c40ce80b6c2a447f1ec252f154010527 Mon Sep 17 00:00:00 2001 From: Christos Nianiakas <cnianiak@gmail.com> Date: Thu, 21 Jul 2016 16:15:26 +0300 Subject: [PATCH 2/5] Added test for collaboration in editor. Testing basic functionality of the editor when collaboration is enabled. Tests can run in Firefox only due to its support for alert dialogs. --- bin/seleniumbender.py | 11 ++- tests/collaboration/__init__.py | 0 tests/collaboration/test_collaboration.py | 115 ++++++++++++++++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 tests/collaboration/__init__.py create mode 100644 tests/collaboration/test_collaboration.py diff --git a/bin/seleniumbender.py b/bin/seleniumbender.py index 8a6981f..76a0ad9 100755 --- a/bin/seleniumbender.py +++ b/bin/seleniumbender.py @@ -41,6 +41,8 @@ def run(self, operation, test=None, libraries=None): self.staging() elif operation == 'delete': self.delete() + elif operation == 'collaboration': + self.collaboration() def run_command(self, command): command = ' '.join(command) @@ -158,6 +160,12 @@ def delete(self): if retval != 0: self.retval = retval + def collaboration(self): + command = self.create_command('collaboration') + retval = self.run_command(command) + if retval != 0: + self.retval = retval + OPERATIONS = { 'common':'\tTest site common functionality', 'libraries': 'Visit all libraries and their examples', @@ -167,7 +175,8 @@ def delete(self): 'noplugin': 'Run tests without app/plugin installed', 'walkthrough': 'Run tests for walkthrough', 'staging': '\tRun tests for staging only', - 'delete': '\tDelete all sketches from test user' + 'delete': '\tDelete all sketches from test user', + 'collaboration': 'Run tests for collaboration' } TARGETS = { diff --git a/tests/collaboration/__init__.py b/tests/collaboration/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/collaboration/test_collaboration.py b/tests/collaboration/test_collaboration.py new file mode 100644 index 0000000..9d6c414 --- /dev/null +++ b/tests/collaboration/test_collaboration.py @@ -0,0 +1,115 @@ +import pytest +from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions +from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.common.alert import Alert +from codebender_testing.utils import SeleniumTestCase +from codebender_testing.config import TIMEOUT +import time + +TEST_SKETCH = 'test_collaboration' +TEST_FILE = 'test.h' +TEST_EMPTY_FILE = 'empty.h' +TEST_RENAME_FILE = 'rename.h' +TEST_RENAMED_FILE = 'renamed.h' +TEST_INPUT = '// test input' + +class TestCollaboration(SeleniumTestCase): + ''' Opens a new tab in the browser ''' + def open_tab(self, url): + self.execute_script('window.open("{}")'.format(url)) + + ''' Closes current tab in the browser ''' + def close_tab(self): + self.execute_script('window.close()') + + ''' Switches between tabs in the browser ''' + def switch_window(self, index): + window = self.driver.window_handles[index] + self.driver.switch_to.window(window) + + @pytest.fixture(scope="class", autouse=True) + def create_test_project(self, tester_login): + """Makes sure we are logged in and have a project open before + performing any of these tests.""" + self.create_sketch('public' , TEST_SKETCH, '') + + def test_open_tab(self): + self.sketch_url = self.execute_script('return location.href') + self.open_tab(self.sketch_url) + WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( + expected_conditions.invisibility_of_element_located( + (By.CSS_SELECTOR, "#editor-loading-screen") + ) + ) + WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( + expected_conditions.element_to_be_clickable( + (By.CSS_SELECTOR, "#editor_heading_project_name") + ) + ) + + def test_create_file(self): + self.switch_window(0) + self.create_file(TEST_FILE) + + def test_check_created_file(self): + self.switch_window(1) + test_file = self.get_element(By.CSS_SELECTOR, '#files_list .filelist[data-name="{}"]'.format(TEST_FILE)) + filename = test_file.text.strip() + assert filename == TEST_FILE + test_file.click() + self.execute_script('editor.aceEditor.setValue("{}");'.format(TEST_INPUT), 'editor') + + def test_check_contents_change(self): + self.switch_window(0) + while self.execute_script('return editor.aceEditor.getValue();') != TEST_INPUT: + time.sleep(1) # Wait for editor to sync + test_input = self.execute_script('return editor.aceEditor.getValue();') + assert TEST_INPUT == test_input + + def test_create_and_delete_file(self): + self.switch_window(0) + self.create_file(TEST_EMPTY_FILE) + self.switch_window(1) + test_file = self.get_element(By.CSS_SELECTOR, '#files_list .filelist[data-name="{}"]'.format(TEST_EMPTY_FILE)) + filename = test_file.text.strip() + assert filename == TEST_EMPTY_FILE + test_file.click() + self.execute_script('editor.aceEditor.setValue("{}");'.format(TEST_INPUT), 'editor') + self.remove_file(filename) + self.switch_window(0) + WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( + expected_conditions.alert_is_present() + ) + Alert(self.driver).dismiss() + + def test_check_deleted_file(self): + self.switch_window(0) + deleted_file = self.driver.find_elements_by_css_selector('#files_list .filelist[data-name="{}"]'.format(TEST_EMPTY_FILE)) + assert len(deleted_file) == 0 + self.create_file(TEST_EMPTY_FILE) + empty_contents = self.execute_script('return editor.aceEditor.getValue();', 'editor') + assert empty_contents == '' + + def test_rename_file(self): + self.switch_window(1) + self.create_file(TEST_RENAME_FILE) + self.execute_script('editor.aceEditor.setValue("int a = 1;");', 'editor') + self.execute_script('editor.aceEditor.session.selection.moveCursorToPosition({row: 0, column: 3}); editor.aceEditor.session.selection.clearSelection();', 'editor') + self.switch_window(0) + self.get_element(By.CSS_SELECTOR, '#files_list .filelist[data-name="{}"]'.format(TEST_RENAME_FILE)).click() + self.rename_file(TEST_RENAME_FILE, TEST_RENAMED_FILE) + self.switch_window(1) + self.get_element(By.CSS_SELECTOR, '#files_list .filelist[data-name="{}"]'.format(TEST_RENAMED_FILE)) + + def test_remove_sketch(self): + self.switch_window(1) + self.remove_sketch_editor() + self.switch_window(0) + WebDriverWait(self.driver, TIMEOUT['LOCATE_ELEMENT']).until( + expected_conditions.alert_is_present() + ) + Alert(self.driver).dismiss() + self.logout() From cd9ee4204e6cc4ab2dbf5d6d98e539a92564b1ce Mon Sep 17 00:00:00 2001 From: Christos Nianiakas <cnianiak@gmail.com> Date: Thu, 21 Jul 2016 16:48:02 +0300 Subject: [PATCH 3/5] Added collaboration tests in common cron job. --- bin/cron/common | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/cron/common b/bin/cron/common index ff0d96a..4626d8c 100755 --- a/bin/cron/common +++ b/bin/cron/common @@ -11,3 +11,5 @@ python seleniumbender.py walkthrough --target=live --saucelabs --capabilities=ca # noplugin python seleniumbender.py noplugin --target=live --saucelabs --capabilities=capabilities_firefox.yaml --config=config.cfg python seleniumbender.py noplugin --target=live --saucelabs --capabilities=capabilities_chrome.yaml --config=config.cfg +# collaboration +python seleniumbender.py collaboration --target=live --saucelabs --capabilities=capabilities_firefox.yaml --config=config.cfg From 50b62ea68fa3ff8979badeb49d1971b3b7255b4d Mon Sep 17 00:00:00 2001 From: Christos Nianiakas <cnianiak@gmail.com> Date: Thu, 21 Jul 2016 16:48:46 +0300 Subject: [PATCH 4/5] Using Windows 10 in tests for walkthrough. --- bin/seleniumbender.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/seleniumbender.py b/bin/seleniumbender.py index 76a0ad9..fcf224a 100755 --- a/bin/seleniumbender.py +++ b/bin/seleniumbender.py @@ -187,7 +187,7 @@ def collaboration(self): PLATFORMS = { 'Linux': 'X11; Ubuntu; Linux x86_64', - 'Windows 7': 'Windows NT 6.1', + 'Windows 10': 'Windows NT 10.0', 'OS X 10.11': 'Macintosh; Intel Mac OS X 10_11_1' } USER_AGENTS = {} From 950627e3a551b662a8fee27d73a39320a9b6b4fc Mon Sep 17 00:00:00 2001 From: Christos Nianiakas <cnianiak@gmail.com> Date: Thu, 21 Jul 2016 17:53:08 +0300 Subject: [PATCH 5/5] Fixed assignment of global variable. Needed 'global' prefix before the assignment. --- codebender_testing/config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/codebender_testing/config.py b/codebender_testing/config.py index df5f36d..d1b0967 100644 --- a/codebender_testing/config.py +++ b/codebender_testing/config.py @@ -147,6 +147,7 @@ def create_webdriver(command_executor, desired_capabilities): browser_profile = None browser_profile_path = None + global SELENIUM_BROWSER SELENIUM_BROWSER = browser_name if browser_name == "chrome":