diff --git a/templates/class-overview.html b/templates/class-overview.html index 05fb46bb3ae..f26a519961a 100644 --- a/templates/class-overview.html +++ b/templates/class-overview.html @@ -44,10 +44,10 @@

{{ class_info.name }}

View customizations + {% else %} - + {% endif %} diff --git a/templates/customize-class.html b/templates/customize-class.html index 7219a769737..cebafb52485 100644 --- a/templates/customize-class.html +++ b/templates/customize-class.html @@ -31,17 +31,17 @@

{{_('select_levels')}}

{{_('select_adventures')}}

- {% for i in range(1, max_level + 1) %} {% endfor %}
-
+
{% if customizations and customizations['sorted_adventures'] %} {% for level, adventures in customizations['sorted_adventures'].items() %} -
+
{% for adventure in adventures %} {% if adventure.name in adventure_names %} {# Note: this code is copy/pasted in teachers.ts. If you change it here, also change it there #} @@ -55,7 +55,7 @@

{{_('select_adventures')}}

{% endfor %} {% else %} {% for level, adventures in adventures_default_order.items() %} -
+
{% for adventure in adventures %}
@@ -67,7 +67,7 @@

{{_('select_adventures')}}

{% endif %}
-
@@ -87,7 +87,7 @@

{{_('opening_dates')}}

{% for i in range(1, max_level + 1) %} - + {{ _('level_title') }} {{ i }} {{_('unlock_thresholds')}} {{_('quiz_score')}} - + @@ -182,12 +183,12 @@

{{_('other_settings')}}

{# TODO JP: make a button that resets the adventures to the default in Hedy content #} - +
- - +
{% endif %} diff --git a/templates/for-teachers.html b/templates/for-teachers.html index 925cb4f6bdd..7c25ec740de 100644 --- a/templates/for-teachers.html +++ b/templates/for-teachers.html @@ -27,7 +27,7 @@

{{_('my_classes')}}

{% for class in teacher_classes %} - {{class.name|e}} + {{class.name|e}} {{class.students|length}} 🗑️ diff --git a/templates/layout.html b/templates/layout.html index 11be667a21d..cac9b143e8b 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -23,7 +23,7 @@ @@ -71,7 +71,7 @@ diff --git a/tests/cypress/e2e/for-teacher_page/customize_class_page/customize_class.cy.js b/tests/cypress/e2e/for-teacher_page/customize_class_page/customize_class.cy.js new file mode 100644 index 00000000000..e73d44f9e8c --- /dev/null +++ b/tests/cypress/e2e/for-teacher_page/customize_class_page/customize_class.cy.js @@ -0,0 +1,206 @@ +import {loginForTeacher} from '../../tools/login/login.js' +import { createClass } from "../../tools/classes/class"; + +describe('customize class page', () => { + beforeEach(() => { + loginForTeacher(); + createClass(); + cy.getBySel('view_class_link').first().click(); // Press on view class button + cy.getBySel('customize_class_button').click(); // Press customize class button + }); + + it('checks the option checkboxes', () => { + // following code checks every single checkbox on the current page: + cy.get('[type="checkbox"]').check({force:true}) + cy.get('[type="checkbox"]').should('be.checked') + cy.get('[type="checkbox"]').uncheck() + cy.get('[type="checkbox"]').should('be.not.checked') + }); + + it('goes back to the view class page', () => { + cy.getBySel('back_to_class') + .should('be.visible') + .should('not.be.disabled') + .click(); + // We should be in the view class page + cy.url() + .should('include', Cypress.config('baseUrl') + Cypress.env('class_page')); + }); + + it('the adventure dragger is hidden and the level dropdown changes which adventures are displayed', () => { + // Click on level 1 + cy.getBySel('adventures') + .select('1') + .should('have.value', '1'); + + // level 1 should be visible and level 2 not + cy.getBySel("level-1") + .should('be.visible'); + + cy.getBySel("level-2") + .should('not.be.visible'); + + // after selecting level 2 it should be visible and level 1 not + cy.getBySel('adventures') + .select('2') + .should('have.value', '2'); + + cy.getBySel("level-1") + .should('not.be.visible'); + + cy.getBySel("level-2") + .should('be.visible'); + }); + + it('tests if the opening tests are not empty', () => { + // The following line has a bug in cypress: + // cy.getBySel("opening_date_level_" + index).type("2023-01-01").should("have.value", "2023-01-01") + // The following tests only checks if the field is not empty using a for loop: + var levelarray = Array.from({length:18},(v, k)=>k+1) // length reflects how many levels there are + cy.wrap(levelarray).each((index) => { + cy.getBySel("opening_date_level_" + index).type("2023-01-01").should("not.be.empty"); + }); + }); + + it('the quiz score holds the value typed to it', () => { + // testing quiz score feature + cy.getBySel('quiz_input').type("50").should("have.value", "50"); + }); + + it('removes the adventure and checks that it is added to the available adventures drop down and removed from the dragger', () => { + + cy.getBySel('sortadventures') + .children() + .should('not.be.visible'); + + // Click on level 2 + cy.getBySel("adventures") + .select('2') + .should('have.value', '2'); + + // The available adventures dropdown should only include the default option + cy.getBySel("available_adventures_current_level") + .children() + .should('have.length', 1) + + // store the name of the adventure we're going to delete + cy.get('[data-cy="level-2"] div:first') + .invoke('attr', 'adventure') + .as('adventure') + .then(adventure => { + // Get the first adventure, and click its remove button + cy.get('[data-cy="level-2"] div:first span') + .click(); + + // The available adventures dropdown should now include the new adventure + cy.getBySel("available_adventures_current_level") + .children() + .should('have.length', 2); + + // the added option should be the last + cy.get('[data-cy="available_adventures_current_level"] option:last') + .should('have.id', `remove-${adventure}`); + + // after selecting the adventure, it shouldn't be among the options + cy.getBySel("available_adventures_current_level") + .select(1) + .children() + .should('have.length', 1); + + // the adventure should now be last + cy.get('[data-cy="level-2"] div:last') + .should('have.attr', 'adventure') + .and('eq', adventure); + }); + }); + + it('saves the customizations and then removes them, checking that the remove button hides accordingly', () => { + // Since this class is new it shouldn't have customizations + cy.getBySel('remove_customizations_button') + .should('not.be.visible'); + + // We save the customizations first + cy.getBySel("save_customizations") + .should('be.visible') + .should('not.be.disabled') + .click(); + + cy.getBySel('modal_alert_text') + .should('be.visible'); + + // Now that it has customizations we can remove them + cy.getBySel('remove_customizations_button') + .should('be.visible') + .should('not.be.disabled') + .click(); + + cy.getBySel('modal_yes_button') + .should('be.visible') + .click(); + + // It shouldn't have the button again + cy.getBySel('remove_customizations_button') + .should('not.be.visible'); + }); + + it('selects two adventures and swaps them using drag and drop', () => { + cy.getBySel('sortadventures') + .children() + .should('not.be.visible'); + + // Click on level 1 + cy.getBySel("adventures") + .select('1') + .should('have.value', '1'); + + // Now it should be visible + cy.getBySel('level-1').should('be.visible'); + + // Get the first and second adventure + cy.getBySel('level-1') + .children() + .eq(0) + .invoke('attr', 'adventure') + .as('first_adventure'); + + cy.getBySel('level-1') + .children() + .eq(1) + .invoke('attr', 'adventure') + .as('second_adventure'); + + // Getting their values first, and then moving them around + cy.get('@first_adventure').then(first_adventure => { + cy.get('@second_adventure').then(second_adventure => { + + // Move the second adventure to the first place + cy.getBySel('level-1') + .children() + .eq(1) + .trigger('dragstart') + .siblings() + .should('have.attr', 'class') + .and('contain', 'drop-adventures-hint'); + + cy.getBySel('level-1') + .children() + .eq(0) + .trigger('drop') + .trigger('dragend'); + + // they should be inverted now + cy.getBySel('level-1') + .children() + .eq(0) + .should('have.attr', 'adventure') + .and('eq', second_adventure); + + cy.getBySel('level-1') + .children() + .eq(1) + .should('have.attr', 'adventure') + .and('eq', first_adventure); + }) + }) + }); + }); \ No newline at end of file diff --git a/tests/cypress/e2e/for-teacher_page/customize_class_page/opening_dates.cy.js b/tests/cypress/e2e/for-teacher_page/customize_class_page/opening_dates.cy.js deleted file mode 100644 index 18414fdc28e..00000000000 --- a/tests/cypress/e2e/for-teacher_page/customize_class_page/opening_dates.cy.js +++ /dev/null @@ -1,26 +0,0 @@ -import { loginForTeacher } from '../../tools/login/login.js' -import { createClass } from "../../tools/classes/class"; - -// Test is incomplete, because it only checks if it is not empty instead of the value -// This is a bug in Cypress - -describe('Testing if opening dates is not empty', () => { - it('Passes', () => { - loginForTeacher(); - cy.wait(500); - createClass(); - - cy.get(".view_class").first().click(); // Press on view class button - - cy.get('#customize-class-button').click(); // Press customize class button - - // The following line has a bug in cypress: - // cy.get("#opening_date_level_" + index).type("2023-01-01").should("have.value", "2023-01-01") - // The following tests only checks if the field is not empty using a for loop: - var levelarray = Array.from({length:18},(v, k)=>k+1) // length reflects how many levels there are - cy.wrap(levelarray).each((index) => { - cy.get("#opening_date_level_" + index).type("2023-01-01").should("not.be.empty") - }) - - }) -}) \ No newline at end of file diff --git a/tests/cypress/e2e/for-teacher_page/customize_class_page/quiz_score.cy.js b/tests/cypress/e2e/for-teacher_page/customize_class_page/quiz_score.cy.js deleted file mode 100644 index 0c5d9bdd9c3..00000000000 --- a/tests/cypress/e2e/for-teacher_page/customize_class_page/quiz_score.cy.js +++ /dev/null @@ -1,18 +0,0 @@ -import { loginForTeacher } from '../../tools/login/login.js' -import { createClass } from "../../tools/classes/class"; - -describe('Testing if quiz_score has specific value', () => { - it('Passes', () => { - loginForTeacher(); - cy.wait(500); - createClass(); - - cy.get(".view_class").first().click(); // Press on view class button - - cy.get('#customize-class-button').click(); // Press customize class button - - // testing quiz score feature - cy.get('#quiz').type("50").should("have.value", "50") - - }) -}) \ No newline at end of file diff --git a/tests/cypress/e2e/for-teacher_page/customize_class_page/test_checkboxes.cy.js b/tests/cypress/e2e/for-teacher_page/customize_class_page/test_checkboxes.cy.js deleted file mode 100644 index fbbd7c7c5ee..00000000000 --- a/tests/cypress/e2e/for-teacher_page/customize_class_page/test_checkboxes.cy.js +++ /dev/null @@ -1,21 +0,0 @@ -import { loginForTeacher } from '../../tools/login/login.js' -import { createClass } from "../../tools/classes/class"; - -describe('Testing all checkboxes', () => { - it('Passes', () => { - loginForTeacher(); - cy.wait(500); - createClass(); - - cy.get(".view_class").first().click(); // Press on view class button - - cy.get('#customize-class-button').click(); // Press customize class button - - // following code checks every single checkbox on the current page: - cy.get('[type="checkbox"]').check({force:true}) - cy.get('[type="checkbox"]').should('be.checked') - cy.get('[type="checkbox"]').uncheck() - cy.get('[type="checkbox"]').should('be.not.checked') - - }) -}) \ No newline at end of file diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index 66ea16ef0e3..855cb98fe31 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -22,4 +22,12 @@ // // // -- This will overwrite an existing command -- -// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) \ No newline at end of file +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) + +Cypress.Commands.add('getBySel', (selector, ...args) => { + return cy.get(`[data-cy=${selector}]`, ...args) +}) + +Cypress.Commands.add('getBySelLike', (selector, ...args) => { + return cy.get(`[data-cy*=${selector}]`, ...args) +}) \ No newline at end of file diff --git a/website/for_teachers.py b/website/for_teachers.py index 847d171ea45..9d73bfa4666 100644 --- a/website/for_teachers.py +++ b/website/for_teachers.py @@ -181,9 +181,7 @@ def get_class_info(self, user, class_id): teacher_adventures = self.db.get_teacher_adventures(user["username"]) customizations = self.db.get_class_customizations(class_id) - print("*"*100) - print(adventures) - print("*"*100) + adventure_names = {} for adv_key, adv_dic in adventures.items(): for name, _ in adv_dic.items():