Merge pull request #23232 from edx/feanil/remove_unused_bokchoy_pages

Feanil/remove unused bokchoy pages
This commit is contained in:
Feanil Patel
2020-03-02 11:37:09 -05:00
committed by GitHub
17 changed files with 1 additions and 815 deletions

View File

@@ -1,101 +0,0 @@
"""
Annotation Component Page.
"""
from bok_choy.page_object import PageObject
from selenium.webdriver import ActionChains
class AnnotationComponentPage(PageObject):
"""
View of annotation component page.
"""
url = None
active_problem = 0
def is_browser_on_page(self):
return self.q(css='.annotatable-title').present
@property
def component_name(self):
"""
Return the current problem name.
"""
return self.q(css='.annotatable-title').text[0]
def click_reply_annotation(self, problem):
"""
Mouse over on annotation selector and click on "Reply to Annotation".
"""
annotation_span_selector = '.annotatable-span[data-problem-id="{}"]'.format(problem)
self.mouse_hover(self.browser.find_element_by_css_selector(annotation_span_selector))
self.wait_for_element_visibility(annotation_span_selector, "Reply to Annotation link is visible")
annotation_reply_selector = '.annotatable-reply[data-problem-id="{}"]'.format(problem)
self.q(css=annotation_reply_selector).click()
self.active_problem = problem
def active_problem_selector(self, sub_selector):
"""
Return css selector for current active problem with sub_selector.
"""
return u'div[data-problem-id="{}"] {}'.format(
self.q(css='.vert-{}'.format(self.active_problem + 1)).map(
lambda el: el.get_attribute('data-id')).results[0],
sub_selector,
)
def mouse_hover(self, element):
"""
Mouse over on given element.
"""
mouse_hover_action = ActionChains(self.browser).move_to_element(element)
mouse_hover_action.perform()
def check_scroll_to_problem(self):
"""
Return visibility of active problem's input selector.
"""
annotation_input_selector = self.active_problem_selector('.annotation-input')
return self.q(css=annotation_input_selector).visible
def answer_problem(self):
"""
Submit correct answer for active problem.
"""
self.q(css=self.active_problem_selector('.comment')).fill('Test Response')
answer_css = self.active_problem_selector('.tag[data-id="{}"]'.format(self.active_problem))
# Selenium will first move the element into view then click on it.
self.q(css=answer_css).click()
# Wait for the click to take effect, which is after the class is applied.
self.wait_for(lambda: 'selected' in self.q(css=answer_css).attrs('class')[0], description='answer selected')
# Click the "Check" button.
self.q(css=self.active_problem_selector('.submit')).click()
# This will trigger a POST to problem_check so wait until the response is returned.
self.wait_for_ajax()
def check_feedback(self):
"""
Return visibility of active problem's feedback.
"""
self.wait_for_element_visibility(
self.active_problem_selector('.tag-status.correct'), "Correct is visible"
)
return self.q(css=self.active_problem_selector('.tag-status.correct')).visible
def click_return_to_annotation(self):
"""
Click on active problem's "Return to Annotation" link.
"""
self.q(css=self.active_problem_selector('.annotation-return')).click()
def check_scroll_to_annotation(self):
"""
Return visibility of active annotation component header.
"""
annotation_header_selector = '.annotation-header'
return self.q(css=annotation_header_selector).visible

View File

@@ -1,51 +0,0 @@
# -*- coding: utf-8 -*-
"""
CCX coach dashboard page
"""
from bok_choy.promise import EmptyPromise
from common.test.acceptance.pages.lms.course_page import CoursePage
class CoachDashboardPage(CoursePage):
"""
CCX coach dashboard, where ccx coach can manage a course.
"""
url_path = "ccx_coach"
def is_browser_on_page(self):
"""
check if ccx dashboard is open.
"""
return self.q(css='div.instructor-dashboard-wrapper-2').present
def is_browser_on_enrollment_page(self):
"""
check if enrollment page in ccx dashboard is open.
"""
return self.q(css='div.batch-enrollment-ccx').present
def fill_ccx_name_text_box(self, ccx_name):
"""
Fill in the form with the provided ccx name and submit it.
"""
ccx_name_selector = "#ccx_name"
create_ccx_button = "#create-ccx"
# Fill the ccx_name.
self.wait_for_element_visibility(ccx_name_selector, 'CCX name field is visible')
self.q(css=ccx_name_selector).fill(ccx_name)
# Verify create ccx button is present before clicking.
EmptyPromise(
lambda: self.q(css=create_ccx_button).present, "Create a new Custom Course for edX"
).fulfill()
self.q(css=create_ccx_button).click()
def is_button_view_unit_in_studio_visible(self):
"""
check if the View Unit in Studio button is on the page
"""
return self.q(css='instructor-info-action').present

View File

@@ -1,65 +0,0 @@
"""
Conditional Pages
"""
from bok_choy.page_object import PageObject
from bok_choy.promise import BrokenPromise, EmptyPromise
POLL_ANSWER = 'Yes, of course'
class ConditionalPage(PageObject):
"""
View of conditional page.
"""
url = None
def is_browser_on_page(self):
"""
Returns True if the browser is currently on the right page.
"""
# This is all a hack to work around the fact that there's no way to adjust the
# timeout parameters for self.q
def check_fn():
return self.q(css='.conditional-wrapper').visible
try:
EmptyPromise(
check_fn,
"On conditional page",
).fulfill()
return True
except BrokenPromise:
return False
def is_content_visible(self):
"""
Returns True if the conditional's content has been revealed,
False otherwise
"""
def check_fn():
return self.q(css='.hidden-contents').visible
try:
EmptyPromise(
check_fn,
"Conditional is visible",
).fulfill()
return True
except BrokenPromise:
return False
def fill_in_poll(self):
"""
Fills in a poll on the same page as the conditional
with the answer that matches POLL_ANSWER
"""
text_selector = '.poll_answer .text'
text_options = self.q(css=text_selector).text
# Out of the possible poll answers, we want
# to select the one that matches POLL_ANSWER and click it.
for idx, text in enumerate(text_options):
if text == POLL_ANSWER:
self.q(css=text_selector).nth(idx).click()

View File

@@ -1,42 +0,0 @@
"""
Dashboard search
"""
from bok_choy.page_object import PageObject
from common.test.acceptance.pages.lms import BASE_URL
class DashboardSearchPage(PageObject):
"""
Dashboard page featuring a search form
"""
search_bar_selector = '#dashboard-search-bar'
url = "{base}/dashboard".format(base=BASE_URL)
@property
def search_results(self):
""" search results list showing """
return self.q(css='.search-results')
def is_browser_on_page(self):
""" did we find the search bar in the UI """
return self.q(css=self.search_bar_selector).present
def enter_search_term(self, text):
""" enter the search term into the box """
self.q(css=self.search_bar_selector + ' input[type="text"]').fill(text)
def search(self):
""" execute the search """
self.q(css=self.search_bar_selector + ' [type="submit"]').click()
self.wait_for_element_visibility('.search-info', 'Search results are shown')
def search_for_term(self, text):
"""
Search and return results
"""
self.enter_search_term(text)
self.search()

View File

@@ -360,129 +360,6 @@ class EdxNotesPage(CoursePage, PaginatedUIMixin):
return len(self.q(css='div.wrapper-note-excerpts').results)
class EdxNotesPageNoContent(CoursePage):
"""
EdxNotes page -- when no notes have been added.
"""
url_path = "edxnotes/"
def is_browser_on_page(self):
return self.q(css=".wrapper-student-notes .is-empty").visible
@property
def no_content_text(self):
"""
Returns no content message.
"""
element = self.q(css=".is-empty").first
if element:
return element.text[0]
else:
return None
class EdxNotesUnitPage(CoursePage):
"""
Page for the Unit with EdxNotes.
"""
url_path = "courseware/"
def is_browser_on_page(self):
return self.q(css="body.courseware .edx-notes-wrapper").present
def move_mouse_to(self, selector):
"""
Moves mouse to the element that matches `selector(str)`.
"""
body = self.q(css=selector)[0]
ActionChains(self.browser).move_to_element(body).perform()
return self
def click(self, selector):
"""
Clicks on the element that matches `selector(str)`.
"""
self.q(css=selector).first.click()
return self
def toggle_visibility(self):
"""
Clicks on the "Show notes" checkbox.
"""
self.q(css=".action-toggle-notes").first.click()
return self
@property
def components(self):
"""
Returns a list of annotatable components.
"""
components = self.q(css=".edx-notes-wrapper")
return [AnnotatableComponent(self.browser, component.get_attribute("id")) for component in components]
@property
def notes(self):
"""
Returns a list of notes for the page.
"""
notes = []
for component in self.components:
notes.extend(component.notes)
return notes
def refresh(self):
"""
Refreshes the page and returns a list of annotatable components.
"""
self.browser.refresh()
return self.components
class AnnotatableComponent(NoteChild):
"""
Helper class that works with annotatable components.
"""
BODY_SELECTOR = ".edx-notes-wrapper"
@property
def notes(self):
"""
Returns a list of notes for the component.
"""
notes = self.q(css=self._bounded_selector(".annotator-hl"))
return [EdxNoteHighlight(self.browser, note, self.item_id) for note in notes]
def create_note(self, selector=".annotate-id"):
"""
Create the note by the selector, return a context manager that will
show and save the note popup.
"""
for element in self.q(css=self._bounded_selector(selector)):
note = EdxNoteHighlight(self.browser, element, self.item_id)
note.select_and_click_adder()
yield note
note.save()
def edit_note(self, selector=".annotator-hl"):
"""
Edit the note by the selector, return a context manager that will
show and save the note popup.
"""
for element in self.q(css=self._bounded_selector(selector)):
note = EdxNoteHighlight(self.browser, element, self.item_id)
note.show().edit()
yield note
note.save()
def remove_note(self, selector=".annotator-hl"):
"""
Removes the note by the selector.
"""
for element in self.q(css=self._bounded_selector(selector)):
note = EdxNoteHighlight(self.browser, element, self.item_id)
note.show().remove()
class EdxNoteHighlight(NoteChild):
"""
Helper class that works with notes.

View File

@@ -1,28 +0,0 @@
"""
Find courses page (main page of the LMS).
"""
from bok_choy.page_object import PageObject
from common.test.acceptance.pages.lms import BASE_URL
class FindCoursesPage(PageObject):
"""
Find courses page (main page of the LMS).
"""
url = BASE_URL
def is_browser_on_page(self):
return "edX" in self.browser.title
@property
def course_id_list(self):
"""
Retrieve the list of available course IDs
on the page.
"""
return self.q(css='article.course').attrs('id')

View File

@@ -1347,70 +1347,6 @@ class StudentSpecificAdmin(StudentAdminPage):
TASK_HISTORY_TABLE_NAME = "task-history-single-table"
class CourseSpecificAdmin(StudentAdminPage):
"""
Course specific section of the Student Admin page.
"""
CONTAINER = ".course-specific-container"
PROBLEM_INPUT_NAME = "problem-select-all"
STUDENT_EMAIL_INPUT_NAME = None
RESET_ATTEMPTS_BUTTON_NAME = "reset-attempts-all"
RESCORE_BUTTON_NAME = "rescore-problem-all"
RESCORE_IF_HIGHER_BUTTON_NAME = "rescore-problem-all-if-higher"
DELETE_STATE_BUTTON_NAME = None
BACKGROUND_TASKS_BUTTON_NAME = "task-history-all"
TASK_HISTORY_TABLE_NAME = "task-history-all-table"
class EntranceExamAdmin(StudentAdminPage):
"""
Entrance exam section of the Student Admin page.
"""
CONTAINER = ".entrance-exam-grade-container"
STUDENT_EMAIL_INPUT_NAME = "entrance-exam-student-select-grade"
PROBLEM_INPUT_NAME = None
RESET_ATTEMPTS_BUTTON_NAME = "reset-entrance-exam-attempts"
RESCORE_BUTTON_NAME = "rescore-entrance-exam"
RESCORE_IF_HIGHER_BUTTON_NAME = "rescore-entrance-exam-if-higher"
DELETE_STATE_BUTTON_NAME = "delete-entrance-exam-state"
BACKGROUND_TASKS_BUTTON_NAME = "entrance-exam-task-history"
TASK_HISTORY_TABLE_NAME = "entrance-exam-task-history-table"
@property
def skip_entrance_exam_button(self):
"""
Return Let Student Skip Entrance Exam button.
"""
return self.q(css=u'{} input[name=skip-entrance-exam]'.format(self.CONTAINER))
@property
def top_notification(self):
"""
Returns show background task history for student button.
"""
return self.q(css=u'{} .request-response-error'.format(self.CONTAINER)).first
def are_all_buttons_visible(self):
"""
Returns whether all buttons related to entrance exams
are visible.
"""
return (
self.student_email_or_username_input.is_present() and
self.reset_attempts_button.is_present() and
self.rescore_button.is_present() and
self.rescore_if_higher_button.is_present() and
self.delete_state_button.is_present() and
self.task_history_button.is_present()
)
class CertificatesPage(PageObject):
"""
Certificates section of the Instructor dashboard.

View File

@@ -1,45 +0,0 @@
"""
Matlab Problem Page.
"""
from bok_choy.page_object import PageObject
class MatlabProblemPage(PageObject):
"""
View of matlab problem page.
"""
url = None
def is_browser_on_page(self):
return self.q(css='.ungraded-matlab-result').present
@property
def problem_name(self):
"""
Return the current problem name.
"""
return self.q(css='.problem-header').text[0]
def set_response(self, response_str):
"""
Input a response to the prompt.
"""
input_css = "$('.CodeMirror')[0].CodeMirror.setValue('{}');".format(response_str)
self.browser.execute_script(input_css)
def click_run_code(self):
"""
Click the run code button.
"""
self.q(css='input.save').click()
self.wait_for_ajax()
def get_grader_msg(self, class_name):
"""
Returns the text value of given class.
"""
self.wait_for_element_visibility(class_name, 'Grader message is visible')
return self.q(css=class_name).text

View File

@@ -166,37 +166,3 @@ class FakePaymentPage(PageObject):
self.q(css="input[value='Submit']").click()
return PaymentAndVerificationFlow(self.browser, self._course_id, entry_point='payment-confirmation').wait_for_page()
class FakeSoftwareSecureVerificationPage(PageObject):
"""
This page is a page used for testing that allows the user to change the status of their most recent
verification.
"""
url = BASE_URL + '/verify_student/software-secure-fake-response'
def is_browser_on_page(self):
""" Determine if browser is on the page. """
message = self.q(css='BODY').text
if not message:
return False
match = re.search('Fake Software Secure page', message[0])
return True if match else False
def mark_approved(self):
""" Mark the latest verification attempt as passing. """
self.q(css='#btn_pass').click()
def mark_denied(self):
""" Mark the latest verification attempt as denied. """
self.q(css='#btn_denied').click()
def mark_error(self):
""" Mark the latest verification attempt as an error. """
self.q(css='#btn_error').click()
def mark_unkown_error(self):
""" Mark the latest verification attempt as an unknown error. """
self.q(css='#btn_unkonwn_error').click()

View File

@@ -1,44 +0,0 @@
"""
Page that allows the student to grade calibration essays
(requirement for being allowed to grade peers).
"""
from bok_choy.page_object import PageObject
from bok_choy.promise import Promise
class PeerCalibratePage(PageObject):
"""
Grade calibration essays.
"""
url = None
def is_browser_on_page(self):
def _is_correct_page():
is_present = (
self.q(css='div.peer-grading-tools').present or
self.q(css='div.calibration-panel.current-state').present
)
return is_present, is_present
return Promise(_is_correct_page, 'On the peer grading calibration page.').fulfill()
def continue_to_grading(self):
"""
Continue to peer grading after completing calibration.
"""
self.q(css='input.calibration-feedback-button').first.click()
@property
def message(self):
"""
Return a message shown to the user, or None if no message is available.
"""
messages = self.q(css='div.peer-grading-tools > div.message-container > p').text
if len(messages) < 1:
return None
else:
return messages[0]

View File

@@ -1,35 +0,0 @@
"""
Confirmation screen for peer calibration and grading.
"""
from bok_choy.page_object import PageObject
from bok_choy.promise import Promise
class PeerConfirmPage(PageObject):
"""
Confirmation for peer calibration and grading.
"""
url = None
def is_browser_on_page(self):
def _is_correct_page():
is_present = self.q(css='section.calibration-interstitial-page').present
return is_present, is_present
return Promise(_is_correct_page, 'On the confirmation page for peer calibration and grading.').fulfill()
def start(self, is_calibrating=False):
"""
Continue to the next section after the confirmation page.
If `is_calibrating` is false, try to continue to peer grading.
Otherwise, try to continue to calibration grading.
"""
if is_calibrating:
css_selector = 'input.calibration-interstitial-page-button'
else:
css_selector = 'input.interstitial-page-button'
self.q(css=css_selector).first.click()

View File

@@ -1,39 +0,0 @@
"""
Students grade peer submissions.
"""
from bok_choy.page_object import PageObject
from bok_choy.promise import Promise
class PeerGradePage(PageObject):
"""
Students grade peer submissions.
"""
url = None
def is_browser_on_page(self):
def _is_correct_page():
is_present = (
self.q(css='div.peer-grading-tools').present or
self.q(css='div.grading-panel.current-state').present
)
return is_present, is_present
return Promise(_is_correct_page, 'On the peer grading page.').fulfill()
@property
def problem_list(self):
"""
Return the list of available problems to peer grade.
"""
return self.q(css='a.problem-button').text
def select_problem(self, problem_name):
"""
Choose the problem with `problem_name` to start grading or calibrating.
"""
index = self.problem_list.index(problem_name) + 1
self.q(css='a.problem-button:nth-of-type({})'.format(index)).first.click()

View File

@@ -1,30 +0,0 @@
"""
Course Textbooks page.
"""
from bok_choy.promise import EmptyPromise
from common.test.acceptance.pages.lms.course_page import CoursePage
class TextbookViewPage(CoursePage):
"""
Course Textbooks page.
"""
url_path = "pdfbook/0/"
def is_browser_on_page(self):
return self.q(css='.book-sidebar').present
def switch_to_pdf_frame(self, test):
"""
Waits for pdf frame to load, then switches driver to the frame
"""
EmptyPromise(
lambda: self.q(css='iframe').present, "Iframe loaded"
).fulfill()
driver = test.get_web_driver()
driver.switch_to_frame(driver.find_element_by_tag_name("iframe"))

View File

@@ -1,44 +0,0 @@
"""
Course rerun page in Studio
"""
from common.test.acceptance.pages.studio.course_page import CoursePage
from common.test.acceptance.pages.studio.utils import set_input_value
class CourseRerunPage(CoursePage):
"""
Course rerun page in Studio
"""
url_path = "course_rerun"
COURSE_RUN_INPUT = '.rerun-course-run'
def is_browser_on_page(self):
"""
Returns True iff the browser has loaded the course rerun page.
"""
return self.q(css='body.view-course-create-rerun').present
@property
def course_run(self):
"""
Returns the value of the course run field.
"""
return self.q(css=self.COURSE_RUN_INPUT).text[0]
@course_run.setter
def course_run(self, value):
"""
Sets the value of the course run field.
"""
set_input_value(self, self.COURSE_RUN_INPUT, value)
def create_rerun(self):
"""
Clicks the create rerun button.
"""
self.q(css='.rerun-course-save')[0].click()
# Clicking on the course will trigger an ajax event
self.wait_for_ajax()

View File

@@ -1,15 +0,0 @@
"""
Edit Subsection page in Studio
"""
from bok_choy.page_object import PageObject
class SubsectionPage(PageObject):
"""
Edit Subsection page in Studio
"""
def is_browser_on_page(self):
return self.q(css='body.view-subsection').present

View File

@@ -1,54 +0,0 @@
"""
PageObject for Crowdsourcehinter
"""
from bok_choy.page_object import PageObject
class CrowdsourcehinterProblemPage(PageObject):
"""
A PageObject representing the Crowdsourcehinter xblock.
"""
url = None
def is_browser_on_page(self):
return len(self.browser.find_elements_by_class_name('crowdsourcehinter_block')) > 0
def submit_text_answer(self, text):
"""
Submit an answer to the problem block
"""
self.q(css='input[type="text"]').fill(text)
self.q(css='.action [data-value="Submit"]').click()
self.wait_for_ajax()
def get_hint_text(self):
"""
Return the hint shown to the student
"""
return self.q(css='div.csh_hint_text').text
def get_student_answer_text(self):
"""
Check the student answer is set correctly
"""
return self.q(css='div.csh_hint_text').attrs('student_answer')
def rate_hint(self):
"""
Click the rate_hint button
"""
self.q(css='div.csh_rate_hint').click()
self.wait_for_ajax()
def submit_new_hint(self, text):
"""
Fill in the textbox and submit a new hint
"""
self.q(css='.csh_student_hint_creation input[type="button"]').click()
self.wait_for_ajax()
self.q(css='.csh_student_text_input input[type="text"]').fill(text)
self.q(css='.csh_submit_new input[type="button"]').click()
self.wait_for_ajax()

View File

@@ -19,7 +19,7 @@ from ...pages.lms.course_home import CourseHomePage
from ...pages.lms.courseware import CoursewarePage, CoursewareSequentialTabPage
from ...pages.lms.create_mode import ModeCreationPage
from ...pages.lms.dashboard import DashboardPage
from ...pages.lms.pay_and_verify import FakePaymentPage, FakeSoftwareSecureVerificationPage, PaymentAndVerificationFlow
from ...pages.lms.pay_and_verify import FakePaymentPage, PaymentAndVerificationFlow
from ...pages.lms.problem import ProblemPage
from ...pages.lms.progress import ProgressPage
from ...pages.lms.track_selection import TrackSelectionPage