From 95560a0c9448dc2cfe0de4679d60450afb6942e5 Mon Sep 17 00:00:00 2001 From: zrana Date: Mon, 17 Dec 2018 17:05:17 +0500 Subject: [PATCH] Grading IV tests --- .../pages/studio/settings_graders.py | 144 ++++++++++++++++-- .../tests/studio/test_studio_grading.py | 113 +++++++++++++- 2 files changed, 242 insertions(+), 15 deletions(-) diff --git a/common/test/acceptance/pages/studio/settings_graders.py b/common/test/acceptance/pages/studio/settings_graders.py index 41e5d6e87b..5e780929ed 100644 --- a/common/test/acceptance/pages/studio/settings_graders.py +++ b/common/test/acceptance/pages/studio/settings_graders.py @@ -1,14 +1,16 @@ """ Course Grading Settings page. """ - from common.test.acceptance.pages.studio.settings import SettingsPage from common.test.acceptance.pages.studio.utils import press_the_notification_button from common.test.acceptance.pages.common.utils import click_css -from selenium.webdriver import ActionChains +from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.common.keys import Keys +from bok_choy.javascript import requirejs from bok_choy.promise import BrokenPromise +@requirejs('js/factories/settings_graders') class GradingPage(SettingsPage): """ Course Grading Settings page. @@ -16,6 +18,7 @@ class GradingPage(SettingsPage): url_path = "settings/grading" grade_ranges = '.grades .grade-specific-bar' + grace_period_field = '#course-grading-graceperiod' assignments = '.field-group.course-grading-assignment-list-item' def is_browser_on_page(self): @@ -29,6 +32,12 @@ class GradingPage(SettingsPage): """ return self.q(css=selector)[0].text + def add_new_assignment_type(self): + """ + Click New Assignment Type button. + """ + self.q(css='.new-button.new-course-grading-item.add-grading-data').click() + @property def total_number_of_grades(self): """ @@ -108,10 +117,97 @@ class GradingPage(SettingsPage): self.q(css='#course-grading-assignment-name').filter( lambda el: el.get_attribute('value') == old_name).fill(new_name) + def set_weight(self, assignment_name, weight): + """ + Set the weight of the assignment type. + + Arguments: + assignment_name (string): Assignment name for which weight is to be changed. + weight (string): New weight + """ + weight_id = '#course-grading-assignment-gradeweight' + f = self.q(css=weight_id).results[-1] + for __ in xrange(len(assignment_name)): + f.send_keys(Keys.END, Keys.BACK_SPACE) + f.send_keys(weight) + + def get_assignment_weight(self, assignment_name): + """ + Gets the weight of assignment + + Arguments: + assignment_name (str): Name of the assignment + Returns: + string: Weight of the assignment + """ + self.wait_for_element_visibility( + '#course-grading-assignment-gradeweight', + 'Weight fields are present' + ) + weight_id = '#course-grading-assignment-gradeweight' + index = self._get_type_index(assignment_name) + all_weight_elements = self.q(css=weight_id).results + return all_weight_elements[index].get_attribute('value') + + def is_notification_button_disbaled(self): + """ + Check to see if notification button is disabled. + + Returns: + bool: True if button is disabled. + """ + self.wait_for_element_visibility('.nav-actions>ul', 'Notification bar not visible.') + return self.q(css='.action-primary.action-save.is-disabled').present + + def edit_grade_name(self, new_grade_name): + """ + Edit name of the highest grade. + """ + self.wait_for_element_visibility(self.grade_ranges, 'Grades are visible') + self.q(css='span[contenteditable="true"]').fill(new_grade_name) + + def try_edit_fail_grade(self, field_value): + """ + Try to edit the name of lowest grade. + """ + self.wait_for_element_visibility(self.grade_ranges, 'Grades are visible') + try: + self.q(css='span[contenteditable="false"]').fill(field_value) + except BrokenPromise: + pass + + @property + def highest_grade_name(self): + """ + Get name of the highest grade. + """ + self.wait_for_element_visibility(self.grade_ranges, 'Grades are visible') + return self.q(css='span[contenteditable="true"]').first.text[0] + + @property + def lowest_grade_name(self): + """ + Get name of the lowest grade. + """ + self.wait_for_element_visibility(self.grade_ranges, 'Grades are visible') + return self.q(css='span[contenteditable="false"]').first.text[0] + + @property + def grace_period_value(self): + """ + Get the grace period field value. + """ + self.wait_for( + lambda: self.q(css='#course-grading-graceperiod').attrs('value')[0] != '00:00', + description="Grace period field is updated after save" + ) + return self.q(css='#course-grading-graceperiod').attrs('value')[0] + @property def grade_letters(self): """ Get names of grade ranges. + Returns: list: A list containing names of the grade ranges. """ @@ -126,6 +222,7 @@ class GradingPage(SettingsPage): def is_grade_added(self, length): """ Checks to see if grade is added by comparing number of grades after the addition + Returns: bool: True if grade is added bool: False if grade is not added @@ -140,17 +237,11 @@ class GradingPage(SettingsPage): except BrokenPromise: return False - def add_new_assignment_type(self): - """ - Add New Assignment type - """ - self.q(css='.add-grading-data').click() - self.save_changes() - @property def grades_range(self): """ Get ranges of all the grades. + Returns: list: A list containing ranges of all the grades """ @@ -207,7 +298,8 @@ class GradingPage(SettingsPage): while len(self.q(css='.remove-grading-data')) > 0: self.delete_assignment_type() - def get_confirmation_message(self): + @property + def confirmation_message(self): """ Get confirmation message received after saving settings. """ @@ -217,8 +309,10 @@ class GradingPage(SettingsPage): def _get_type_index(self, name): """ Gets the index of assignment type. + Arguments: name(str): name of the assignment + Returns: int: index of the assignment type """ @@ -241,9 +335,31 @@ class GradingPage(SettingsPage): """ press_the_notification_button(self, "Cancel") - def refresh_and_wait_for_load(self): + def set_grace_period(self, grace_time_value): """ - Refresh the page and wait for all resources to load. + Set value in grace period field. """ - self.browser.refresh() - self.wait_for_page() + self.set_element_value(grace_time_value) + + def check_field_value(self, field_value): + """ + Check updated values in input field + """ + self.wait_for( + lambda: self.q(css='#course-grading-graceperiod').attrs('value')[0] == field_value, + "Value of input field is correct." + ) + + def set_element_value(self, element_value): + """ + Set the values of the elements to those specified + in the element_values dict. + """ + element = self.q(css='#course-grading-graceperiod').results[0] + element.click() + element.clear() + self.wait_for( + lambda: self.q(css='#course-grading-graceperiod').attrs('value')[0] == '', + "Value of input field is correct." + ) + element.send_keys(element_value) diff --git a/common/test/acceptance/tests/studio/test_studio_grading.py b/common/test/acceptance/tests/studio/test_studio_grading.py index db1a1d5461..a0c7c6b76d 100644 --- a/common/test/acceptance/tests/studio/test_studio_grading.py +++ b/common/test/acceptance/tests/studio/test_studio_grading.py @@ -4,6 +4,7 @@ Acceptance tests for grade settings in Studio. from common.test.acceptance.pages.studio.settings_graders import GradingPage from common.test.acceptance.tests.studio.base_studio_test import StudioCourseTest from common.test.acceptance.fixtures.course import XBlockFixtureDesc +from bok_choy.promise import EmptyPromise class GradingPageTest(StudioCourseTest): @@ -12,6 +13,7 @@ class GradingPageTest(StudioCourseTest): """ url = None + GRACE_FIELD_CSS = "#course-grading-graceperiod" def setUp(self): # pylint: disable=arguments-differ super(GradingPageTest, self).setUp() @@ -23,6 +25,16 @@ class GradingPageTest(StudioCourseTest): ) self.grading_page.visit() + self.ensure_input_fields_are_loaded() + + def ensure_input_fields_are_loaded(self): + """ + Ensures values in input fields are loaded. + """ + EmptyPromise( + lambda: self.grading_page.q(css=self.GRACE_FIELD_CSS).attrs('value')[0], + "Waiting for input fields to be loaded" + ).fulfill() def populate_course_fixture(self, course_fixture): """ @@ -168,5 +180,104 @@ class GradingPageTest(StudioCourseTest): """ self.grading_page.change_assignment_name('Homework', 'New Type') self.grading_page.save() - confirmation_message = self.grading_page.get_confirmation_message() + confirmation_message = self.grading_page.confirmation_message self.assertEqual(confirmation_message, 'Your changes have been saved.') + + def test_staff_can_set_weight_to_assignment(self): + """ + Scenario: Users can set weight to Assignment types + Given I have opened a new course in Studio + And I am viewing the grading settings + When I add a new assignment type "New Type" + And I set the assignment weight to "7" + And I press the "Save" notification button + Then the assignment weight is displayed as "7" + And I reload the page + Then the assignment weight is displayed as "7" + """ + self.grading_page.add_new_assignment_type() + self.grading_page.change_assignment_name('', 'New Type') + self.grading_page.set_weight('New Type', '7') + self.grading_page.save() + assignment_weight = self.grading_page.get_assignment_weight('New Type') + self.assertEqual(assignment_weight, '7') + self.grading_page.refresh_and_wait_for_load() + assignment_weight = self.grading_page.get_assignment_weight('New Type') + self.assertEqual(assignment_weight, '7') + + def test_staff_cannot_save_invalid_settings(self): + """ + Scenario: User cannot save invalid settings + Given I have populated a new course in Studio + And I am viewing the grading settings + When I change assignment type "Homework" to "" + Then the save notification button is disabled + """ + self.grading_page.change_assignment_name('Homework', '') + self.assertTrue(self.grading_page.is_notification_button_disbaled(), True) + + def test_edit_highest_grade_name(self): + """ + Scenario: User can edit grading range names + Given I have populated a new course in Studio + And I am viewing the grading settings + When I change the highest grade range to "Good" + And I press the "Save" notification button + And I reload the page + Then I see the highest grade range is "Good" + """ + self.grading_page.edit_grade_name('Good') + self.grading_page.save() + self.grading_page.refresh_and_wait_for_load() + grade_name = self.grading_page.highest_grade_name + self.assertEqual(grade_name, 'Good') + + def test_staff_cannot_edit_lowest_grade_name(self): + """ + Scenario: User cannot edit failing grade range name + Given I have populated a new course in Studio + And I am viewing the grading settings + Then I cannot edit the "Fail" grade range + """ + self.grading_page.try_edit_fail_grade('Failure') + self.assertNotEqual(self.grading_page.lowest_grade_name, 'Failure') + + def test_grace_period_wrapped_to_correct_time(self): + """ + Scenario: Grace periods of more than 59 minutes are wrapped to the correct time + Given I have populated a new course in Studio + And I am viewing the grading settings + When I change the grace period to "01:99" + And I press the "Save" notification button + And I reload the page + Then I see the grace period is "02:39" + """ + self.ensure_input_fields_are_loaded() + self.grading_page.check_field_value('00:00') + self.grading_page.set_grace_period('01:99') + self.grading_page.check_field_value('01:99') + self.grading_page.click_button("save") + self.grading_page.refresh_and_wait_for_load() + self.ensure_input_fields_are_loaded() + grace_time = self.grading_page.grace_period_value + self.assertEqual(grace_time, '02:39') + + def test_setting_grace_period_greater_than_one_day(self): + """ + Scenario: User can set a grace period greater than one day + Given I have populated a new course in Studio + And I am viewing the grading settings + When I change the grace period to "48:00" + And I press the "Save" notification button + And I reload the page + Then I see the grace period is "48:00" + """ + self.ensure_input_fields_are_loaded() + self.grading_page.check_field_value('00:00') + self.grading_page.set_grace_period('48:00') + self.grading_page.check_field_value('48:00') + self.grading_page.click_button("save") + self.grading_page.refresh_and_wait_for_load() + self.ensure_input_fields_are_loaded() + grace_time = self.grading_page.grace_period_value + self.assertEqual(grace_time, '48:00')