diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4c3a6939..cac933d4 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -22,22 +22,13 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- - name: Set up test environment
- run: |
- sudo apt-get install xvfb
- wget https://github.com/mozilla/geckodriver/releases/download/v0.15.0/geckodriver-v0.15.0-linux64.tar.gz
- mkdir geckodriver
- tar -xzf geckodriver-v0.15.0-linux64.tar.gz -C geckodriver
- export PATH=$PATH:$(pwd)/geckodriver
- export BOTO_CONFIG=/dev/null
-
- name: Install Requirements
run: |
pip install -r requirements/pip.txt
pip install -r requirements/ci.txt
- name: Run Tests
- run: xvfb-run --server-args=-ac -- tox -e ${{ matrix.toxenv }}
+ run: tox -e ${{ matrix.toxenv }}
- name: Upload coverage to CodeCov
if: matrix.python-version == '3.8' && matrix.toxenv == 'django42'
diff --git a/requirements/base.txt b/requirements/base.txt
index dd1fb37d..b4bf1c00 100644
--- a/requirements/base.txt
+++ b/requirements/base.txt
@@ -12,9 +12,9 @@ asgiref==3.7.2
# via django
binaryornot==0.4.4
# via cookiecutter
-boto3==1.28.63
+boto3==1.28.65
# via fs-s3fs
-botocore==1.31.63
+botocore==1.31.65
# via
# boto3
# s3transfer
@@ -115,7 +115,7 @@ typing-extensions==4.8.0
# via
# asgiref
# rich
-urllib3==1.26.17
+urllib3==1.26.18
# via
# botocore
# requests
diff --git a/requirements/dev.txt b/requirements/dev.txt
index 22a3b67b..e419e9e3 100644
--- a/requirements/dev.txt
+++ b/requirements/dev.txt
@@ -32,16 +32,12 @@ binaryornot==0.4.4
# -r requirements/base.txt
# -r requirements/test.txt
# cookiecutter
-bok-choy==0.7.1
- # via
- # -r requirements/test.in
- # -r requirements/test.txt
-boto3==1.28.63
+boto3==1.28.65
# via
# -r requirements/base.txt
# -r requirements/test.txt
# fs-s3fs
-botocore==1.31.63
+botocore==1.31.65
# via
# -r requirements/base.txt
# -r requirements/test.txt
@@ -152,7 +148,6 @@ lazy==1.6
# -r requirements/base.txt
# -r requirements/test.txt
# acid-xblock
- # bok-choy
# xblock
lazy-object-proxy==1.9.0
# via astroid
@@ -190,14 +185,6 @@ mock==5.1.0
# via
# -r requirements/test.in
# -r requirements/test.txt
-needle==0.5.0
- # via
- # -r requirements/test.txt
- # bok-choy
-nose==1.3.7
- # via
- # -r requirements/test.txt
- # needle
openedx-django-pyfs==3.4.0
# via
# -r requirements/base.txt
@@ -211,10 +198,6 @@ packaging==23.2
# tox
pbr==5.11.1
# via stevedore
-pillow==10.0.1
- # via
- # -r requirements/test.txt
- # needle
platformdirs==3.11.0
# via
# -r requirements/test.txt
@@ -315,12 +298,6 @@ s3transfer==0.7.0
# -r requirements/base.txt
# -r requirements/test.txt
# boto3
-selenium==3.4.1
- # via
- # -r requirements/test.in
- # -r requirements/test.txt
- # bok-choy
- # needle
simplejson==3.19.2
# via
# -r requirements/base.txt
@@ -330,7 +307,6 @@ six==1.16.0
# via
# -r requirements/base.txt
# -r requirements/test.txt
- # bok-choy
# edx-lint
# fs
# fs-s3fs
@@ -382,7 +358,7 @@ typing-extensions==4.8.0
# astroid
# pylint
# rich
-urllib3==1.26.17
+urllib3==1.26.18
# via
# -r requirements/base.txt
# -r requirements/test.txt
@@ -409,6 +385,7 @@ xblock[django]==1.8.1
# -r requirements/base.txt
# -r requirements/test.txt
# acid-xblock
+ # xblock
# The following packages are considered to be unsafe in a requirements file:
# setuptools
diff --git a/requirements/pip.txt b/requirements/pip.txt
index 3e7d8f4a..2154d29f 100644
--- a/requirements/pip.txt
+++ b/requirements/pip.txt
@@ -8,7 +8,7 @@ wheel==0.41.2
# via -r requirements/pip.in
# The following packages are considered to be unsafe in a requirements file:
-pip==23.2.1
+pip==23.3
# via -r requirements/pip.in
setuptools==68.2.2
# via -r requirements/pip.in
diff --git a/requirements/quality.txt b/requirements/quality.txt
index 2351b135..08ca462c 100644
--- a/requirements/quality.txt
+++ b/requirements/quality.txt
@@ -26,13 +26,11 @@ binaryornot==0.4.4
# via
# -r requirements/test.txt
# cookiecutter
-bok-choy==0.7.1
- # via -r requirements/test.txt
-boto3==1.28.63
+boto3==1.28.65
# via
# -r requirements/test.txt
# fs-s3fs
-botocore==1.31.63
+botocore==1.31.65
# via
# -r requirements/test.txt
# boto3
@@ -65,6 +63,7 @@ cookiecutter==2.4.0
coverage[toml]==7.3.2
# via
# -r requirements/test.txt
+ # coverage
# pytest-cov
ddt==1.6.0
# via -r requirements/test.txt
@@ -126,7 +125,6 @@ lazy==1.6
# via
# -r requirements/test.txt
# acid-xblock
- # bok-choy
# xblock
lazy-object-proxy==1.9.0
# via astroid
@@ -157,14 +155,6 @@ mdurl==0.1.2
# markdown-it-py
mock==5.1.0
# via -r requirements/test.txt
-needle==0.5.0
- # via
- # -r requirements/test.txt
- # bok-choy
-nose==1.3.7
- # via
- # -r requirements/test.txt
- # needle
openedx-django-pyfs==3.4.0
# via
# -r requirements/test.txt
@@ -177,10 +167,6 @@ packaging==23.2
# tox
pbr==5.11.1
# via stevedore
-pillow==10.0.1
- # via
- # -r requirements/test.txt
- # needle
platformdirs==3.11.0
# via
# -r requirements/test.txt
@@ -265,11 +251,6 @@ s3transfer==0.7.0
# via
# -r requirements/test.txt
# boto3
-selenium==3.4.1
- # via
- # -r requirements/test.txt
- # bok-choy
- # needle
simplejson==3.19.2
# via
# -r requirements/test.txt
@@ -277,7 +258,6 @@ simplejson==3.19.2
six==1.16.0
# via
# -r requirements/test.txt
- # bok-choy
# edx-lint
# fs
# fs-s3fs
@@ -322,7 +302,7 @@ typing-extensions==4.8.0
# astroid
# pylint
# rich
-urllib3==1.26.17
+urllib3==1.26.18
# via
# -r requirements/test.txt
# botocore
@@ -345,6 +325,7 @@ xblock[django]==1.8.1
# via
# -r requirements/test.txt
# acid-xblock
+ # xblock
# The following packages are considered to be unsafe in a requirements file:
# setuptools
diff --git a/requirements/test.in b/requirements/test.in
index 1cef2888..5f9513ca 100644
--- a/requirements/test.in
+++ b/requirements/test.in
@@ -2,13 +2,11 @@
-r base.txt
acid-xblock
-bok_choy==0.7.1
coverage
ddt
mock
pytest-django
pytest-cov
pytest-rerunfailures
-selenium==3.4.1 # Forcing this version fixes issues on CI
tox # Virtualenv management for tests
tox-battery # Makes tox aware of requirements file changes
diff --git a/requirements/test.txt b/requirements/test.txt
index 1e7237d8..cf3641c7 100644
--- a/requirements/test.txt
+++ b/requirements/test.txt
@@ -22,13 +22,11 @@ binaryornot==0.4.4
# via
# -r requirements/base.txt
# cookiecutter
-bok-choy==0.7.1
- # via -r requirements/test.in
-boto3==1.28.63
+boto3==1.28.65
# via
# -r requirements/base.txt
# fs-s3fs
-botocore==1.31.63
+botocore==1.31.65
# via
# -r requirements/base.txt
# boto3
@@ -98,7 +96,6 @@ lazy==1.6
# via
# -r requirements/base.txt
# acid-xblock
- # bok-choy
# xblock
lxml==4.9.3
# via
@@ -125,10 +122,6 @@ mdurl==0.1.2
# markdown-it-py
mock==5.1.0
# via -r requirements/test.in
-needle==0.5.0
- # via bok-choy
-nose==1.3.7
- # via needle
openedx-django-pyfs==3.4.0
# via
# -r requirements/base.txt
@@ -138,8 +131,6 @@ packaging==23.2
# pytest
# pytest-rerunfailures
# tox
-pillow==10.0.1
- # via needle
platformdirs==3.11.0
# via virtualenv
pluggy==1.3.0
@@ -197,11 +188,6 @@ s3transfer==0.7.0
# via
# -r requirements/base.txt
# boto3
-selenium==3.4.1
- # via
- # -r requirements/test.in
- # bok-choy
- # needle
simplejson==3.19.2
# via
# -r requirements/base.txt
@@ -209,7 +195,6 @@ simplejson==3.19.2
six==1.16.0
# via
# -r requirements/base.txt
- # bok-choy
# fs
# fs-s3fs
# python-dateutil
@@ -243,7 +228,7 @@ typing-extensions==4.8.0
# -r requirements/base.txt
# asgiref
# rich
-urllib3==1.26.17
+urllib3==1.26.18
# via
# -r requirements/base.txt
# botocore
@@ -262,6 +247,7 @@ xblock[django]==1.8.1
# via
# -r requirements/base.txt
# acid-xblock
+ # xblock
# The following packages are considered to be unsafe in a requirements file:
# setuptools
diff --git a/tox.ini b/tox.ini
index 2e1671f7..602aa549 100644
--- a/tox.ini
+++ b/tox.ini
@@ -19,7 +19,6 @@ deps =
-r{toxinidir}/requirements/test.txt
passenv =
DISPLAY
- BOTO_CONFIG
commands =
make var/workbench.db
python -Wd -m pytest {posargs}
diff --git a/workbench/test/selenium_test.py b/workbench/test/selenium_test.py
deleted file mode 100644
index c5f3b964..00000000
--- a/workbench/test/selenium_test.py
+++ /dev/null
@@ -1,39 +0,0 @@
-"""
-Helpers for Selenium tests.
-"""
-
-
-
-import pytest
-from bok_choy.web_app_test import WebAppTest
-from selenium.webdriver.support.expected_conditions import staleness_of
-from selenium.webdriver.support.ui import WebDriverWait
-
-from django.contrib.staticfiles.testing import StaticLiveServerTestCase
-
-from workbench.runtime_util import reset_global_state
-
-
-@pytest.mark.selenium
-class SeleniumTest(WebAppTest, StaticLiveServerTestCase):
- """
- Base test class that provides setUpClass and tearDownClass
- methods necessary for selenium testing.
- """
-
- def setUp(self):
- super().setUp()
-
- # Clear the in-memory key value store, the usage store, and whatever
- # else needs to be cleared and re-initialized.
- reset_global_state()
-
- def wait_for_page_load(self, old_element, timeout=30):
- """
- Uses Selenium's built-in "staleness" hook to wait until the page has
- loaded. For use when clicking a link to ensure that the new page
- has loaded before selecting elements. I think that this could be used
- to check that elements have been made stale via ajax as well, but it
- is not being used for that in any of the tests here.
- """
- return WebDriverWait(self.browser, timeout).until(staleness_of(old_element))
diff --git a/workbench/test/test_filethumbs.py b/workbench/test/test_filethumbs.py
deleted file mode 100644
index 4b661f77..00000000
--- a/workbench/test/test_filethumbs.py
+++ /dev/null
@@ -1,78 +0,0 @@
-"""Tests for the thumbs module"""
-
-
-import pytest
-from bok_choy.promise import EmptyPromise
-
-from workbench import scenarios
-from workbench.test.selenium_test import SeleniumTest
-
-
-class ThreeThumbsTest(SeleniumTest):
- """Test the functionalities of the three thumbs test XBlock."""
-
- def setUp(self):
- super().setUp()
-
- scenarios.add_xml_scenario(
- "test_three_file_thumbs", "three file thumbs test",
- """"""
- )
- self.addCleanup(scenarios.remove_scenario, "test_three_file_thumbs")
-
- # Suzy opens the browser to visit the workbench
- self.browser.get(self.live_server_url)
-
- # She knows it's the site by the header
- header1 = self.browser.find_element_by_css_selector('h1')
- self.assertEqual(header1.text, 'XBlock scenarios')
-
- @pytest.mark.flaky(reruns=5, reruns_delay=2)
- def test_three_thumbs_initial_state(self):
- # She clicks on the three thumbs at once scenario
- link = self.browser.find_element_by_link_text('three file thumbs test')
- link.click()
- self.wait_for_page_load(link, timeout=10)
-
- # The header reflects the XBlock
- header1 = self.browser.find_element_by_css_selector('h1')
- self.assertEqual(header1.text, 'XBlock: three file thumbs test')
-
- # She sees that there are 3 sets of thumbs
- vertical_css = 'div.student_view > div.xblock-v1 > div.vertical'
-
- # The following will give a NoSuchElementException error
- # if it is not there
- vertical = self.browser.find_element_by_css_selector(vertical_css)
-
- # Make sure there are three thumbs blocks
- thumb_css = 'div.xblock-v1[data-block-type="filethumbs"]'
- thumbs = vertical.find_elements_by_css_selector(thumb_css)
- self.assertEqual(3, len(thumbs))
-
- # Make sure they all have 0 for upvote and downvote counts
- up_count_css = 'span.upvote span.count'
- down_count_css = 'span.downvote span.count'
-
- for thumb in thumbs:
- # pylint: disable=cell-var-from-loop
- up_count = thumb.find_element_by_css_selector(up_count_css)
- down_count = thumb.find_element_by_css_selector(down_count_css)
- initial_up = int(up_count.text)
- initial_down = int(down_count.text)
-
- # upvote
- thumb.find_element_by_css_selector('span.upvote').click()
- _ = EmptyPromise(
- lambda: int(thumb.find_element_by_css_selector(up_count_css).text) == initial_up + 1,
- "upvote action succeeded"
- ).fulfill()
- self.assertEqual(initial_down, int(thumb.find_element_by_css_selector(down_count_css).text))
-
- # downvote
- thumb.find_element_by_css_selector('span.downvote').click()
- _ = EmptyPromise(
- lambda: int(thumb.find_element_by_css_selector(down_count_css).text) == initial_down + 1,
- "downvote action succeeded"
- ).fulfill()
- self.assertEqual(initial_up + 1, int(thumb.find_element_by_css_selector(up_count_css).text))
diff --git a/workbench/test/test_problems.py b/workbench/test/test_problems.py
deleted file mode 100644
index 3fb1954a..00000000
--- a/workbench/test/test_problems.py
+++ /dev/null
@@ -1,95 +0,0 @@
-"""Test that problems and problem submission works well."""
-
-
-import time
-import unittest
-
-from bok_choy.query import BrowserQuery
-from selenium.common.exceptions import StaleElementReferenceException
-
-from workbench import scenarios
-from workbench.test.selenium_test import SeleniumTest
-
-
-class ProblemInteractionTest(SeleniumTest):
- """
- A browser-based test of answering problems right and wrong.
- """
-
- def setUp(self):
- super().setUp()
-
- one_problem = """
-
- $a $b
-
-
-
-
- """
- self.num_problems = 3
- scenarios.add_xml_scenario(
- "test_many_problems", "Many problems",
- "" + one_problem * self.num_problems + ""
- )
- self.addCleanup(scenarios.remove_scenario, "test_many_problems")
-
- @unittest.skip("Flaky test: PLAT-614")
- def test_many_problems(self):
- # Test that problems work properly.
- self.browser.get(self.live_server_url + "/scenario/test_many_problems")
- header1 = BrowserQuery(self.browser, css="h1")
- self.assertEqual(header1.text[0], "XBlock: Many problems")
-
- # Find the numbers on the page.
- nums = self.browser.find_elements_by_css_selector("p.the_numbers")
- num_pairs = [tuple(int(n) for n in num.text.split()) for num in nums]
-
- # They should be all different.
- self.assertEqual(len(set(num_pairs)), self.num_problems)
-
- text_ctrls_xpath = '//div[@data-block-type="textinput_demo"][@data-name="sum_input"]/input'
- text_ctrls = self.browser.find_elements_by_xpath(text_ctrls_xpath)
- check_btns = BrowserQuery(self.browser, css='input.check')
- check_indicators = 'span.indicator'
-
- def assert_image(right_wrong_idx, expected_icon):
- """Assert that the img src text includes `expected_icon`"""
- for _ in range(3):
- try:
- sources = BrowserQuery(
- self.browser,
- css='{} img'.format(
- check_indicators,
- ),
- ).nth(right_wrong_idx).attrs('src')
- if sources and expected_icon in sources[0]:
- break
- time.sleep(.25)
- except StaleElementReferenceException as exc:
- print(exc)
- self.assertIn(expected_icon, sources[0])
-
- for i in range(self.num_problems):
- # Before answering, the indicator says Not Attempted.
- self.assertIn("Not attempted", BrowserQuery(self.browser, css=check_indicators).nth(i).text[0])
-
- answer = sum(num_pairs[i])
-
- for _ in range(2):
- # Answer right.
- text_ctrls[i].clear()
- text_ctrls[i].send_keys(str(answer))
- check_btns[i].click()
- assert_image(i, "/correct-icon.png")
-
- # Answer wrong.
- text_ctrls[i].clear()
- text_ctrls[i].send_keys(str(answer + 1))
- check_btns[i].click()
- assert_image(i, "/incorrect-icon.png")
diff --git a/workbench/test/test_thumbs.py b/workbench/test/test_thumbs.py
deleted file mode 100644
index a70da453..00000000
--- a/workbench/test/test_thumbs.py
+++ /dev/null
@@ -1,133 +0,0 @@
-"""Tests for the thumbs module"""
-
-
-import pytest
-from bok_choy.promise import EmptyPromise
-
-from workbench import scenarios
-from workbench.test.selenium_test import SeleniumTest
-
-pytestmark = pytest.mark.django_db
-
-
-class ThreeThumbsTest(SeleniumTest):
- """Test the functionalities of the three thumbs test XBlock."""
-
- def setUp(self):
- super().setUp()
-
- scenarios.add_xml_scenario(
- "test_three_thumbs", "three thumbs test",
- """"""
- )
- self.addCleanup(scenarios.remove_scenario, "test_three_thumbs")
-
- # Suzy opens the browser to visit the workbench
- self.browser.get(self.live_server_url)
-
- # She knows it's the site by the header
- header1 = self.browser.find_element_by_css_selector('h1')
- self.assertEqual(header1.text, 'XBlock scenarios')
-
- @pytest.mark.flaky(reruns=5, reruns_delay=2)
- def test_three_thumbs_initial_state(self):
- # She clicks on the three thumbs at once scenario
- link = self.browser.find_element_by_link_text('three thumbs test')
- link.click()
- self.wait_for_page_load(link, timeout=10)
-
- # The header reflects the XBlock
- header1 = self.browser.find_element_by_css_selector('h1')
- self.assertEqual(header1.text, 'XBlock: three thumbs test')
-
- # She sees that there are 3 sets of thumbs
- vertical_css = 'div.student_view > div.xblock-v1 > div.vertical'
-
- # The following will give a NoSuchElementException error
- # if it is not there
- vertical = self.browser.find_element_by_css_selector(vertical_css)
-
- # Make sure there are three thumbs blocks
- thumb_css = 'div.xblock-v1[data-block-type="thumbs"]'
- thumbs = vertical.find_elements_by_css_selector(thumb_css)
- self.assertEqual(3, len(thumbs))
-
- # Make sure they all have 0 for upvote and downvote counts
- up_count_css = 'span.upvote span.count'
- down_count_css = 'span.downvote span.count'
-
- for thumb in thumbs:
- up_count = thumb.find_element_by_css_selector(up_count_css)
- down_count = thumb.find_element_by_css_selector(down_count_css)
- self.assertEqual('0', up_count.text)
- self.assertEqual('0', down_count.text)
-
- @pytest.mark.flaky(reruns=5, reruns_delay=2)
- def test_three_upvoting(self):
- # She clicks on the three thumbs at once scenario
- link = self.browser.find_element_by_link_text('three thumbs test')
- link.click()
- self.wait_for_page_load(link, timeout=10)
-
- # The vertical that contains the thumbs
- vertical_css = 'div.student_view > div.xblock-v1 > div.vertical'
- vertical = self.browser.find_element_by_css_selector(vertical_css)
-
- # The three thumbs blocks
- thumb_css = 'div.xblock-v1[data-block-type="thumbs"]'
- thumbs = vertical.find_elements_by_css_selector(thumb_css)
-
- # Up and down counts
- up_count_css = 'span.upvote span.count'
- down_count_css = 'span.downvote span.count'
-
- # Up vote for the first thumb
- thumbs[0].find_element_by_css_selector('span.upvote').click()
-
- # Only the first thumb's upcount should increase
- _ = EmptyPromise(
- lambda: int(thumbs[0].find_element_by_css_selector(up_count_css).text) == 1,
- "upvote action succeeded"
- ).fulfill()
- self.assertEqual('0', thumbs[1].find_element_by_css_selector(up_count_css).text)
- self.assertEqual('0', thumbs[2].find_element_by_css_selector(up_count_css).text)
-
- # Down counts should all still be zero
- for thumb in thumbs:
- down_count = thumb.find_element_by_css_selector(down_count_css)
- self.assertEqual('0', down_count.text)
-
- @pytest.mark.flaky(reruns=5, reruns_delay=2)
- def test_three_downvoting(self):
- # She clicks on the three thumbs at once scenario
- link = self.browser.find_element_by_link_text('three thumbs test')
- link.click()
- self.wait_for_page_load(link, timeout=10)
-
- # The vertical that contains the thumbs
- vertical_css = 'div.student_view > div.xblock-v1 > div.vertical'
- vertical = self.browser.find_element_by_css_selector(vertical_css)
-
- # The three thumbs blocks
- thumb_css = 'div.xblock-v1[data-block-type="thumbs"]'
- thumbs = vertical.find_elements_by_css_selector(thumb_css)
-
- # Up and down counts
- up_count_css = 'span.upvote span.count'
- down_count_css = 'span.downvote span.count'
-
- # Up vote for the first thumb
- thumbs[0].find_element_by_css_selector('span.downvote').click()
-
- # Only the first thumb's downcount should increase
- _ = EmptyPromise(
- lambda: int(thumbs[0].find_element_by_css_selector(down_count_css).text) == 1,
- "downvote action succeeded"
- ).fulfill()
- self.assertEqual('0', thumbs[1].find_element_by_css_selector(down_count_css).text)
- self.assertEqual('0', thumbs[2].find_element_by_css_selector(down_count_css).text)
-
- # Up counts should all still be zero
- for thumb in thumbs:
- down_count = thumb.find_element_by_css_selector(up_count_css)
- self.assertEqual('0', down_count.text)