Skip to content

Commit edcadb6

Browse files
committed
Merge pull request #21 from codebendercc/tests_additions_and_fixes
Various additions and fixes.
2 parents 6bd1e31 + d6138ee commit edcadb6

File tree

12 files changed

+91
-167
lines changed

12 files changed

+91
-167
lines changed

bin/seleniumbender

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ done
6464
cd ..
6565

6666
URL="https://codebender.cc"
67-
SOURCE="codebender_cc"
6867

6968
email_date=$(date +"%Y-%m-%d %H:%M:%S")
7069

@@ -73,40 +72,43 @@ NO_LOGS=0 # flag for tests that do not send any logs on their email
7372

7473
if [ "${target}" -eq 1 ]; then
7574
IDENTIFIER="test_target_libraries"
76-
tox tests/target_libraries -- --url=${URL} --source=${SOURCE} -F --plugin --libraries=${TARGETS}
75+
tox tests/target_libraries -- --url=${URL} -F --plugin --libraries=${TARGETS}
7776
elif [ "${examples}" -eq 1 ]; then
7877
IDENTIFIER="libraries_test"
79-
tox tests/libraries -- --url=${URL} --source=${SOURCE} -F --plugin
78+
tox tests/libraries -- --url=${URL} -F --plugin
8079
elif [ "${libraries}" -eq 1 ]; then
8180
IDENTIFIER="libraries_fetch"
82-
tox tests/libraries_fetch -- --url=${URL} --source=${SOURCE} -F --plugin
81+
tox tests/libraries_fetch -- --url=${URL} -F --plugin
8382
elif [ "${sketches}" -eq 1 ]; then
8483
IDENTIFIER="cb_compile_tester"
85-
tox tests/compile_tester -- --url=${URL} --source=${SOURCE} -F --plugin
84+
tox tests/compile_tester -- --url=${URL} -F --plugin
8685
elif [ "${common}" -eq 1 ]; then
8786
IDENTIFIER="common"
88-
tox tests/common -- --url=${URL} --source=${SOURCE} --plugin
87+
tox tests/common -- --url=${URL} --plugin
8988
RETVAL=$?
9089
NO_LOGS=1
9190
elif [ "${noplugin}" -eq 1 ]; then
9291
IDENTIFIER="noplugin"
93-
tox tests/noplugin -- --url=${URL} --source=${SOURCE}
92+
tox tests/noplugin -- --url=${URL}
9493
RETVAL=$?
9594
NO_LOGS=1
9695
elif [ "${walkthrough}" -eq 1 ]; then
9796
IDENTIFIER="walkthrough"
9897
RETVALS=()
9998
# Linux
99+
export SELENIUM_USER_AGENT_CHROME='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36 codebender-selenium'
100100
export SELENIUM_USER_AGENT='Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0 codebender-selenium'
101-
tox tests/walkthrough -- --url=${URL} --source=${SOURCE} --plugin
101+
tox tests/walkthrough -- --url=${URL} --plugin
102102
RETVALS+=($?)
103103
# Windows
104+
export SELENIUM_USER_AGENT_CHROME='Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36 codebender-selenium'
104105
export SELENIUM_USER_AGENT='Mozilla/5.0 (Windows NT 6.1; rv:43.0) Gecko/20100101 Firefox/43.0 codebender-selenium'
105-
tox tests/walkthrough -- --url=${URL} --source=${SOURCE} --plugin
106+
tox tests/walkthrough -- --url=${URL} --plugin
106107
RETVALS+=($?)
107108
# MacOSX
109+
export SELENIUM_USER_AGENT_CHROME='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36 codebender-selenium'
108110
export SELENIUM_USER_AGENT='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1; rv:43.0) Gecko/20100101 Firefox/43.0 codebender-selenium'
109-
tox tests/walkthrough -- --url=${URL} --source=${SOURCE} --plugin
111+
tox tests/walkthrough -- --url=${URL} --plugin
110112
RETVALS+=($?)
111113

112114
for i in "${RETVALS[@]}"
@@ -119,7 +121,7 @@ elif [ "${walkthrough}" -eq 1 ]; then
119121
elif [ "${staging}" -eq 1 ]; then
120122
IDENTIFIER="cb_compile_tester_staging"
121123
URL="https://staging.codebender.cc"
122-
tox tests/compile_tester -- --url=${URL} --source=${SOURCE} -F --plugin
124+
tox tests/compile_tester -- --url=${URL} -F --plugin
123125
# No need to send email for tests in staging
124126
exit $?
125127
fi

codebender_testing/capabilities.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
seleniumVersion: "2.48.0"
1313
maxDuration: 10800
1414
- browserName: "chrome"
15-
version: 41
15+
version: 47
1616
public: "public restricted"
17-
seleniumVersion: "2.48.0"
17+
seleniumVersion: "2.50.1"
1818
maxDuration: 10800

codebender_testing/config.py

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@
99

1010

1111
def _rel_path(*args):
12-
"""Forms a path relative to this file's directory."""
12+
"""Returns a path relative to config.py file's directory."""
1313
return os.path.join(os.path.dirname(__file__), *args)
1414

1515
def get_path(directory, filename=None):
16+
"""Returns an absolute path as seen from your current working directory.
17+
If a file is passed as argument, returns an aboslute path including the
18+
file."""
1619
path = os.path.join(os.path.dirname( __file__ ), '..', directory)
1720
if filename:
1821
path = os.path.join(os.path.dirname( __file__ ), '..', directory, filename)
@@ -21,16 +24,12 @@ def get_path(directory, filename=None):
2124
def jsondump(data):
2225
return simplejson.dumps(data, sort_keys=True, indent=4 * ' ')
2326

24-
# URL of the default site to be used for testing
27+
# URL of the default site to be used for testing.
2528
BASE_URL = "http://localhost"
26-
# URL of the actual Codebender website
29+
# URL of the actual Codebender website.
2730
LIVE_SITE_URL = "https://codebender.cc"
2831
STAGING_SITE_URL = "https://staging.codebender.cc"
2932

30-
# Names of sources (i.e. repositories) used to generate the codebender site.
31-
SOURCE_BACHELOR = 'bachelor'
32-
SOURCE_CODEBENDER_CC = 'codebender_cc'
33-
3433
# User whose projects we'd like to compile in our compile_tester
3534
# test case(s).
3635
COMPILE_TESTER_URL = "/user/cb_compile_tester"
@@ -41,42 +40,42 @@ def jsondump(data):
4140
# be formatted appropriately.
4241
LOGFILE_PREFIX = _rel_path("..", "logs", "%Y-%m-%d_%H-%M-%S-{log_name}.json")
4342

44-
# Logfile for COMPILE_TESTER compilation results
43+
# Logfile for COMPILE_TESTER compilation results.
4544
COMPILE_TESTER_LOGFILE = LOGFILE_PREFIX.format(log_name="cb_compile_tester")
4645
COMPILE_TESTER_LOGFILE_STAGING = LOGFILE_PREFIX.format(log_name="staging_cb_compile_tester")
4746

48-
# Logfile for /libraries compilation results
47+
# Logfile for /libraries compilation results.
4948
LIBRARIES_TEST_LOGFILE = LOGFILE_PREFIX.format(log_name="libraries_test")
5049

51-
# Logfile for /libraries fetch results
50+
# Logfile for /libraries fetch results.
5251
LIBRARIES_FETCH_LOGFILE = LOGFILE_PREFIX.format(log_name="libraries_fetch")
5352

53+
# Directory in which Firefox and Chrome extensions are stored.
5454
_EXTENSIONS_DIR = _rel_path('..', 'extensions')
55+
56+
# Firefox plugin for all Firefox versions.
5557
_FIREFOX_EXTENSION_FNAME = 'codebender.xpi'
58+
# Chrome extension for Chrome versions < 42.
5659
_CHROME_EXTENSION_FNAME = 'codebendercc-extension.crx'
60+
# Chrome extension for Chrome versions >= 42.
61+
_CHROME_APP_FNAME = 'chrome-app-1.0.0.8.zip'
5762

5863
# Maximum version number that we can use the Chrome extension with.
59-
# For versions higher than this, we need to use the newer Codebender app
64+
# For versions higher than this, we need to use the newer Codebender app.
6065
CHROME_EXT_MAX_CHROME_VERSION = 41
6166

62-
# Path to YAML file specifying capability list
67+
# Path to YAML file specifying capability list.
6368
DEFAULT_CAPABILITIES_FILE = os.getenv('CAPABILITIES', 'capabilities.yaml')
6469
DEFAULT_CAPABILITIES_FILE_PATH = _rel_path(DEFAULT_CAPABILITIES_FILE)
6570

66-
# Files used for testing
71+
# Files used for testing.
6772
TEST_DATA_DIR = _rel_path('..', 'test_data')
6873
TEST_DATA_INO = os.path.join(TEST_DATA_DIR, 'upload_ino.ino')
6974
TEST_DATA_ZIP = os.path.join(TEST_DATA_DIR, 'upload_zip.zip')
7075

7176
# Directory in which the local compile tester files are stored.
7277
COMPILE_TESTER_DIR = os.path.join(TEST_DATA_DIR, 'cb_compile_tester')
7378

74-
# Credentials to use when logging into the bachelor site
75-
TEST_CREDENTIALS = {
76-
"username": "tester",
77-
"password": "testerPASS"
78-
}
79-
8079
TEST_PROJECT_NAME = "test_project"
8180

8281
TIMEOUT = {
@@ -86,7 +85,12 @@ def jsondump(data):
8685
DEFAULT_USER_AGENT = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0 codebender-selenium'
8786
TESTS_USER_AGENT = os.getenv('SELENIUM_USER_AGENT', DEFAULT_USER_AGENT)
8887

89-
# Set up Selenium Webdrivers to be used for selenium tests
88+
DEFAULT_USER_AGENT_CHROME = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'
89+
TESTS_USER_AGENT_CHROME = os.getenv('SELENIUM_USER_AGENT_CHROME', DEFAULT_USER_AGENT_CHROME)
90+
91+
BROWSER = "firefox"
92+
93+
# Set up Selenium Webdrivers to be used for selenium tests.
9094
def _get_firefox_profile():
9195
"""Returns the Firefox profile to be used for the FF webdriver.
9296
Specifically, we're equipping the webdriver with the Codebender
@@ -131,26 +135,20 @@ def create_webdriver(command_executor, desired_capabilities):
131135
browser_profile_path = None
132136

133137
if browser_name == "chrome":
138+
BROWSER = "chrome"
134139
desired_capabilities = DesiredCapabilities.CHROME.copy()
135140
desired_capabilities.update(_capabilities)
136-
137-
# NOTE: the following logic is disabled since the remote webdriver is
138-
# not properly installing the codebender extension. It is kept for
139-
# reference until we can figure out how to properly add the Chrome
140-
# extension.
141-
142-
# # Add chrome extension to capabilities
143-
# options = chrome.options.Options()
144-
# options.add_extension(os.path.join(_EXTENSIONS_DIR, _CHROME_EXTENSION_FNAME))
145-
# desired_capabilities.update(options.to_capabilities())
146-
# # Right now we only support up to v41 for this testing suite.
147-
# if "version" in desired_capabilities:
148-
# if desired_capabilities["version"] > CHROME_EXT_MAX_CHROME_VERSION:
149-
# raise ValueError("The testing suite only supports Chrome versions up to v%d, "
150-
# "but v%d was specified. Please specify a lower version "
151-
# "number." % (CHROME_EXT_MAX_CHROME_VERSION, desired_capabilities["version"]))
152-
# else:
153-
# desired_capabilities["version"] = CHROME_EXT_MAX_CHROME_VERSION
141+
if desired_capabilities["version"] > CHROME_EXT_MAX_CHROME_VERSION:
142+
# Add new chrome extension to capabilities.
143+
options = chrome.options.Options()
144+
options.add_extension(os.path.join(_EXTENSIONS_DIR, _CHROME_APP_FNAME))
145+
options.add_argument("--user-agent=" + TESTS_USER_AGENT_CHROME)
146+
desired_capabilities.update(options.to_capabilities())
147+
desired_capabilities.update(_capabilities)
148+
else:
149+
raise ValueError("The testing suite only supports Chrome versions greater than v%d, "
150+
"but v%d was specified. Please specify a higher version number."
151+
% (CHROME_EXT_MAX_CHROME_VERSION, desired_capabilities["version"]))
154152

155153
elif browser_name == "firefox":
156154
desired_capabilities = DesiredCapabilities.FIREFOX.copy()

codebender_testing/utils.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
from codebender_testing.config import BASE_URL
2525
from codebender_testing.config import TIMEOUT
26-
from codebender_testing.config import TEST_CREDENTIALS
2726
from codebender_testing.config import TEST_PROJECT_NAME
2827
from codebender_testing.config import get_path
2928
from codebender_testing.config import jsondump
@@ -314,8 +313,6 @@ def login(self, credentials=None):
314313
unspecified location when calling this function.
315314
`credentials` should be a dict with keys 'username' and 'password',
316315
mapped to the appropriate values."""
317-
if credentials is None:
318-
credentials = TEST_CREDENTIALS
319316
try:
320317
self.open()
321318
login_button = self.driver.find_element_by_id('login_btn')
@@ -336,6 +333,7 @@ def logout(self):
336333
try:
337334
logout_button = self.driver.find_element_by_id("logout")
338335
logout_button.send_keys(Keys.ENTER)
336+
self.get_element(By.CSS_SELECTOR, '#login_btn')
339337
except NoSuchElementException:
340338
# 'Log out' is not displayed, so we're already logged out.
341339
pass
@@ -496,9 +494,7 @@ def compile_sketch(self, url, boards, iframe=False, project_view=False):
496494
try:
497495
self.execute_script(SELECT_BOARD_SCRIPT(board), '$', 'compilerflasher.pluginHandler.plugin_found')
498496
self.execute_script(_VERIFY_SCRIPT, 'compilerflasher')
499-
# In the BACHELOR site the id is 'operation_output', but in the live
500-
# site the id is 'cb_cf_operation_output'. The [id$=operation_output]
501-
# here selects an id that _ends_ with 'operation_output'.
497+
# The [id$=operation_output] here selects an id that _ends_ with 'operation_output'.
502498
compile_result = WebDriverWait(self.driver, VERIFY_TIMEOUT).until(
503499
any_text_to_be_present_in_element(
504500
(By.CSS_SELECTOR, "[id$=operation_output]"),

extensions/chrome-app-1.0.0.8.zip

106 KB
Binary file not shown.

extensions/codebender-app.crx

-49 KB
Binary file not shown.

tests/common/home/test_home.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ def test_navigate_home(self, tester_logout):
1313

1414
def test_login(self, tester_logout):
1515
credentials = {
16-
'username': os.environ.get('CODEBENDER_TEST_USER', config.TEST_CREDENTIALS['username']),
17-
'password': os.environ.get('CODEBENDER_TEST_PASS', config.TEST_CREDENTIALS['password']),
16+
'username': os.environ.get('CODEBENDER_TEST_USER'),
17+
'password': os.environ.get('CODEBENDER_TEST_PASS'),
1818
}
1919
driver = self.driver
2020
self.open("/")

tests/common/sketch/test_sketch.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,11 @@ def test_boards_dropdown(self):
5454

5555
assert boards_dropdown.first_selected_option.text == TEST_BOARD
5656

57-
@pytest.mark.requires_extension
5857
def test_ports_dropdown(self):
5958
"""Tests that the ports dropdown exists."""
6059
ports = self.get_element(By.ID, "cb_cf_ports")
6160
assert ports.text == 'No ports detected'
6261

63-
@pytest.mark.requires_extension
6462
def test_run_with_no_port(self):
6563
"""Makes sure that there is an error when we attempt to run with no
6664
port selected."""
@@ -72,13 +70,11 @@ def test_run_with_no_port(self):
7270
)
7371
)
7472

75-
@pytest.mark.requires_extension
7673
def test_speeds_dropdown(self):
7774
"""Tests that the speeds dropdown exists."""
7875
self.get_element(By.ID, "serial_monitor_toggle").click()
7976
self.get_element(By.ID, "cb_cf_baud_rates")
8077

81-
@pytest.mark.requires_extension
8278
def test_serial_monitor_disables_fields(self):
8379
"""Tests that opening the serial monitor disables the port and baudrate
8480
fields."""

tests/common/user_home/test_user_home.py

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
from codebender_testing.config import TEST_DATA_INO
55
from codebender_testing.config import TEST_DATA_ZIP
6-
from codebender_testing.config import SOURCE_BACHELOR
7-
from codebender_testing.config import SOURCE_CODEBENDER_CC
86
from codebender_testing.utils import SeleniumTestCase
97

108

@@ -19,45 +17,6 @@ def open_user_home(self, tester_login):
1917
performing any of these tests."""
2018
pass
2119

22-
@pytest.mark.requires_source(SOURCE_BACHELOR)
23-
def test_create_project_blank_name(self):
24-
"""Test that we get an error when creating a project with no name."""
25-
create_button = self.get_element(By.CSS_SELECTOR, '.form-search button')
26-
create_button.click()
27-
error_heading = self.get_element(By.CSS_SELECTOR, '.alert h4')
28-
assert error_heading.text.startswith('Error')
29-
30-
@pytest.mark.requires_source(SOURCE_BACHELOR)
31-
def test_create_project_invalid_name(self):
32-
"""Test that we get an error when creating a project with an
33-
invalid name (e.g., a name containing a backslash).
34-
"""
35-
project_name_input = self.get_element(By.CSS_SELECTOR,
36-
'.form-search input[type=text]')
37-
project_name_input.clear()
38-
project_name_input.send_keys('foo\\bar')
39-
create_button = self.get_element(By.CSS_SELECTOR, '.form-search button')
40-
create_button.click()
41-
42-
error_heading = self.get_element(By.CSS_SELECTOR, '.alert h4')
43-
assert error_heading.text.startswith('Error')
44-
45-
@pytest.mark.requires_source(SOURCE_BACHELOR)
46-
def test_create_project_valid_name(self):
47-
"""Test that we can successfully create a project with a valid name."""
48-
project_name_input = self.get_element(By.CSS_SELECTOR,
49-
'.form-search input[type=text]')
50-
project_name_input.clear()
51-
project_name_input.send_keys(NEW_PROJECT_NAME)
52-
create_button = self.get_element(By.CSS_SELECTOR, '.form-search button')
53-
create_button.click()
54-
55-
project_heading = self.get_element(By.ID, 'editor_heading_project_name')
56-
assert project_heading.text == NEW_PROJECT_NAME
57-
58-
# Cleanup: delete the project we just created.
59-
self.delete_project(NEW_PROJECT_NAME)
60-
6120
def _upload_test(self, dropzone_selector, test_fname, sketch_name=None):
6221
"""Tests that we can successfully upload `test_fname`.
6322
`project_name` is the expected name of the project; by
@@ -66,16 +25,16 @@ def _upload_test(self, dropzone_selector, test_fname, sketch_name=None):
6625
"""
6726
try:
6827
upload_name = self.upload_project(dropzone_selector, test_fname, sketch_name)
69-
assert upload_name in self.driver.page_source
28+
selector = '#project_list li[data-name="'+ str(upload_name.lower()) +'"]'
29+
project_uploaded = self.get_element(By.CSS_SELECTOR, selector).text.split('\n')[0]
30+
assert upload_name == project_uploaded
7031
finally:
7132
self.delete_project(upload_name)
7233

73-
@pytest.mark.requires_source(SOURCE_CODEBENDER_CC)
7434
def test_upload_project_ino(self):
7535
"""Tests that we can upload a .ino file."""
7636
self._upload_test('#uploadInoModal form', TEST_DATA_INO)
7737

78-
@pytest.mark.requires_source(SOURCE_CODEBENDER_CC)
7938
def test_upload_project_zip(self):
8039
"""Tests that we can successfully upload a zipped project."""
8140
# TODO: how is the project name inferred from the zip file?

0 commit comments

Comments
 (0)