mirror of
https://github.com/UniversityOfHelsinkiCS/oodikone.git
synced 2026-10-12 19:03:39 +03:00
[RIP][Cypress] Wave goodbye to cypress o7, you will not be missed
This commit is contained in:
committed by
Aaro Koivukangas
parent
d25e950d8a
commit
e75a521284
@@ -8,7 +8,6 @@
|
||||
"**/coverage/**",
|
||||
"nyc-config.cjs",
|
||||
".lintstagedrc.mjs",
|
||||
"cypress.config.js",
|
||||
"playwright/**/*.js"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
name: 'Run tests'
|
||||
description: 'Runs Cypress tests for individual spec'
|
||||
|
||||
inputs:
|
||||
username:
|
||||
required: true
|
||||
description: 'Toska registry username'
|
||||
password:
|
||||
required: true
|
||||
description: 'Toska registry password'
|
||||
spec:
|
||||
required: true
|
||||
description: 'Path to Cypress file'
|
||||
test_name:
|
||||
required: true
|
||||
description: 'Name of the test'
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: 'Login to toska Docker registry'
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: registry-toska.ext.ocp-prod-0.k8s.it.helsinki.fi
|
||||
username: ${{ inputs.username }}
|
||||
password: ${{ inputs.password }}
|
||||
|
||||
- name: 'Run services, pull rest of the needed images'
|
||||
shell: bash
|
||||
run: docker compose --file docker-compose.ci.yml --profile oodikone up --detach --quiet-pull
|
||||
|
||||
- name: Run Cypress inside docker container
|
||||
shell: bash
|
||||
# Permission errors? See: https://github.com/cypress-io/cypress-docker-images/blob/master/examples/included-as-non-root/README.md#run-as-non-root
|
||||
run: |
|
||||
docker run --user node --rm -v $PWD:/e2e -w /e2e --add-host host.docker.internal:host-gateway -e CYPRESS_VIDEO -e CYPRESS_baseUrl=http://host.docker.internal:1337 --entrypoint cypress cypress/included:15.18.1 run --browser firefox --spec ${{ inputs.spec }}
|
||||
|
||||
- name: 'Upload video if tests fail'
|
||||
uses: actions/upload-artifact@v7
|
||||
if: failure()
|
||||
with:
|
||||
name: 'Cypress videos - ${{ inputs.test_name }}'
|
||||
path: /tmp/cypress/videos/*
|
||||
retention-days: 7
|
||||
|
||||
- name: 'Print logs on failure'
|
||||
shell: bash
|
||||
if: failure()
|
||||
run: npm run logs:ci && sleep 15
|
||||
|
||||
- name: Teardown containers started by compose
|
||||
if: always()
|
||||
uses: ./.github/actions/teardown
|
||||
@@ -13,8 +13,6 @@ on:
|
||||
- 'docker-compose.ci.yml'
|
||||
- 'docker-compose.test.yml'
|
||||
- 'package*.json'
|
||||
- 'cypress/**'
|
||||
- 'cypress.config.json'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
|
||||
@@ -13,8 +13,6 @@ on:
|
||||
- 'docker-compose.ci.yml'
|
||||
- 'docker-compose.test.yml'
|
||||
- 'package*.json'
|
||||
- 'cypress/**'
|
||||
- 'cypress.config.json'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
npx lint-staged
|
||||
|
||||
if git grep -qE --cached "(it|describe)\.only" $(git diff --cached --name-only --diff-filter=ACMR | xargs) ./cypress; then
|
||||
if git grep -qE --cached "(it|describe)\.only" $(git diff --cached --name-only --diff-filter=ACMR | xargs); then
|
||||
echo "\e[0;31mDo not commit .only-tests."
|
||||
exit 1
|
||||
else
|
||||
|
||||
@@ -45,8 +45,6 @@
|
||||
"**/coverage/**",
|
||||
"nyc-config.cjs",
|
||||
".lintstagedrc.mjs",
|
||||
"cypress.config.js",
|
||||
"cypress/**/*.js",
|
||||
"playwright/**/*.js",
|
||||
"playwright.config.ts"
|
||||
],
|
||||
@@ -348,26 +346,6 @@
|
||||
},
|
||||
"plugins": ["react"]
|
||||
},
|
||||
{
|
||||
"files": ["cypress/**/*.js"],
|
||||
"rules": {
|
||||
"cypress/no-assigning-return-values": "error",
|
||||
"cypress/no-unnecessary-waiting": "error",
|
||||
"cypress/no-async-tests": "error",
|
||||
"cypress/unsafe-to-chain-command": "error"
|
||||
},
|
||||
"jsPlugins": ["eslint-plugin-cypress"],
|
||||
"globals": {
|
||||
"cy": "readonly",
|
||||
"Cypress": "readonly",
|
||||
"expect": "readonly",
|
||||
"assert": "readonly",
|
||||
"chai": "readonly"
|
||||
},
|
||||
"env": {
|
||||
"mocha": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["services/backend/tests/**/*.ts"],
|
||||
"rules": {
|
||||
|
||||
@@ -183,7 +183,6 @@ Playwright
|
||||
- Run all migrated specs with `npm run playwright`.
|
||||
- Run headed mode with `npm run playwright:headed`.
|
||||
- Open UI mode with `npm run playwright:ui`.
|
||||
- The migration from Cypress was done with an automated converter. The generated files are a baseline and still need manual cleanup in places where `cy.*` logic is left over.
|
||||
|
||||
Continuous integration (CI) works with Github actions and is defined in workflow files in `.github/workflows` folder:
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/* eslint-disable import-x/no-extraneous-dependencies */
|
||||
/* eslint-disable import-x/no-default-export */
|
||||
const { defineConfig } = require('cypress')
|
||||
|
||||
module.exports = defineConfig({
|
||||
projectId: 'c3jsph',
|
||||
|
||||
// Fixes Github <-> Cypress permission errors in CI
|
||||
downloadsFolder: '/tmp/cypress/downloads',
|
||||
screenshotsFolder: '/tmp/cypress/screenshots',
|
||||
videosFolder: '/tmp/cypress/videos',
|
||||
video: true,
|
||||
|
||||
defaultCommandTimeout: 30000,
|
||||
requestTimeout: 30000,
|
||||
videoCompression: false,
|
||||
viewportWidth: 1920,
|
||||
viewportHeight: 1080,
|
||||
e2e: {
|
||||
// We've imported your old cypress plugins here.
|
||||
// You may want to clean this up later by importing these.
|
||||
setupNodeEvents(on, config) {
|
||||
require('./cypress/plugins/index.js')(on, config)
|
||||
return config
|
||||
},
|
||||
baseUrl: 'http://localhost:3000',
|
||||
specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}',
|
||||
},
|
||||
})
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,192 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
const fillName = () => {
|
||||
const name = `TEST-${new Date().getTime()}`
|
||||
cy.contains('Insert a name for this custom population if you wish to save it')
|
||||
cy.cs('custom-population-name-input').type(name)
|
||||
return name
|
||||
}
|
||||
|
||||
const save = () => {
|
||||
cy.get('button').contains('Save').click()
|
||||
}
|
||||
|
||||
const selectSavedPopulation = name => {
|
||||
cy.cs('history-search').type(`${name}{enter}`)
|
||||
}
|
||||
|
||||
const deleteAllSearches = () => {
|
||||
cy.cs('history-search').click()
|
||||
cy.get('.MuiAutocomplete-popper > .MuiPaper-root')
|
||||
.find('li[role=option]')
|
||||
.then($lis => {
|
||||
const labels = [...$lis].map(li => li.textContent?.trim() || '')
|
||||
|
||||
labels.forEach((label, index) => {
|
||||
if (index !== 0) cy.cs('history-search').click()
|
||||
cy.contains('.MuiAutocomplete-popper li[role=option]', label).click()
|
||||
cy.contains('button', 'Delete').click()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const fillForm = (content, separator) => {
|
||||
cy.cs('student-number-input').type(content.join(separator))
|
||||
}
|
||||
|
||||
const search = () => {
|
||||
cy.cs('search-button').click()
|
||||
}
|
||||
|
||||
const searchFor = (studentnumbers, separator) => {
|
||||
fillForm(studentnumbers, separator)
|
||||
search()
|
||||
}
|
||||
|
||||
const hasLanded = () => {
|
||||
cy.contains('Credit accumulation')
|
||||
cy.contains('Programme distribution')
|
||||
cy.contains('Courses of population')
|
||||
cy.contains('Students')
|
||||
}
|
||||
|
||||
const containsAmountOfStudents = (amount = 0) => {
|
||||
cy.contains(`Credit accumulation (for ${amount} students)`)
|
||||
}
|
||||
|
||||
const containsSpecificStudents = (studentnumbers = []) => {
|
||||
cy.contains(`Students (${studentnumbers.length})`)
|
||||
.parent()
|
||||
.then($parentDiv => {
|
||||
if (!$parentDiv.hasClass('active')) cy.contains(`Students (${studentnumbers.length})`).click()
|
||||
})
|
||||
|
||||
studentnumbers.forEach(s => cy.contains(s))
|
||||
}
|
||||
|
||||
const checkRightsNotification = studentNumbers => {
|
||||
cy.cs('rights-notification').within(() => {
|
||||
cy.contains(
|
||||
'The following students information could not be displayed. This could be either because they do not exist, or you do not have the right to view their information.'
|
||||
)
|
||||
cy.get('ul').within(() => {
|
||||
studentNumbers.forEach(number => cy.get('li').contains(number))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
describe('Custom population tests', () => {
|
||||
const nonExistentStudentNumbers = ['123', 'X', '-']
|
||||
beforeEach(() => {
|
||||
cy.init('/custompopulation')
|
||||
cy.url().should('include', '/custompopulation')
|
||||
cy.contains('Custom population')
|
||||
})
|
||||
|
||||
after(() => {
|
||||
cy.visit('/custompopulation')
|
||||
cy.url().should('include', '/custompopulation')
|
||||
cy.contains('Custom population')
|
||||
deleteAllSearches()
|
||||
})
|
||||
|
||||
describe('Custom population searching', () => {
|
||||
it('Finds a proper population', () => {
|
||||
cy.fixture('customPopulations').then(({ studentNumbersForCSStudentsSet1: students }) => {
|
||||
searchFor(students, '\n')
|
||||
hasLanded()
|
||||
containsAmountOfStudents(students.length)
|
||||
containsSpecificStudents(students)
|
||||
})
|
||||
})
|
||||
|
||||
it("Doesn't return non-existing students", () => {
|
||||
cy.fixture('customPopulations').then(({ studentNumbersForCSStudentsSet1: students }) => {
|
||||
searchFor([...students, ...nonExistentStudentNumbers], ' ')
|
||||
hasLanded()
|
||||
containsAmountOfStudents(students.length)
|
||||
containsSpecificStudents(students)
|
||||
checkRightsNotification(nonExistentStudentNumbers)
|
||||
})
|
||||
})
|
||||
|
||||
it("Doesn't find empty custom population", () => {
|
||||
searchFor(nonExistentStudentNumbers, ',')
|
||||
checkRightsNotification(nonExistentStudentNumbers)
|
||||
cy.contains('Credit accumulation').should('not.exist')
|
||||
cy.contains('Programme distribution').should('not.exist')
|
||||
cy.contains('Courses of population').should('not.exist')
|
||||
cy.get('button').contains('Back to search form')
|
||||
})
|
||||
|
||||
it("Doesn't return students user has no right to", () => {
|
||||
// These students exist in the database, but the user doesn't have the right to view them
|
||||
const studentsForEduBachStudents = ['014990067', '013069465', '014853890']
|
||||
// Two semicolons on purpose, the page should be able to handle it
|
||||
searchFor(studentsForEduBachStudents, ';;')
|
||||
checkRightsNotification(studentsForEduBachStudents)
|
||||
cy.contains('Credit accumulation').should('not.exist')
|
||||
cy.contains('Programme distribution').should('not.exist')
|
||||
cy.contains('Courses of population').should('not.exist')
|
||||
cy.get('button').contains('Back to search form')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Custom population search saving', () => {
|
||||
it('Saves a custom population search', { retries: 2 }, () => {
|
||||
cy.fixture('customPopulations').then(({ studentNumbersForCSStudentsSet1: students }) => {
|
||||
cy.contains(
|
||||
'Insert student numbers to use for the population. Each student number needs to be separated with a comma, a semicolon, a space, or a line break.'
|
||||
)
|
||||
const name = fillName()
|
||||
// A comma and a newline on purpose, the page should be able to handle it
|
||||
fillForm(students, ',\n')
|
||||
save()
|
||||
|
||||
// Round 1
|
||||
selectSavedPopulation(name)
|
||||
search()
|
||||
cy.contains(`Custom population: ${name}`)
|
||||
containsAmountOfStudents(students.length)
|
||||
containsSpecificStudents(students)
|
||||
|
||||
// Round 2
|
||||
cy.visit('/custompopulation')
|
||||
cy.contains('Custom population')
|
||||
selectSavedPopulation(name)
|
||||
search()
|
||||
cy.contains(`Custom population: ${name}`)
|
||||
containsAmountOfStudents(students.length)
|
||||
containsSpecificStudents(students)
|
||||
})
|
||||
})
|
||||
|
||||
it('Updates a custom population search', () => {
|
||||
cy.fixture('customPopulations').then(
|
||||
({ studentNumbersForCSStudentsSet1: students1, studentNumbersForCSStudentsSet2: students2 }) => {
|
||||
const name = fillName()
|
||||
fillForm(students1, ' ')
|
||||
save()
|
||||
|
||||
selectSavedPopulation(name)
|
||||
search()
|
||||
cy.contains(`Custom population: ${name}`)
|
||||
containsAmountOfStudents(students1.length)
|
||||
containsSpecificStudents(students1)
|
||||
cy.contains('Back to search form').click()
|
||||
selectSavedPopulation(name)
|
||||
fillForm(['\n', ...students2], ', ')
|
||||
save()
|
||||
|
||||
cy.visit('/custompopulation')
|
||||
cy.contains('Custom population')
|
||||
selectSavedPopulation(name)
|
||||
search()
|
||||
cy.contains(`Custom population: ${name}`)
|
||||
containsAmountOfStudents(students1.length + students2.length)
|
||||
containsSpecificStudents([...students1, ...students2])
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,922 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
const getEmptyYears = isAcademicYear => {
|
||||
const today = new Date()
|
||||
const latestYear = isAcademicYear && today.getMonth() < 7 ? today.getFullYear() - 1 : today.getFullYear()
|
||||
|
||||
const years = []
|
||||
for (let year = latestYear; year >= 2024; year--) {
|
||||
if (isAcademicYear) {
|
||||
years.push(`${year} - ${year + 1}`)
|
||||
} else {
|
||||
years.push(year)
|
||||
}
|
||||
}
|
||||
return years
|
||||
}
|
||||
|
||||
const tagName = `tag-${new Date().getTime()}`
|
||||
|
||||
const selectYear = year => {
|
||||
// ? Testing the MUI X DatePicker seems very difficult. It does not detect data-cy and the tests fail in CI/CD
|
||||
cy.contains('Associated start year (optional)').click({ force: true })
|
||||
cy.get('[placeholder=YYYY]').type(year)
|
||||
}
|
||||
|
||||
const deleteTag = tagName => {
|
||||
cy.cs(`delete-tag-${tagName}-button`).click()
|
||||
cy.contains('Delete tag')
|
||||
cy.contains('Are you sure you want to delete tag')
|
||||
cy.cs('confirm-delete-tag-button').click()
|
||||
}
|
||||
|
||||
describe('Degree programme overview', () => {
|
||||
describe('Degree programme selector', () => {
|
||||
it('Degree programme search filter', () => {
|
||||
cy.init('/study-programme', 'admin')
|
||||
cy.contains('Tietojenkäsittelytieteen kandiohjelma').should('exist')
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma').should('exist')
|
||||
cy.cs('study-programme-filter').type('Tietojenkäsittelytieteen')
|
||||
cy.contains('Tietojenkäsittelytieteen kandiohjelma').should('exist')
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Basic information tab works for basic user', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/study-programme')
|
||||
cy.contains('a', 'Matemaattisten tieteiden kandiohjelma').click({ force: true })
|
||||
cy.cs('year-toggle').click() // NOTE: Tests are written for calendar years
|
||||
})
|
||||
|
||||
// If the backend breaks for one of the sections, the section header is not rendered and this will fail
|
||||
it('Basic information tab loads', () => {
|
||||
cy.cs('students-of-the-study-programme-section')
|
||||
cy.cs('credits-produced-by-the-study-programme-section')
|
||||
cy.cs('graduated-and-thesis-writers-of-the-programme-section')
|
||||
cy.cs('programmes-before-or-after-section')
|
||||
cy.cs('average-graduation-times-section')
|
||||
})
|
||||
|
||||
it('Basic information contains correct students', () => {
|
||||
const years = getEmptyYears()
|
||||
const tableContents = [
|
||||
// [Year, Started studying, Accepted, Graduated, Cancelled, Transferred Away, Transferred to]
|
||||
...years.map(year => [year, 0, 0, 0, 0, 0]),
|
||||
[2023, 8, 8, 26, 2, 0, 0],
|
||||
[2022, 25, 26, 47, 0, 1, 3],
|
||||
[2021, 29, 32, 48, 1, 0, 2],
|
||||
[2020, 26, 27, 12, 0, 1, 3],
|
||||
[2019, 28, 34, 1, 0, 0, 1],
|
||||
[2018, 40, 45, 0, 0, 0, 1],
|
||||
[2017, 41, 47, 0, 0, 0, 0],
|
||||
]
|
||||
|
||||
cy.checkTableStats(tableContents, 'students-of-the-study-programme')
|
||||
})
|
||||
|
||||
it('Basic information contains correct credits', () => {
|
||||
const years = getEmptyYears()
|
||||
const tableContents = [
|
||||
...years.map(year => [year, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
|
||||
[2023, 1519, 1519, 0, 0, 0, 0, 0, 222, 0],
|
||||
[2022, 3235, 3205, 0, 0, 30, 0, 0, 209, 0],
|
||||
[2021, 5133, 5108, 0, 0, 25, 0, 0, 428, 25],
|
||||
[2020, 5801, 5796, 0, 0, 5, 0, 0, 94, 0],
|
||||
[2019, 5305, 5305, 0, 0, 0, 0, 0, 162, 0],
|
||||
[2018, 3442, 3432, 0, 0, 10, 0, 0, 21, 0],
|
||||
[2017, 1211, 1211, 0, 0, 0, 0, 0, 189, 0],
|
||||
]
|
||||
|
||||
cy.checkTableStats(tableContents, 'credits-produced-by-the-study-programme')
|
||||
})
|
||||
|
||||
it('Basic information contains correct thesis writers and graduates', () => {
|
||||
const years = getEmptyYears()
|
||||
const tableContents = [
|
||||
// [Year, Graduated, Wrote thesis]
|
||||
...years.map(year => [year, 0, 0]),
|
||||
[2023, 26, 5],
|
||||
[2022, 47, 13],
|
||||
[2021, 48, 76],
|
||||
[2020, 12, 23],
|
||||
[2019, 1, 19],
|
||||
[2018, 0, 0],
|
||||
[2017, 0, 1],
|
||||
]
|
||||
|
||||
cy.checkTableStats(tableContents, 'graduated-and-graduations-of-the-programme')
|
||||
})
|
||||
|
||||
it('Special study rights can be excluded and basic data changes accordingly', () => {
|
||||
cy.cs('study-right-toggle').click()
|
||||
const years = getEmptyYears()
|
||||
const studentTableContents = [
|
||||
// [Year, Started studying, Accepted, Graduated]
|
||||
...years.map(year => [year, 0, 0, 0]),
|
||||
[2023, 8, 8, 24],
|
||||
[2022, 25, 26, 43],
|
||||
[2021, 29, 32, 47],
|
||||
[2020, 26, 27, 11],
|
||||
[2019, 28, 34, 1],
|
||||
[2018, 40, 45, 0],
|
||||
[2017, 41, 47, 0],
|
||||
]
|
||||
|
||||
cy.checkTableStats(studentTableContents, 'students-of-the-study-programme')
|
||||
|
||||
const graduatedTableContents = [
|
||||
// [Year, Graduated, Wrote thesis]
|
||||
...years.map(year => [year, 0, 0]),
|
||||
[2023, 24, 5],
|
||||
[2022, 43, 12],
|
||||
[2021, 47, 69],
|
||||
[2020, 11, 22],
|
||||
[2019, 1, 18],
|
||||
[2018, 0, 0],
|
||||
[2017, 0, 1],
|
||||
]
|
||||
|
||||
cy.checkTableStats(graduatedTableContents, 'graduated-and-graduations-of-the-programme')
|
||||
})
|
||||
|
||||
it('Year can be changed to academic year, and data changes accordingly', () => {
|
||||
cy.cs('year-toggle').click()
|
||||
const isAcademicYear = true
|
||||
const years = getEmptyYears(isAcademicYear)
|
||||
const studentTableContents = [
|
||||
// [Year, Started studying, Accepted, Graduated, Cancelled, Transferred away, Transferred to]
|
||||
...years.map(year => [year, 0, 0, 0, 0, 0]),
|
||||
['2023 - 2024', 8, 8, 4, 1, 0, 0],
|
||||
['2022 - 2023', 25, 26, 35, 1, 0, 0],
|
||||
['2021 - 2022', 29, 32, 58, 1, 1, 5],
|
||||
['2020 - 2021', 26, 27, 30, 0, 0, 3],
|
||||
['2019 - 2020', 28, 34, 7, 0, 1, 1],
|
||||
['2018 - 2019', 40, 45, 0, 0, 0, 1],
|
||||
['2017 - 2018', 41, 47, 0, 0, 0, 0],
|
||||
]
|
||||
cy.checkTableStats(studentTableContents, 'students-of-the-study-programme')
|
||||
|
||||
const creditTableContents = [
|
||||
...years.map(year => [year, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
|
||||
['2023 - 2024', 160, 160, 0, 0, 0, 0, 0, 67, 0],
|
||||
['2022 - 2023', 2725, 2720, 0, 0, 5, 0, 0, 337, 0],
|
||||
['2021 - 2022', 4092, 4042, 0, 0, 50, 0, 0, 198, 0],
|
||||
['2020 - 2021', 5420, 5415, 0, 0, 5, 0, 0, 321, 25],
|
||||
['2019 - 2020', 6043, 6043, 0, 0, 0, 0, 0, 101, 0],
|
||||
['2018 - 2019', 4856, 4851, 0, 0, 5, 0, 0, 107, 0],
|
||||
['2017 - 2018', 2350, 2345, 0, 0, 5, 0, 0, 26, 0],
|
||||
]
|
||||
|
||||
cy.checkTableStats(creditTableContents, 'credits-produced-by-the-study-programme')
|
||||
cy.cs('year-toggle').click()
|
||||
})
|
||||
|
||||
it('Basic information graphs render', () => {
|
||||
cy.cs('students-of-the-study-programme-line-graph-section')
|
||||
.should('contain', 'Started studying')
|
||||
.should('contain', 'Accepted')
|
||||
.should('contain', 'Graduated')
|
||||
.should('contain', 'Transferred away')
|
||||
.should('contain', 'Transferred to')
|
||||
|
||||
cy.cs('credits-produced-by-the-study-programme-stacked-bar-chart-section')
|
||||
.should('contain', 'Degree students')
|
||||
.should('contain', 'Transferred')
|
||||
.should('contain', 5796)
|
||||
.should('contain', 428)
|
||||
|
||||
cy.cs('graduated-and-thesis-writers-of-the-programme-bar-chart-section')
|
||||
.should('contain', 'Graduated students')
|
||||
.should('contain', 'Wrote thesis')
|
||||
.should('contain', 47)
|
||||
.should('contain', 76)
|
||||
|
||||
cy.cs('graduation-mode-selector').within(() => {
|
||||
cy.cs('select-median').click()
|
||||
})
|
||||
cy.cs('unset-median-bar-chart').within(() => {
|
||||
cy.contains('47 graduated').should('be.visible')
|
||||
cy.contains('47 graduated').hover()
|
||||
})
|
||||
|
||||
cy.get('.grad-vals').contains('47 students graduated in year 2022').should('be.visible')
|
||||
|
||||
cy.contains('median study time: 6 semesters')
|
||||
cy.contains('24 graduated on time')
|
||||
cy.contains('12 graduated max year overtime')
|
||||
cy.contains('11 graduated over year late')
|
||||
|
||||
cy.cs('programmes-before-or-after-stacked-bar-chart-section')
|
||||
.should('contain', 'Tietojenkäsittelytieteen maisteriohjelma')
|
||||
.should('contain', 'Datatieteen maisteriohjelma')
|
||||
.should('contain', 'Matematiikan ja tilastotieteen maisteriohjelma')
|
||||
.should('contain', 32)
|
||||
.should('contain', 21)
|
||||
.should('contain', 17)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Graduation times of master programmes', () => {
|
||||
it('are split into three graphs', () => {
|
||||
cy.init('/study-programme')
|
||||
cy.contains('a', 'Matematiikan ja tilastotieteen maisteriohjelma').click({ force: true })
|
||||
cy.cs('year-toggle').click() // Tests are written for calendar year
|
||||
|
||||
cy.cs('unset-breakdown-bar-chart')
|
||||
|
||||
cy.cs('graduation-mode-selector').within(() => {
|
||||
cy.cs('select-average').click()
|
||||
})
|
||||
cy.cs('unset-graduation-times-section')
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.contains('Master study right')
|
||||
cy.contains('2 graduated').should('be.visible')
|
||||
cy.contains('2 graduated').hover()
|
||||
})
|
||||
|
||||
cy.get('.grad-vals').contains('2 students graduated in year 2021').should('be.visible')
|
||||
cy.contains('average study time: 4.5 semesters')
|
||||
cy.contains('1 graduated on time')
|
||||
cy.contains('1 graduated max year overtime')
|
||||
cy.contains('0 graduated over year late')
|
||||
|
||||
cy.cs('unset-graduation-times-section')
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.contains('Bachelor + master study right')
|
||||
cy.contains('11 graduated').should('be.visible')
|
||||
cy.contains('11 graduated').hover()
|
||||
})
|
||||
|
||||
cy.get('.grad-vals').contains('11 students graduated in year 2023').should('be.visible')
|
||||
cy.contains('average study time: 11.18 semesters')
|
||||
cy.contains('4 graduated on time')
|
||||
cy.contains('6 graduated max year overtime')
|
||||
cy.contains('1 graduated over year late')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Study tracks and class statistics tab works for basic user', () => {
|
||||
beforeEach(() => {
|
||||
cy.intercept(
|
||||
'GET',
|
||||
'api/studyprogrammes/KH50_001/studytrackstats?special_groups=SPECIAL_INCLUDED&combined_programme='
|
||||
).as('stQuery')
|
||||
cy.init('/study-programme')
|
||||
cy.contains('a', 'Matemaattisten tieteiden kandiohjelma').click()
|
||||
cy.cs('StudyTracksAndClassStatisticsTab').click()
|
||||
})
|
||||
|
||||
describe('Info boxes', () => {
|
||||
it('Study track overview section', () => {
|
||||
cy.cs('study-track-overview-info-box-button').click()
|
||||
cy.cs('study-track-overview-info-box-content').contains('Opiskelijat, joiden')
|
||||
})
|
||||
|
||||
it('Progress of students section', () => {
|
||||
cy.cs('progress-of-students-info-box-button').click()
|
||||
cy.cs('progress-of-students-info-box-content').contains('Kuvaa koulutusohjelmassa')
|
||||
})
|
||||
|
||||
// HACK: Do this properly
|
||||
it('Average graduation times section', () => {
|
||||
cy.wait(500)
|
||||
cy.cs('average-graduation-times-info-box-button').click()
|
||||
cy.cs('average-graduation-times-info-box-content').contains('Yksittäinen palkki')
|
||||
})
|
||||
})
|
||||
|
||||
it('All sections are visible', () => {
|
||||
cy.cs('study-track-selector-section')
|
||||
cy.cs('study-track-overview-section')
|
||||
cy.cs('progress-of-students-section')
|
||||
cy.cs('average-graduation-times-section')
|
||||
})
|
||||
|
||||
it('Students of the degree programme are shown correctly', () => {
|
||||
const tableContents = [
|
||||
// [Year, All, Started studying, Present, Absent, Passive, Graduated, Has recent attainments, Men, Women, Other/Unknown, Finland, Other]
|
||||
['2023 - 2024', 8, 8, 0, 0, 8, 0, 0, 5, 3, 0, 8, 1],
|
||||
['2022 - 2023', 26, 25, 0, 0, 24, 2, 0, 19, 7, 0, 25, 1],
|
||||
['2021 - 2022', 37, 29, 0, 0, 33, 4, 0, 29, 8, 0, 35, 4],
|
||||
['2020 - 2021', 30, 26, 0, 0, 11, 19, 0, 15, 15, 0, 29, 3],
|
||||
['2019 - 2020', 35, 28, 0, 0, 8, 27, 0, 22, 13, 0, 35, 2],
|
||||
['2018 - 2019', 46, 40, 0, 0, 6, 40, 0, 26, 20, 0, 45, 1],
|
||||
['2017 - 2018', 47, 41, 0, 0, 5, 42, 0, 31, 16, 0, 47, 0],
|
||||
['Total', 229, 197, 0, 0, 95, 134, 0, 147, 82, 0, 224, 12],
|
||||
]
|
||||
|
||||
cy.checkTableStats(tableContents, 'study-tracks-and-class-statistics')
|
||||
})
|
||||
|
||||
it.skip('Years in the students table can be expanded and study track data will be shown', () => {
|
||||
// TODO: Fix this test
|
||||
cy.cs('study-tracks-and-class-statistics-data-table').within(() => {
|
||||
cy.get('tbody tr.header-row')
|
||||
.eq(3)
|
||||
.within(() => {
|
||||
cy.get('td i.angle.right.icon').click()
|
||||
})
|
||||
|
||||
const dataForStudyTracks = [
|
||||
['Ekonometria, MAT-EKO', 2, 2, 0, 0, 0, 2, 1, 1, 0, 2, 0],
|
||||
['Matematiikka, MAT-MAT', 13, 10, 0, 0, 1, 12, 7, 6, 0, 12, 3],
|
||||
['Tietojenkäsittelyteoria, MAT-TIE', 2, 1, 0, 0, 1, 1, 2, 0, 0, 2, 0],
|
||||
['Tilastotiede, MAT-TIL', 4, 4, 0, 0, 0, 4, 1, 3, 0, 4, 0],
|
||||
]
|
||||
|
||||
dataForStudyTracks.forEach((data, index) => {
|
||||
cy.get('tbody tr.regular-row')
|
||||
.eq(index)
|
||||
.within(() => {
|
||||
cy.get('td').each((cell, i) => {
|
||||
cy.wrap(cell).contains(data[i])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('tbody tr.header-row')
|
||||
.eq(3)
|
||||
.within(() => {
|
||||
cy.get('td i.angle.down.icon').click()
|
||||
})
|
||||
|
||||
cy.get('tbody tr.regular-row').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Population link button works for', () => {
|
||||
it('a single year', () => {
|
||||
cy.cs('2023-population-link-button').first().click()
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma')
|
||||
cy.contains('Class of 2023 - 2024, 8 students')
|
||||
})
|
||||
|
||||
it('total', () => {
|
||||
cy.cs('total-population-link-button').click()
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma')
|
||||
cy.contains('Class of 2017 - 2026, 227 students')
|
||||
})
|
||||
|
||||
it('Links to class statistics page with study track info included work', () => {
|
||||
cy.cs('show-study-tracks-button').first().click()
|
||||
cy.contains('td', 'Matematiikka (MAT-MAT)').within(() => {
|
||||
cy.get('a').click()
|
||||
})
|
||||
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma')
|
||||
cy.contains('Studytrack MAT-MAT')
|
||||
cy.contains('Class of 2022 - 2023, 26 students')
|
||||
cy.contains('Showing 3 out of 26 students')
|
||||
})
|
||||
})
|
||||
|
||||
it('Student progress data is shown correctly', () => {
|
||||
const years = getEmptyYears(true)
|
||||
const tableContents = [
|
||||
// [Year, All, < 30 credits, 30–60 credits, 60–90 credits, 90–120 credits, 120–150 credits, 150–180 credits, ≥ 180 credits, Graduated]
|
||||
...years.map(year => [year, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
|
||||
['2023 - 2024', 8, 8, 0, 0, 0, 0, 0, 0, 0],
|
||||
['2022 - 2023', 26, 9, 8, 4, 3, 0, 0, 0, 2],
|
||||
['2021 - 2022', 37, 8, 4, 9, 8, 4, 0, 0, 4],
|
||||
['2020 - 2021', 30, 2, 1, 2, 5, 0, 0, 1, 19],
|
||||
['2019 - 2020', 35, 1, 0, 2, 1, 0, 0, 4, 27],
|
||||
['2018 - 2019', 46, 0, 1, 1, 2, 0, 0, 2, 40],
|
||||
['2017 - 2018', 47, 0, 1, 3, 0, 0, 1, 0, 42],
|
||||
['Total', 229, 28, 15, 21, 19, 4, 1, 7, 134],
|
||||
]
|
||||
|
||||
cy.checkTableStats(tableContents, 'study-programme-progress')
|
||||
})
|
||||
|
||||
it('Progress section', () => {
|
||||
cy.cs('programme-progress-bar-chart-section').scrollIntoView()
|
||||
|
||||
cy.cs('programme-progress-bar-chart-section')
|
||||
.should('contain', 'Less than 30 credits')
|
||||
.should('contain', '30–60 credits')
|
||||
.should('contain', 'At least 180 credits')
|
||||
.should('contain', '58.5%') // The percentage for total graduated, to check that the graph renders
|
||||
|
||||
cy.cs('programme-progress-bar-chart-section').contains('58.5%').hover()
|
||||
cy.contains('Graduated: 134')
|
||||
})
|
||||
|
||||
// CI contains different data than locally
|
||||
it.skip('Average graduation times section', () => {
|
||||
cy.cs('average-graduation-times-section').scrollIntoView()
|
||||
|
||||
cy.cs('average-graduation-times-section').within(() => {
|
||||
cy.cs('unset-graduation-times-section').within(() => {
|
||||
cy.contains('2020 - 2021')
|
||||
})
|
||||
|
||||
cy.get('text').contains('16').hover()
|
||||
cy.contains('On time: 16')
|
||||
|
||||
cy.cs('unset-graduation-times-section').within(() => {
|
||||
cy.contains("Click a bar to view that year's study track level breakdown")
|
||||
cy.get('text').contains('22').click()
|
||||
})
|
||||
|
||||
cy.contains('Year 2019 - 2020 by start year')
|
||||
|
||||
cy.get('text').contains('13').hover()
|
||||
cy.contains('Matematiikka')
|
||||
cy.contains('MAT-MAT')
|
||||
cy.contains('On time: 13')
|
||||
})
|
||||
|
||||
cy.cs('graduation-time-toggle').click()
|
||||
|
||||
cy.cs('average-graduation-times-section').within(() => {
|
||||
cy.contains('2020 - 2021')
|
||||
cy.contains('19 graduated').hover()
|
||||
cy.contains('From class of 2020 - 2021, 19/30 students have graduated')
|
||||
cy.contains('median study time: 6 semesters')
|
||||
cy.contains('16 graduated on time')
|
||||
cy.contains('2 graduated max year overtime')
|
||||
cy.contains('1 graduated over year late')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Study track can be changed', () => {
|
||||
beforeEach(() => {
|
||||
cy.wait('@stQuery')
|
||||
cy.contains('All students of the programme')
|
||||
cy.cs('study-track-select').click()
|
||||
cy.contains('Ekonometria')
|
||||
cy.contains('Tietojenkäsittelyteoria')
|
||||
cy.contains('Tilastotiede')
|
||||
cy.contains('Matematiikka').click()
|
||||
})
|
||||
|
||||
it('Students of the study track are shown correctly', () => {
|
||||
cy.cs('study-track-overview-section').contains('Students of the study track MAT-MAT by starting year')
|
||||
const tableContents = [
|
||||
// [Year, All, Started studying, Present, Absent, Passive, Graduated, Has recent attainment, Men, Women, Other/Unknown, Finland, Other]
|
||||
['2022 - 2023', 3, 3, 0, 0, 1, 2, 0, 2, 1, 0, 3, 0],
|
||||
['2021 - 2022', 4, 1, 0, 0, 1, 3, 0, 3, 1, 0, 4, 0],
|
||||
['2020 - 2021', 13, 10, 0, 0, 1, 12, 0, 7, 6, 0, 12, 3],
|
||||
['2019 - 2020', 17, 14, 0, 0, 0, 17, 0, 10, 7, 0, 17, 1],
|
||||
['2018 - 2019', 24, 21, 0, 0, 2, 22, 0, 11, 13, 0, 24, 0],
|
||||
['2017 - 2018', 28, 24, 0, 0, 1, 27, 0, 15, 13, 0, 28, 0],
|
||||
['Total', 89, 73, 0, 0, 6, 83, 0, 48, 41, 0, 88, 4],
|
||||
]
|
||||
cy.checkTableStats(tableContents, 'study-tracks-and-class-statistics')
|
||||
})
|
||||
|
||||
it('Links to class statistics page with study track info included work', () => {
|
||||
cy.cs('2020-population-link-button').first().click()
|
||||
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma')
|
||||
cy.contains('Studytrack MAT-MAT')
|
||||
cy.contains('Class of 2020 - 2021, 30 students')
|
||||
cy.contains('Showing 10 out of 30 students')
|
||||
})
|
||||
|
||||
// FIXME: This feature was implemented. The data is no-good, so maybe reimplement this when it's clean.
|
||||
it.skip('Info message about missing progress stats is displayed', () => {
|
||||
cy.contains('Progress of students of the study track MAT-MAT by starting year')
|
||||
cy.contains('Progress data is currently only available for all students of the degree programme.')
|
||||
})
|
||||
|
||||
it.skip('Average graduation times are displayed correctly', () => {
|
||||
cy.get("[data-cy='Section-averageGraduationTimesStudyTracks']")
|
||||
cy.get("[data-cy='graduation-times-graph-breakdownBachelor']").within(() => {
|
||||
cy.contains('Start year')
|
||||
cy.contains('2020 - 2021')
|
||||
cy.get('[aria-label="2020 - 2021, 9. On time."]').hover()
|
||||
cy.contains('Graduated On time: 9 students')
|
||||
})
|
||||
|
||||
cy.cs('graduation-time-toggle').click()
|
||||
cy.cs('bachelor-median-time-bar-chart').within(() => {
|
||||
cy.contains('Start year')
|
||||
cy.contains('2020 - 2021')
|
||||
cy.contains('12 graduated').hover()
|
||||
cy.contains('From class of 2020 - 2021, 12/13 students have graduated')
|
||||
cy.contains('median study time: 34 months')
|
||||
cy.contains('9 graduated on time')
|
||||
cy.contains('2 graduated max year overtime')
|
||||
cy.contains('1 graduated over year late')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Programme courses tab works for basic user', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/study-programme')
|
||||
cy.contains('a', 'Matemaattisten tieteiden kandiohjelma').click()
|
||||
cy.cs('ProgrammeCoursesTab').click()
|
||||
|
||||
cy.cs('by-credit-type-section')
|
||||
cy.cs('by-credit-type-tab')
|
||||
cy.cs('by-semester-tab')
|
||||
})
|
||||
|
||||
describe('By credit type tab', () => {
|
||||
beforeEach(() => {
|
||||
cy.cs('show-credits-students-toggle').click()
|
||||
cy.cs('year-toggle').click()
|
||||
cy.get('thead').within(() => {
|
||||
cy.get('tr')
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.get('th').eq(3).click()
|
||||
})
|
||||
})
|
||||
cy.get('tbody').within(() => {
|
||||
cy.get('tr')
|
||||
.eq(8)
|
||||
.within(() => {
|
||||
cy.get('td').eq(0).contains('Course')
|
||||
cy.get('td').eq(1).contains('MAT11004')
|
||||
cy.get('td').eq(2).contains('Differentiaalilaskenta')
|
||||
cy.get('td').eq(3).contains('1240')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('time range selection works', () => {
|
||||
cy.cs('from-year-select').click()
|
||||
cy.cs('from-year-select-option-2021').click()
|
||||
cy.cs('to-year-select').click()
|
||||
cy.cs('to-year-select-option-2022').click()
|
||||
|
||||
cy.get('tbody').within(() => {
|
||||
cy.get('tr')
|
||||
.eq(9)
|
||||
.within(() => {
|
||||
cy.get('td').eq(0).contains('Course')
|
||||
cy.get('td').eq(1).contains('MAT21009')
|
||||
cy.get('td').eq(2).contains('Kandidaatintutkielma')
|
||||
cy.get('td').eq(3).contains('414')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('year toggle works', () => {
|
||||
cy.cs('year-toggle').click() // Default view now Academic years
|
||||
|
||||
cy.cs('from-year-select').click()
|
||||
cy.cs('from-year-select-option-2017').click()
|
||||
cy.cs('to-year-select').click()
|
||||
cy.cs('to-year-select-option-2023').click()
|
||||
|
||||
cy.get('tbody').within(() => {
|
||||
cy.get('tr')
|
||||
.eq(5)
|
||||
.within(() => {
|
||||
cy.get('td').eq(0).contains('Course')
|
||||
cy.get('td').eq(1).contains('MAT11001')
|
||||
cy.get('td').eq(2).contains('Johdatus yliopistomatematiikkaan')
|
||||
cy.get('td').eq(3).contains('1265')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// TODO: Fix sorting / filters
|
||||
it.skip('different sorting options work', () => {
|
||||
cy.cs('CoursesSortableTable').within(() => {
|
||||
// Course code
|
||||
cy.get('th').eq(0).click()
|
||||
cy.get('tr')
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.get('td').eq(0).contains('odgi-zef0')
|
||||
cy.get('td').eq(1).contains('Työ- ja organisaatiopsykologian perusopinnot')
|
||||
})
|
||||
cy.get('th').eq(0).click()
|
||||
cy.get('tr')
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.get('td').eq(0).contains('MAT-yht')
|
||||
cy.get('td').eq(1).contains('Muut opinnot')
|
||||
})
|
||||
|
||||
// Course name
|
||||
cy.get('th').eq(1).click()
|
||||
cy.get('tr')
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.get('td').eq(0).contains('MAT20003')
|
||||
cy.get('td').eq(1).contains('Äidinkielen opinnot')
|
||||
})
|
||||
cy.get('th').eq(1).click()
|
||||
cy.get('tr')
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.get('td').eq(0).contains('MAT11008')
|
||||
cy.get('td').eq(1).contains('Advanced calculus')
|
||||
})
|
||||
|
||||
// Total credits
|
||||
cy.get('th').eq(2).click()
|
||||
cy.get('tr')
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.get('td').eq(0).contains('MAT110')
|
||||
cy.get('td').eq(1).contains('Matematiikka, perusopinnot')
|
||||
})
|
||||
cy.get('th').eq(2).click()
|
||||
cy.get('tr')
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.get('td').eq(0).contains('MAT20001')
|
||||
cy.get('td').eq(1).contains('Kypsyysnäyte')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("'Show credits/Show students' toggle works", () => {
|
||||
cy.cs('year-toggle').click()
|
||||
cy.wait(500) // So that the toggle has time to load
|
||||
cy.get('thead tr')
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.get('th').should('have.length', 6)
|
||||
const headers = ['Type', 'Code', 'Name', 'Total credits', 'Credits produced by', 'Transferred credits']
|
||||
headers.forEach((header, index) => {
|
||||
cy.get('th').eq(index).contains(header)
|
||||
})
|
||||
})
|
||||
cy.get('thead tr')
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.get('th').should('have.length', 7)
|
||||
const headers = [
|
||||
'Degree students',
|
||||
'Open university (hetu)',
|
||||
'Open university (no hetu)',
|
||||
'Exchange students',
|
||||
'Other universities',
|
||||
'Separate studies',
|
||||
'Other',
|
||||
]
|
||||
headers.forEach((header, index) => {
|
||||
cy.get('th').eq(index).contains(header)
|
||||
})
|
||||
})
|
||||
|
||||
cy.cs('show-credits-students-toggle').click()
|
||||
|
||||
cy.get('thead tr')
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.get('th').should('have.length', 7)
|
||||
const headers = [
|
||||
'Type',
|
||||
'Code',
|
||||
'Name',
|
||||
'Total students',
|
||||
'Breakdown of total',
|
||||
'Breakdown of passed',
|
||||
'Not included in total or passed',
|
||||
]
|
||||
headers.forEach((header, index) => {
|
||||
cy.get('th').eq(index).contains(header)
|
||||
})
|
||||
})
|
||||
cy.get('thead tr')
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.get('th').should('have.length', 10)
|
||||
const headers = [
|
||||
'Passed',
|
||||
'Not completed',
|
||||
'Degree students',
|
||||
'Open university students (with hetu)',
|
||||
'Open university students (without hetu)',
|
||||
'Exchange students',
|
||||
'Other university students',
|
||||
'Separate studies',
|
||||
'Other students',
|
||||
'Students with transferred credits',
|
||||
]
|
||||
headers.forEach((header, index) => {
|
||||
cy.get('th').eq(index).contains(header)
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('tbody').within(() => {
|
||||
cy.get('tr')
|
||||
.eq(5)
|
||||
.within(() => {
|
||||
cy.get('td').eq(0).contains('Course')
|
||||
cy.get('td').eq(1).contains('MAT11001')
|
||||
cy.get('td').eq(2).contains('Johdatus yliopistomatematiikkaan')
|
||||
cy.get('td').eq(3).contains('272')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('By semester tab', () => {
|
||||
beforeEach(() => {
|
||||
cy.cs('by-semester-tab').click()
|
||||
})
|
||||
|
||||
// FIXME: Flaky
|
||||
it.skip('test', () => {
|
||||
// TODO: Implement some real tests for this tab
|
||||
cy.contains('From')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Degree courses tab works for basic user', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/study-programme')
|
||||
cy.contains('a', 'Matemaattisten tieteiden kandiohjelma').click()
|
||||
cy.cs('DegreeCoursesTab').click()
|
||||
})
|
||||
|
||||
it('Curriculum section', () => {
|
||||
cy.cs('curriculum-section')
|
||||
cy.contains('Select curriculum to edit:')
|
||||
cy.cs('curriculum-picker').contains('2023–2026')
|
||||
// TODO: Test changing the curriculum
|
||||
})
|
||||
|
||||
describe('Credit criteria section', () => {
|
||||
it('info box', () => {
|
||||
cy.cs('credit-criteria-section')
|
||||
cy.cs('credit-criteria-info-box-button').click()
|
||||
cy.cs('credit-criteria-info-box-content').contains('Here you can change')
|
||||
})
|
||||
|
||||
it.skip('changing the credit criteria works', () => {
|
||||
// TODO: Test using the inputs
|
||||
// TODO: Button status
|
||||
// TODO: Test "previously set to _" text changing when saving
|
||||
})
|
||||
})
|
||||
|
||||
it('Degree course table', () => {
|
||||
cy.cs('degree-course-table')
|
||||
// TODO: Test clicking the arrow buttons
|
||||
// TODO: Test toggling visibility for MODULES and COURSES
|
||||
// TODO: Test changing criterion labels
|
||||
})
|
||||
})
|
||||
|
||||
describe('Tags tab works for basic user', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/study-programme')
|
||||
cy.contains('a', 'Matemaattisten tieteiden kandiohjelma').click({ force: true })
|
||||
cy.cs('TagsTab').click()
|
||||
})
|
||||
|
||||
it('info box', () => {
|
||||
cy.cs('create-new-tag-info-box-button').click()
|
||||
cy.cs('create-new-tag-info-box-content').contains('Here you can create')
|
||||
})
|
||||
|
||||
describe('Adding tags to populations and removing them works', () => {
|
||||
beforeEach(() => {
|
||||
cy.contains('This degree programme does not have any tags yet')
|
||||
cy.cs('tag-name-text-field').type(tagName)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
deleteTag(tagName)
|
||||
cy.contains('This degree programme does not have any tags yet')
|
||||
})
|
||||
|
||||
it('can create and delete tags without start year', () => {
|
||||
cy.cs('create-button').click()
|
||||
cy.contains(tagName)
|
||||
cy.contains('No associated start year')
|
||||
})
|
||||
|
||||
it.skip('can create and delete tags with start year', () => {
|
||||
// TODO: This test fails in the pipeline, but works locally. Investigate.
|
||||
selectYear('2022')
|
||||
cy.cs('create-button').click()
|
||||
cy.contains(tagName)
|
||||
cy.contains('Associated start year 2022')
|
||||
})
|
||||
|
||||
it.skip('population link works', () => {
|
||||
// TODO: This test fails in the pipeline, but works locally. Investigate.
|
||||
selectYear('2022')
|
||||
cy.cs('create-button').click()
|
||||
cy.contains(tagName)
|
||||
cy.cs('population-link-button').click()
|
||||
cy.contains(`Tagged with: ${tagName}`)
|
||||
cy.go('back')
|
||||
})
|
||||
|
||||
it('can create personal tags', () => {
|
||||
cy.cs('personal-tag-toggle').click()
|
||||
cy.cs('create-button').click()
|
||||
cy.contains(tagName)
|
||||
cy.cs(`${tagName}-visibility-icon`)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Adding tags to students and removing them works', () => {
|
||||
const studentInput = '477806,478275; 478953 479239\n 480080'
|
||||
const studentNumbers = studentInput.match(/[^\s,;]+/g)
|
||||
|
||||
it.skip('can add tags to students', () => {
|
||||
// TODO: This test fails in the pipeline, but works locally. Investigate.
|
||||
cy.cs('tag-name-text-field').type(tagName)
|
||||
selectYear('2022')
|
||||
cy.cs('create-button').click()
|
||||
cy.contains(tagName)
|
||||
|
||||
cy.cs('add-students-button').click()
|
||||
cy.cs('add-students-text-field').type(studentInput)
|
||||
cy.cs('add-students-confirm-button').click()
|
||||
cy.contains('Students added to tag')
|
||||
|
||||
cy.cs('population-link-button').click()
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma')
|
||||
cy.contains('Class of 2022 - 2023')
|
||||
cy.contains(`Tagged with: ${tagName}`)
|
||||
cy.contains('Students (5)')
|
||||
.parent()
|
||||
.then($parentDiv => {
|
||||
if (!$parentDiv.hasClass('active')) cy.contains('Students (5)').click()
|
||||
})
|
||||
|
||||
for (const studentNumber of studentNumbers) {
|
||||
cy.contains(studentNumber)
|
||||
}
|
||||
|
||||
for (const studentNumber of studentNumbers) {
|
||||
cy.visit(`/students/${studentNumber}`)
|
||||
cy.contains('Tags')
|
||||
cy.contains(tagName)
|
||||
}
|
||||
|
||||
cy.get('a').contains('Matemaattisten tieteiden kandiohjelma').invoke('removeAttr', 'target').click()
|
||||
cy.url().should('include', '/study-programme/KH50_001?tab=4')
|
||||
|
||||
deleteTag(tagName)
|
||||
})
|
||||
|
||||
it('deleting a tag from tag view also removes it from students', () => {
|
||||
cy.contains(tagName).should('not.exist')
|
||||
for (const studentNumber of studentNumbers) {
|
||||
cy.visit(`/students/${studentNumber}`)
|
||||
cy.contains('Tags').should('not.exist')
|
||||
cy.contains(tagName).should('not.exist')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('IAM user', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/study-programme', 'onlyiamrights')
|
||||
cy.contains('a', 'Matemaattisten tieteiden kandiohjelma').click()
|
||||
})
|
||||
|
||||
it.skip('year selector', () => {
|
||||
// TODO: Implement this test
|
||||
// Things to test:
|
||||
// - Clicking the button works
|
||||
// - Selecting a study track works
|
||||
// - The button is disabled if only one year is selected
|
||||
// - The slider is not visible if the user does not have correct programme rights
|
||||
})
|
||||
|
||||
it('can access programme and correct tabs are visible', () => {
|
||||
cy.contains('Basic information')
|
||||
cy.contains('Study tracks and class statistics')
|
||||
|
||||
cy.contains('Update statistics').should('not.exist')
|
||||
cy.contains('Degree courses').should('not.exist')
|
||||
})
|
||||
|
||||
it('can access basic information', () => {
|
||||
cy.cs('BasicInformationTab').click()
|
||||
|
||||
cy.cs('students-of-the-study-programme-section')
|
||||
cy.cs('credits-produced-by-the-study-programme-section')
|
||||
cy.cs('graduated-and-thesis-writers-of-the-programme-section')
|
||||
cy.cs('average-graduation-times-section')
|
||||
cy.cs('programmes-before-or-after-section')
|
||||
})
|
||||
|
||||
it('can access study tracks', () => {
|
||||
cy.cs('StudyTracksAndClassStatisticsTab').click()
|
||||
|
||||
cy.cs('study-track-overview-section')
|
||||
cy.cs('progress-of-students-section')
|
||||
cy.cs('average-graduation-times-section')
|
||||
})
|
||||
|
||||
it("doesn't see other tabs", () => {
|
||||
cy.cs('DegreeCoursesTab').should('not.exist')
|
||||
cy.cs('TagsTab').should('not.exist')
|
||||
cy.cs('UpdateStatisticsTab').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,287 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
const path = require('path')
|
||||
|
||||
const timestamp = new Date().toLocaleDateString('en-CA', { year: 'numeric', month: '2-digit', day: '2-digit' }) // YYYY-MM-DD, taking the local time zone into account
|
||||
const downloadsFolder = Cypress.config('downloadsFolder')
|
||||
|
||||
describe('Faculty statistics', () => {
|
||||
describe('Faculty list', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/faculties')
|
||||
})
|
||||
|
||||
it('contains faculty names and faculty codes', () => {
|
||||
cy.contains('Faculties')
|
||||
cy.contains('Teologinen tiedekunta')
|
||||
cy.contains('H10')
|
||||
cy.contains('Oikeustieteellinen tiedekunta')
|
||||
cy.contains('H20')
|
||||
cy.contains('Lääketieteellinen tiedekunta')
|
||||
cy.contains('H30')
|
||||
cy.contains('Humanistinen tiedekunta')
|
||||
cy.contains('H40')
|
||||
cy.contains('Matemaattis-luonnontieteellinen tiedekunta')
|
||||
cy.contains('H50')
|
||||
cy.contains('Farmasian tiedekunta')
|
||||
cy.contains('H55')
|
||||
cy.contains('Bio- ja ympäristötieteellinen tiedekunta')
|
||||
cy.contains('H57')
|
||||
cy.contains('Kasvatustieteellinen tiedekunta')
|
||||
cy.contains('H60')
|
||||
cy.contains('Valtiotieteellinen tiedekunta')
|
||||
cy.contains('H70')
|
||||
cy.contains('Svenska social- och kommunalhögskolan')
|
||||
cy.contains('H74')
|
||||
cy.contains('Maatalous-metsätieteellinen tiedekunta')
|
||||
cy.contains('H80')
|
||||
cy.contains('Eläinlääketieteellinen tiedekunta')
|
||||
cy.contains('H90')
|
||||
})
|
||||
|
||||
it('contains a working link to faculty page', () => {
|
||||
cy.contains('Faculties')
|
||||
cy.contains('a', 'Teologinen tiedekunta').click()
|
||||
cy.location('pathname').should('eq', '/faculties/hy-org-1000000580')
|
||||
cy.contains('Teologinen tiedekunta')
|
||||
cy.contains('H10')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Basic information tab', () => {
|
||||
describe('Admin user', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/faculties', 'admin')
|
||||
cy.contains('a', 'Eläinlääketieteellinen tiedekunta').click()
|
||||
})
|
||||
|
||||
it('Correct tabs are shown', () => {
|
||||
cy.cs('faculty-tabs').should('contain', 'Basic information')
|
||||
cy.cs('faculty-tabs').should('contain', 'Students by starting year')
|
||||
cy.cs('faculty-tabs').should('contain', 'Graduation times')
|
||||
cy.cs('faculty-tabs').should('contain', 'Update statistics')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Basic user', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/faculties')
|
||||
cy.contains('a', 'Matemaattis-luonnontieteellinen tiedekunta').click()
|
||||
})
|
||||
|
||||
describe('Info boxes', () => {
|
||||
it('Students of the faculty', () => {
|
||||
cy.cs('students-of-the-faculty-info-box-button').click()
|
||||
cy.cs('students-of-the-faculty-info-box-content').contains('Taulukon luvut on')
|
||||
})
|
||||
|
||||
it('Graduated of the faculty', () => {
|
||||
cy.cs('graduated-of-the-faculty-info-box-button').click()
|
||||
cy.cs('graduated-of-the-faculty-info-box-content').contains('Sisältää kyseisenä')
|
||||
})
|
||||
|
||||
it('Thesis writers of the faculty', () => {
|
||||
cy.cs('thesis-writers-of-the-faculty-info-box-button').click()
|
||||
cy.cs('thesis-writers-of-the-faculty-info-box-content').contains('Sisältää kyseisenä')
|
||||
})
|
||||
|
||||
it('Credits produced by the faculty', () => {
|
||||
cy.cs('credits-produced-by-the-faculty-info-box-button').click()
|
||||
cy.cs('credits-produced-by-the-faculty-info-box-content').contains('Sisältää opintopisteet')
|
||||
})
|
||||
})
|
||||
|
||||
it('All graphs and tables are shown', () => {
|
||||
cy.cs('students-of-the-faculty-line-graph-section').should('be.visible')
|
||||
cy.cs('students-of-the-faculty-interactive-data-table').should('be.visible')
|
||||
cy.cs('graduated-of-the-faculty-line-graph-section').should('be.visible')
|
||||
cy.cs('graduated-of-the-faculty-interactive-data-table').should('be.visible')
|
||||
cy.cs('thesis-writers-of-the-faculty-line-graph-section').should('be.visible')
|
||||
cy.cs('thesis-writers-of-the-faculty-interactive-data-table').should('be.visible')
|
||||
cy.cs('credits-produced-by-the-faculty-stacked-bar-chart-section').should('be.visible')
|
||||
cy.cs('credits-produced-by-the-faculty-interactive-data-table').should('be.visible')
|
||||
})
|
||||
|
||||
it('Correct tabs are shown', () => {
|
||||
cy.cs('faculty-tabs').should('contain', 'Basic information')
|
||||
cy.cs('faculty-tabs').should('contain', 'Students by starting year')
|
||||
cy.cs('faculty-tabs').should('contain', 'Graduation times')
|
||||
cy.cs('faculty-tabs').should('not.contain', 'Update statistics')
|
||||
})
|
||||
|
||||
it('Toggle years works', () => {
|
||||
cy.cs('credits-produced-by-the-faculty-interactive-data-table').should('contain', '2022 - 2023')
|
||||
cy.cs('thesis-writers-of-the-faculty-interactive-data-table').should('contain', '2022 - 2023')
|
||||
cy.cs('students-of-the-faculty-interactive-data-table').should('contain', '2022 - 2023')
|
||||
cy.cs('graduated-of-the-faculty-interactive-data-table').should('contain', '2022 - 2023')
|
||||
cy.cs('year-toggle').click()
|
||||
cy.cs('credits-produced-by-the-faculty-interactive-data-table').should('contain', '2022')
|
||||
cy.cs('thesis-writers-of-the-faculty-interactive-data-table').should('contain', '2022')
|
||||
cy.cs('students-of-the-faculty-interactive-data-table').should('contain', '2022')
|
||||
cy.cs('graduated-of-the-faculty-interactive-data-table').should('contain', '2022')
|
||||
})
|
||||
|
||||
it('Toggle programmes works', () => {
|
||||
cy.cs('faculty-programmes-shown-info').should('not.exist')
|
||||
cy.cs('programme-toggle').click()
|
||||
cy.cs('faculty-programmes-shown-info').should('be.visible')
|
||||
})
|
||||
|
||||
it('Toggle study rights works', () => {
|
||||
cy.cs('faculty-exclude-specials-info').should('not.exist')
|
||||
cy.cs('study-right-toggle').click()
|
||||
cy.cs('faculty-exclude-specials-info').should('be.visible')
|
||||
})
|
||||
|
||||
it.skip('Data can be exported to Excel files', { retries: 2 }, () => {
|
||||
// TODO: Fix this test
|
||||
const sections = [
|
||||
'StudentsOfTheFaculty',
|
||||
'GraduatedOfTheFaculty',
|
||||
'ThesisWritersOfTheFaculty',
|
||||
'CreditsProducedByTheFaculty',
|
||||
]
|
||||
sections.forEach(section => {
|
||||
cy.cs(`${section}Graph`).within(() => {
|
||||
cy.get('[aria-label="View chart menu, Chart"]').click({ force: true })
|
||||
cy.contains('li.highcharts-menu-item', 'Download XLS').click()
|
||||
const downloadedFile = `oodikone_${section}_H50_${timestamp}.xls`
|
||||
cy.readFile(path.join(downloadsFolder, downloadedFile))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Students by starting year tab', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/faculties')
|
||||
cy.contains('a', 'Matemaattis-luonnontieteellinen tiedekunta').click()
|
||||
cy.contains('Students by starting year').click()
|
||||
})
|
||||
|
||||
it('Export button', { retries: 2 }, () => {
|
||||
cy.cs('faculty-student-table-export-button').should('be.visible').and('not.be.disabled').click()
|
||||
const downloadedFile = `oodikone_H50_programme_stats_${timestamp}.xlsx`
|
||||
cy.readFile(path.join(downloadsFolder, downloadedFile))
|
||||
})
|
||||
|
||||
it('Info box', () => {
|
||||
cy.cs('faculty-student-table-info-box-button').click()
|
||||
cy.cs('faculty-student-table-info-box-content').contains('Opiskelijat, joiden')
|
||||
})
|
||||
|
||||
it.skip('Study right toggle', () => {
|
||||
// TODO: Implement
|
||||
})
|
||||
|
||||
it.skip('Graduated toggle', () => {
|
||||
// TODO: Implement
|
||||
})
|
||||
|
||||
it.skip('Hoverable country list', () => {
|
||||
// TODO: Implement
|
||||
})
|
||||
|
||||
it.skip('Expandable rows', () => {
|
||||
// TODO: Implement
|
||||
})
|
||||
|
||||
it.skip('Population links', () => {
|
||||
// TODO: Implement
|
||||
})
|
||||
|
||||
it('Percentage toggle works', () => {
|
||||
cy.cs('faculty-student-stats-table').should('be.visible')
|
||||
cy.cs('faculty-student-stats-table').should('not.contain', '92.3 %')
|
||||
cy.cs('percentage-toggle').click()
|
||||
cy.cs('faculty-student-stats-table').should('contain', '92.3 %')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Progress tab', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/faculties')
|
||||
cy.contains('a', 'Matemaattis-luonnontieteellinen tiedekunta').click()
|
||||
cy.contains('Progress').click()
|
||||
})
|
||||
|
||||
it.skip('Export button', { retries: 2 }, () => {
|
||||
// TODO: Fix this test
|
||||
cy.cs('FacultyProgress-export-button').should('be.visible').and('not.be.disabled').click()
|
||||
const downloadedFile = `oodikone_H50_progress_tab_${timestamp}.xlsx`
|
||||
cy.readFile(path.join(downloadsFolder, downloadedFile))
|
||||
})
|
||||
|
||||
it.skip('Info boxes', () => {
|
||||
cy.cs('FacultyProgress-info-box-button').click()
|
||||
cy.cs('FacultyProgress-info-box-content').contains('Kuvaa tiedekuntaan')
|
||||
// TODO: Click open the accordion first
|
||||
cy.cs('BachelorMastersProgress-info-box-button').click()
|
||||
cy.cs('BachelorMastersProgress-info-box-content').contains('The starting year is the')
|
||||
})
|
||||
|
||||
it.skip('Progress bar charts exist', () => {
|
||||
// TODO: Click open the accordion first
|
||||
cy.cs('FacultyBachelorsProgressBarChart').should('be.visible')
|
||||
cy.cs('FacultyBachelorMastersProgressBarChart').should('be.visible')
|
||||
cy.cs('FacultyMastersProgressBarChart').should('be.visible')
|
||||
cy.cs('FacultyBachelorsProgressBarChart').should('be.visible')
|
||||
})
|
||||
|
||||
it.skip('Progress tables exist', () => {
|
||||
// TODO: Click open the accordion first
|
||||
cy.cs('FacultyBachelorsProgressTable').should('be.visible')
|
||||
cy.cs('FacultyBachelorMasterProgressTable').should('be.visible')
|
||||
cy.cs('FacultyMastersProgressTable').should('be.visible')
|
||||
cy.cs('FacultyBachelorsProgressTable').should('be.visible')
|
||||
})
|
||||
|
||||
it.skip('Graduated toggle', () => {
|
||||
// TODO: Implement
|
||||
})
|
||||
|
||||
it.skip('Study right toggle', () => {
|
||||
// TODO: Implement
|
||||
})
|
||||
})
|
||||
|
||||
describe('Graduation times tab', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/faculties')
|
||||
cy.contains('a', 'Matemaattis-luonnontieteellinen tiedekunta').click()
|
||||
cy.contains('Graduation times').click()
|
||||
})
|
||||
|
||||
it.skip('Export button', { retries: 2 }, () => {
|
||||
// TODO: Fix this test
|
||||
cy.cs('average-graduation-times-export-button').should('be.visible').and('not.be.disabled').click()
|
||||
const downloadedFile = `oodikone_H50_graduation_times_${timestamp}.xlsx`
|
||||
cy.readFile(path.join(downloadsFolder, downloadedFile))
|
||||
})
|
||||
|
||||
it('Info boxes', () => {
|
||||
cy.cs('average-graduation-times-info-box-button').click()
|
||||
cy.cs('average-graduation-times-info-box-content').contains('Opiskelijoiden keskimääräiset')
|
||||
})
|
||||
|
||||
it.skip('Study times toggle', () => {
|
||||
// TODO: Implement
|
||||
})
|
||||
|
||||
it.skip('Year toggle', () => {
|
||||
// TODO: Implement
|
||||
})
|
||||
|
||||
it.skip('Degree programme toggle', () => {
|
||||
// TODO: Implement
|
||||
})
|
||||
|
||||
it('Graphs are visible', () => {
|
||||
cy.cs('bachelor-graduation-times-section').should('be.visible')
|
||||
// ! No test data for bachelor + master
|
||||
cy.cs('master-graduation-times-section').should('be.visible')
|
||||
cy.cs('doctor-graduation-times-section').should('be.visible')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,468 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
const setClockToMockedDate = () => {
|
||||
const MOCKED_DATE = new Date('2024-08-30')
|
||||
cy.clock(MOCKED_DATE, ['Date'])
|
||||
}
|
||||
|
||||
const checkFilteredStudentCount = studentCount => {
|
||||
cy.contains(`Students (${studentCount})`)
|
||||
}
|
||||
|
||||
describe("Population statistics with a master's programme", { testIsolation: false }, () => {
|
||||
const pathToMathMSc2020 = '/populations?years=2020&programme=MH50_001&semesters=FALL&semesters=SPRING'
|
||||
const defaultAmountOfStudents = 26
|
||||
const expectedBaMaStudents = 24
|
||||
const expectedMasterOnlyStudents = 2
|
||||
|
||||
before(() => cy.init(pathToMathMSc2020))
|
||||
|
||||
it('Study track filter works', () => {
|
||||
cy.cs('studyTrackFilter-header').click()
|
||||
cy.selectFromDropdown('studyTrackFilter', 'Matematiikka ja soveltava matematiikka (MAST-MSM)', true)
|
||||
checkFilteredStudentCount(15)
|
||||
|
||||
cy.cs('studyTrackFilter-clear').click()
|
||||
cy.cs('studyTrackFilter-header').click()
|
||||
})
|
||||
|
||||
it('Study right type filter works', () => {
|
||||
cy.cs('studyRightTypeFilter-header').click()
|
||||
cy.get('input[name="studyRightTypeFilter"][value="0"]').should('be.checked')
|
||||
|
||||
// Bachelor + master
|
||||
cy.get('input[name="studyRightTypeFilter"][value="1"]').click()
|
||||
cy.get('input[name="studyRightTypeFilter"][value="1"]').should('be.checked')
|
||||
checkFilteredStudentCount(expectedBaMaStudents)
|
||||
// Master only
|
||||
cy.get('input[name="studyRightTypeFilter"][value="2"]').click()
|
||||
cy.get('input[name="studyRightTypeFilter"][value="2"]').should('be.checked')
|
||||
checkFilteredStudentCount(expectedMasterOnlyStudents)
|
||||
// All
|
||||
cy.get('input[name="studyRightTypeFilter"][value="0"]').click()
|
||||
cy.get('input[name="studyRightTypeFilter"][value="0"]').should('be.checked')
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
|
||||
cy.cs('studyRightTypeFilter-header').click()
|
||||
})
|
||||
})
|
||||
|
||||
describe.skip('Population Statistics', { testIsolation: false }, () => {
|
||||
const pathToMathBSc2020 = '/populations?years=2020&programme=KH50_001&semesters=FALL&semesters=SPRING'
|
||||
const defaultAmountOfStudents = 27
|
||||
const graduated = 16
|
||||
const transferred = 3
|
||||
|
||||
before(() => cy.init(pathToMathBSc2020))
|
||||
beforeEach(() => setClockToMockedDate())
|
||||
|
||||
it.skip('Study right type filter is not visible', () => {
|
||||
cy.contains('Study right type').should('not.exist')
|
||||
})
|
||||
|
||||
// TODO: FilterRadio is not working correcly
|
||||
it.skip('Transfer filter works and is set to "not transferred" by default', () => {
|
||||
cy.cs('transferredToProgrammeFilter-filter-card').should('have.attr', 'data-active', 'true')
|
||||
cy.get('input[name="transferredToProgrammeFilter"][value="Not transferred"]').should('be.checked')
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
|
||||
cy.cs('transferredToProgrammeFilter-filter-card').should('have.attr', 'data-active', 'true')
|
||||
cy.get('input[name="transferredToProgrammeFilter"][value="Not transferred"]').should('be.checked')
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
|
||||
cy.get('input[name="transferredToProgrammeFilter"][value="Transferred"]').click()
|
||||
cy.get('input[name="transferredToProgrammeFilter"][value="Transferred"]').should('be.checked')
|
||||
checkFilteredStudentCount(transferred)
|
||||
|
||||
cy.get('input[name="transferredToProgrammeFilter"][value="All"]').click()
|
||||
cy.get('input[name="transferredToProgrammeFilter"][value="All"]').should('be.checked')
|
||||
checkFilteredStudentCount(defaultAmountOfStudents + transferred)
|
||||
|
||||
cy.get('input[name="transferredToProgrammeFilter"][value="Not transferred"]').click()
|
||||
cy.get('input[name="transferredToProgrammeFilter"][value="Not transferred"]').should('be.checked')
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Graduation filter works', () => {
|
||||
cy.cs('graduatedFromProgrammeFilter-header').click()
|
||||
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="1"]').click()
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="1"]').should('be.checked')
|
||||
checkFilteredStudentCount(graduated)
|
||||
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="-1"]').click()
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="-1"]').should('be.checked')
|
||||
checkFilteredStudentCount(defaultAmountOfStudents - graduated)
|
||||
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="0"]').click()
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="0"]').should('be.checked')
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
|
||||
cy.cs('graduatedFromProgrammeFilter-header').click()
|
||||
})
|
||||
|
||||
it('Enrollment filter works', () => {
|
||||
cy.cs('enrollmentStatusFilter-header').click()
|
||||
cy.selectFromDropdown('enrollmentStatusFilter-status', 0)
|
||||
cy.selectFromDropdown('enrollmentStatusFilter-semester', 'Syksy 2023', true)
|
||||
checkFilteredStudentCount(25)
|
||||
|
||||
cy.cs('enrollmentStatusFilter-clear').click()
|
||||
cy.cs('enrollmentStatusFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Credit filter works', () => {
|
||||
cy.cs('creditsEarnedFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
cy.setRangeSelect('creditsEarnedFilter', 50, 150, 12)
|
||||
|
||||
cy.cs('creditsEarnedFilter-clear').click()
|
||||
cy.cs('creditsEarnedFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Age filter works', () => {
|
||||
cy.cs('ageFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
cy.setRangeSelect('ageFilter', 23, 30, 21)
|
||||
|
||||
cy.cs('ageFilter-clear').click()
|
||||
cy.cs('ageFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Gender filter works', () => {
|
||||
cy.cs('genderFilter-header').click()
|
||||
cy.selectFromDropdown('genderFilter', 0)
|
||||
checkFilteredStudentCount(13)
|
||||
cy.selectFromDropdown('genderFilter', 1)
|
||||
checkFilteredStudentCount(14)
|
||||
cy.selectFromDropdown('genderFilter', 2)
|
||||
checkFilteredStudentCount(0)
|
||||
cy.selectFromDropdown('genderFilter', 3)
|
||||
checkFilteredStudentCount(0)
|
||||
|
||||
cy.cs('genderFilter-clear').click()
|
||||
cy.cs('genderFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Starting year filter works', () => {
|
||||
cy.cs('startYearAtUniFilter-header').click()
|
||||
cy.selectFromDropdown('startYearAtUniFilter', 0)
|
||||
checkFilteredStudentCount(1)
|
||||
cy.selectFromDropdown('startYearAtUniFilter', 7)
|
||||
checkFilteredStudentCount(21)
|
||||
|
||||
cy.cs('startYearAtUniFilter-clear').click()
|
||||
cy.cs('startYearAtUniFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Admission type filter works', () => {
|
||||
cy.cs('admissionTypeFilter-header').click()
|
||||
cy.selectFromDropdown('admissionTypeFilter', 0)
|
||||
checkFilteredStudentCount(18)
|
||||
cy.selectFromDropdown('admissionTypeFilter', 1)
|
||||
checkFilteredStudentCount(6)
|
||||
|
||||
cy.cs('admissionTypeFilter-clear').click()
|
||||
cy.cs('admissionTypeFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Courses filter works', () => {
|
||||
const courses = [
|
||||
{ code: 'MAT21012', name: 'Differentiaaliyhtälöt I' },
|
||||
{ code: 'MFK-M204', name: 'Matematiikkaa kaikkialla' },
|
||||
]
|
||||
|
||||
cy.cs('courseFilter-header').click()
|
||||
cy.selectFromAutocomplete('courseFilter', `${courses[0].code} - ${courses[0].name}`)
|
||||
checkFilteredStudentCount(9)
|
||||
cy.selectFromDropdown(`courseFilter-${courses[0].code}`, 1)
|
||||
checkFilteredStudentCount(7)
|
||||
cy.selectFromAutocomplete('courseFilter', `${courses[1].code} - ${courses[1].name}`)
|
||||
checkFilteredStudentCount(6)
|
||||
cy.selectFromDropdown(`courseFilter-${courses[1].code}`, 1)
|
||||
checkFilteredStudentCount(4)
|
||||
|
||||
cy.cs(`courseFilter-${courses[1].code}-clear`).click()
|
||||
checkFilteredStudentCount(7)
|
||||
|
||||
cy.cs('courseFilter-clear').click()
|
||||
cy.cs('courseFilter-header').click()
|
||||
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Filter combinations work', () => {
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
|
||||
cy.cs('graduatedFromProgrammeFilter-header').click()
|
||||
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="1"]').click()
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="1"]').should('be.checked')
|
||||
checkFilteredStudentCount(graduated)
|
||||
|
||||
cy.cs('ageFilter-header').click()
|
||||
cy.setRangeSelect('ageFilter', 23, 30, 12)
|
||||
|
||||
cy.cs('graduatedFromProgrammeFilter-clear').click()
|
||||
cy.cs('graduatedFromProgrammeFilter-header').click()
|
||||
cy.cs('ageFilter-clear').click()
|
||||
cy.cs('ageFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('"Reset All Filters" button works', () => {
|
||||
cy.cs('genderFilter-header').click()
|
||||
cy.selectFromDropdown('genderFilter', 0)
|
||||
checkFilteredStudentCount(13)
|
||||
cy.cs('startYearAtUniFilter-header').click()
|
||||
cy.selectFromDropdown('startYearAtUniFilter', 7)
|
||||
checkFilteredStudentCount(8)
|
||||
|
||||
cy.cs('reset-all-filters').click()
|
||||
cy.cs('genderFilter-header').click()
|
||||
cy.cs('startYearAtUniFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Population Statistics with Bachelor + Master', { testIsolation: false }, () => {
|
||||
const pathToMathBSc2017 =
|
||||
'/populations?years=2017&programme=KH50_001&showBachelorAndMaster=true&semesters=FALL&semesters=SPRING'
|
||||
const defaultAmountOfStudents = 47
|
||||
|
||||
before(() => cy.init(pathToMathBSc2017))
|
||||
|
||||
it('Graduation filter works', () => {
|
||||
cy.cs('graduatedFromProgrammeFilter-header').click()
|
||||
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="1"]').click()
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="1"]').should('be.checked')
|
||||
checkFilteredStudentCount(42)
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="2"]').click()
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="2"]').should('be.checked')
|
||||
checkFilteredStudentCount(18)
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="-1"]').click()
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="-1"]').should('be.checked')
|
||||
checkFilteredStudentCount(5)
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="-2"]').click()
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="-2"]').should('be.checked')
|
||||
checkFilteredStudentCount(29)
|
||||
|
||||
cy.cs('graduatedFromProgrammeFilter-clear').click()
|
||||
cy.cs('graduatedFromProgrammeFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Study right status filter works', () => {
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
cy.cs('studyRightStatusFilter-header').click()
|
||||
|
||||
// Bachelor
|
||||
cy.get('input[name="studyRightStatusFilter"][value="Active Bachelor study right"]').click()
|
||||
cy.get('input[name="studyRightStatusFilter"][value="Active Bachelor study right"]').should('be.checked')
|
||||
checkFilteredStudentCount(0)
|
||||
// Master (combined)
|
||||
cy.get('input[name="studyRightStatusFilter"][value="Active Master study right"]').click()
|
||||
cy.get('input[name="studyRightStatusFilter"][value="Active Master study right"]').should('be.checked')
|
||||
checkFilteredStudentCount(0)
|
||||
|
||||
// Non-Bachelor
|
||||
cy.get('input[name="studyRightStatusFilter"][value="Passive Bachelor study right"]').click()
|
||||
cy.get('input[name="studyRightStatusFilter"][value="Passive Bachelor study right"]').should('be.checked')
|
||||
checkFilteredStudentCount(5)
|
||||
// Non-Master (combined)
|
||||
cy.get('input[name="studyRightStatusFilter"][value="Passive Master study right"]').click()
|
||||
cy.get('input[name="studyRightStatusFilter"][value="Passive Master study right"]').should('be.checked')
|
||||
checkFilteredStudentCount(24)
|
||||
|
||||
cy.cs('studyRightStatusFilter-clear').click()
|
||||
cy.cs('studyRightStatusFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
})
|
||||
|
||||
// FIXME: Flaky
|
||||
describe.skip('Course Statistics', { testIsolation: false }, () => {
|
||||
const pathToLimits2021 =
|
||||
'/coursepopulation?coursecodes=%5B"MAT11003"%2C"57116"%2C"57016"%2C"AYMAT11003"%5D&from=72&separate=false&to=72&unifyCourses=unifyStats'
|
||||
const defaultAmountOfStudents = 48
|
||||
|
||||
before(() => cy.init(pathToLimits2021))
|
||||
beforeEach(() => setClockToMockedDate())
|
||||
|
||||
it('Grade filter works', () => {
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
cy.cs('gradeFilter-header').click()
|
||||
|
||||
cy.cs('gradeFilter-5').click()
|
||||
checkFilteredStudentCount(23)
|
||||
cy.cs('gradeFilter-3').click()
|
||||
checkFilteredStudentCount(29)
|
||||
cy.cs('gradeFilter-3').click()
|
||||
cy.cs('gradeFilter-5').click()
|
||||
|
||||
cy.cs('gradeFilter-clear').should('not.exist')
|
||||
|
||||
cy.cs('gradeFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Programme filter works and defaults to "Attainment"', () => {
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
cy.cs('programmeFilter-header').click()
|
||||
cy.cs('programmeFilter-mode-selector').children().eq(0).should('contain', 'Attainment')
|
||||
cy.selectFromDropdown('programmeFilter', 1, true)
|
||||
checkFilteredStudentCount(33)
|
||||
|
||||
cy.cs('programmeFilter-clear').click()
|
||||
cy.cs('programmeFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Age filter works', () => {
|
||||
cy.cs('ageFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
cy.setRangeSelect('ageFilter', 23, 30, 36)
|
||||
|
||||
cy.cs('ageFilter-clear').click()
|
||||
cy.cs('ageFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Gender filter works', () => {
|
||||
cy.cs('genderFilter-header').click()
|
||||
cy.selectFromDropdown('genderFilter', 0)
|
||||
checkFilteredStudentCount(9)
|
||||
cy.selectFromDropdown('genderFilter', 1)
|
||||
checkFilteredStudentCount(39)
|
||||
cy.selectFromDropdown('genderFilter', 2)
|
||||
checkFilteredStudentCount(0)
|
||||
cy.selectFromDropdown('genderFilter', 3)
|
||||
checkFilteredStudentCount(0)
|
||||
|
||||
cy.cs('genderFilter-clear').click()
|
||||
cy.cs('genderFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Starting year filter works', () => {
|
||||
cy.cs('startYearAtUniFilter-header').click()
|
||||
cy.selectFromDropdown('startYearAtUniFilter', 0)
|
||||
checkFilteredStudentCount(1)
|
||||
cy.selectFromDropdown('startYearAtUniFilter', 10)
|
||||
checkFilteredStudentCount(24)
|
||||
|
||||
cy.cs('startYearAtUniFilter-clear').click()
|
||||
cy.cs('startYearAtUniFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Filter combinations work', () => {
|
||||
cy.cs('ageFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
cy.setRangeSelect('ageFilter', 23, 30, 36)
|
||||
|
||||
cy.cs('gradeFilter-header').click()
|
||||
cy.cs('gradeFilter-5').click()
|
||||
checkFilteredStudentCount(17)
|
||||
|
||||
cy.cs('gradeFilter-clear').click()
|
||||
cy.cs('gradeFilter-header').click()
|
||||
cy.cs('ageFilter-clear').click()
|
||||
cy.cs('ageFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Custom Population Statistics', { testIsolation: false }, () => {
|
||||
let defaultAmountOfStudents
|
||||
|
||||
before(() => {
|
||||
cy.init('/custompopulation')
|
||||
cy.fixture('customPopulations').then(({ studentNumbersForCSStudentsSet1, studentNumbersForCSStudentsSet2 }) => {
|
||||
const students = [...studentNumbersForCSStudentsSet1, ...studentNumbersForCSStudentsSet2]
|
||||
defaultAmountOfStudents = students.length
|
||||
cy.cs('student-number-input').click()
|
||||
cy.cs('student-number-input').type(students.join('{enter}'))
|
||||
cy.cs('search-button').click()
|
||||
})
|
||||
})
|
||||
beforeEach(() => setClockToMockedDate())
|
||||
|
||||
it('Age filter works', () => {
|
||||
cy.cs('ageFilter-header').click()
|
||||
cy.setRangeSelect('ageFilter', 24, 28, 5)
|
||||
|
||||
cy.cs('ageFilter-clear').click()
|
||||
cy.cs('ageFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Programme filter works and defaults to "Active Study Right"', () => {
|
||||
cy.cs('programmeFilter-header').click()
|
||||
cy.cs('programmeFilter-mode-selector').children().eq(0).should('contain', 'Active Study Right')
|
||||
cy.selectFromDropdown('programmeFilter', 1, true)
|
||||
checkFilteredStudentCount(3)
|
||||
|
||||
cy.cs('programmeFilter-clear').click()
|
||||
cy.cs('programmeFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Gender filter works', () => {
|
||||
cy.cs('genderFilter-header').click()
|
||||
cy.selectFromDropdown('genderFilter', 0)
|
||||
checkFilteredStudentCount(5)
|
||||
cy.selectFromDropdown('genderFilter', 1)
|
||||
checkFilteredStudentCount(3)
|
||||
cy.selectFromDropdown('genderFilter', 2)
|
||||
checkFilteredStudentCount(0)
|
||||
cy.selectFromDropdown('genderFilter', 3)
|
||||
checkFilteredStudentCount(0)
|
||||
|
||||
cy.cs('genderFilter-clear').click()
|
||||
cy.cs('genderFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Starting year filter works', () => {
|
||||
cy.cs('startYearAtUniFilter-header').click()
|
||||
cy.selectFromDropdown('startYearAtUniFilter', 0)
|
||||
checkFilteredStudentCount(2)
|
||||
|
||||
cy.cs('startYearAtUniFilter-clear').click()
|
||||
cy.cs('startYearAtUniFilter-header').click()
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
|
||||
it('Courses filter works', () => {
|
||||
const courses = [
|
||||
{ code: 'MAT11005', name: 'Integraalilaskenta' },
|
||||
{ code: 'MAT21007', name: 'Mitta ja integraali' },
|
||||
]
|
||||
|
||||
cy.cs('courseFilter-header').click()
|
||||
cy.selectFromAutocomplete('courseFilter', `${courses[0].code} - ${courses[0].name}`)
|
||||
checkFilteredStudentCount(7)
|
||||
cy.selectFromDropdown(`courseFilter-${courses[0].code}`, 1)
|
||||
checkFilteredStudentCount(6)
|
||||
cy.selectFromAutocomplete('courseFilter', `${courses[1].code} - ${courses[1].name}`)
|
||||
checkFilteredStudentCount(6)
|
||||
cy.selectFromDropdown(`courseFilter-${courses[1].code}`, 3)
|
||||
checkFilteredStudentCount(6)
|
||||
|
||||
cy.cs(`courseFilter-${courses[1].code}-clear`).click()
|
||||
checkFilteredStudentCount(6)
|
||||
|
||||
cy.cs('courseFilter-clear').click()
|
||||
cy.cs('courseFilter-header').click()
|
||||
|
||||
checkFilteredStudentCount(defaultAmountOfStudents)
|
||||
})
|
||||
})
|
||||
@@ -1,89 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
const chooseSemester = (semester, fromOrTo) => {
|
||||
cy.cs(`semester-${fromOrTo}`).click()
|
||||
cy.cs(`select-opt-${semester}`).click()
|
||||
cy.cs(`select-opt-${semester}`).should('not.have.class', 'visible')
|
||||
}
|
||||
|
||||
const checkNumbers = (numbers, numberOfColumns, mode) => {
|
||||
const offset = 1 // skip first col with codes / names
|
||||
cy.cs(`ooditable-${mode}`).find('table').find('tbody').as('tbody')
|
||||
cy.get('@tbody').find('tr').first().as('totalRow')
|
||||
cy.get('@totalRow').find('td').should('have.length', numberOfColumns)
|
||||
cy.get('@totalRow').find('td').eq(0).should('contain', 'All courses total')
|
||||
|
||||
numbers.forEach((number, index) => {
|
||||
cy.get('@totalRow')
|
||||
.find('td')
|
||||
.eq(index + offset)
|
||||
.should('contain', number)
|
||||
})
|
||||
}
|
||||
|
||||
describe('When language center is opened', () => {
|
||||
describe('as an admin user', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/languagecenterview', 'admin')
|
||||
cy.cs('completions-button').click()
|
||||
})
|
||||
|
||||
describe('Faculties tab', () => {
|
||||
beforeEach(() => {
|
||||
chooseSemester('Syksy 2017', 'from')
|
||||
chooseSemester('Kevät 2024', 'to')
|
||||
})
|
||||
|
||||
it('Initial view is correct', () => {
|
||||
cy.contains('All courses total')
|
||||
cy.contains('Academic and Professional')
|
||||
cy.contains('AYKK-RUKIRJ')
|
||||
})
|
||||
|
||||
it('Faculties tab shows numbers', () => {
|
||||
cy.get('table > tbody > tr:first').within(() => {
|
||||
cy.get('td').should('have.length', 15)
|
||||
cy.get('td').eq(0).contains('All courses total')
|
||||
const numbers = [2076, 36, 9, 34, 759, 15, 40, 6, 51, 1, 24, 1059, 42, 0]
|
||||
numbers.forEach((number, index) => {
|
||||
cy.get('td')
|
||||
.eq(index + 1)
|
||||
.contains(number)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('Faculties tab "exceeding" button works', () => {
|
||||
cy.cs('difference-button').click()
|
||||
checkNumbers([66, 3, 0, 4, 18, 0, 1, 1, 4, 0, 0, 31, 3, 1], 15, 'faculties')
|
||||
})
|
||||
|
||||
it('Faculties tab semester selector changes numbers', () => {
|
||||
chooseSemester('Syksy 2020', 'from')
|
||||
checkNumbers([1184, 28, 6, 28, 499, 4, 10, 2, 36, 0, 9, 535, 27, 0], 15, 'faculties')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Semester tab', () => {
|
||||
beforeEach(() => {
|
||||
cy.contains('By semesters').click()
|
||||
chooseSemester('Syksy 2017', 'from')
|
||||
chooseSemester('Kevät 2024', 'to')
|
||||
})
|
||||
|
||||
it('Semester tab shows numbers', () => {
|
||||
checkNumbers([2076, 69, 26, 298, 58, 343, 98, 438, 138, 310, 90, 123, 74, 10, 1], 16, 'semesters')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a user with no rights', () => {
|
||||
it('"Access denied" is shown', () => {
|
||||
cy.init('/languagecenterview', 'norights')
|
||||
cy.contains('Access denied')
|
||||
cy.contains("You don't currently have permission to view this page.")
|
||||
cy.contains('Special populations').click()
|
||||
cy.contains('Language center view').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,443 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
// Now "Class statistics" in UI
|
||||
|
||||
const selectStudyProgramme = programme => {
|
||||
cy.cs('population-programme-selector').within(() =>
|
||||
cy.get('input').should('have.attr', 'placeholder', 'Select degree programme')
|
||||
)
|
||||
cy.cs('population-programme-selector-parent').click()
|
||||
cy.cs('population-programme-selector-parent').within(() => cy.contains(programme).click())
|
||||
}
|
||||
|
||||
const selectStudyTrack = studyTrack => {
|
||||
cy.cs('population-studytrack-selector').within(() =>
|
||||
cy.get('input').should('have.attr', 'placeholder', 'Select study track')
|
||||
)
|
||||
cy.cs('population-studytrack-selector-parent').click()
|
||||
cy.cs('population-studytrack-selector-parent').within(() => cy.contains(studyTrack).click())
|
||||
}
|
||||
|
||||
describe('Population statistics tests', () => {
|
||||
const getPath = programme => {
|
||||
return `/populations?months=49&semesters=FALL&semesters=SPRING&programme=${programme}&years=2020`
|
||||
}
|
||||
const pathToMathBSc2020 = getPath('KH50_001')
|
||||
const pathToMathMSc2020 = getPath('MH50_001')
|
||||
|
||||
describe('When using basic user', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/populations')
|
||||
cy.intercept('/api/populationstatistics/studyprogrammes').as('studyprogrammes')
|
||||
cy.intercept('/api/studyprogrammes/**/studytracks').as('studytracks')
|
||||
})
|
||||
|
||||
describe('Population search', () => {
|
||||
it('Info box works', () => {
|
||||
cy.cs('PopulationSearch-info-box-content').should('not.exist')
|
||||
cy.cs('PopulationSearch-info-box-button').hover()
|
||||
cy.cs('PopulationSearch-info-box-content').should('be.visible')
|
||||
cy.cs('PopulationSearch-info-box-content').contains('Tässä osiossa voi tarkastella')
|
||||
cy.cs('PopulationSearch-info-box-button').trigger('mouseout')
|
||||
cy.cs('PopulationSearch-info-box-content').should('not.exist')
|
||||
})
|
||||
|
||||
// TODO: Delete MUI
|
||||
it.skip('Form is usable', { retries: { runMode: 2 } }, () => {
|
||||
cy.contains('Search for class')
|
||||
cy.contains('See class').should('be.disabled')
|
||||
|
||||
cy.cs('population-year-selector').as('yearSelect')
|
||||
cy.cs('population-year-decrement').as('yearDecrement')
|
||||
cy.cs('population-year-increment').as('yearIncrement')
|
||||
|
||||
cy.get('@yearSelect').click()
|
||||
cy.contains('2018 - 2019').click()
|
||||
cy.get('@yearSelect').within(() => cy.contains('2018 - 2019'))
|
||||
cy.get('@yearDecrement').click()
|
||||
cy.get('@yearSelect').within(() => cy.contains('2017 - 2018'))
|
||||
cy.get('@yearIncrement').click()
|
||||
cy.get('@yearSelect').within(() => cy.contains('2018 - 2019'))
|
||||
|
||||
cy.cs('population-studytrack-selector').within(() => {
|
||||
cy.get('input').should('have.attr', 'placeholder', 'No study tracks available')
|
||||
})
|
||||
selectStudyProgramme('Matematiikan ja tilastotieteen maisteriohjelma')
|
||||
cy.contains('See class').should('be.enabled')
|
||||
selectStudyTrack('Matematiikka ja soveltava matematiikka')
|
||||
cy.contains('See class').should('be.enabled')
|
||||
})
|
||||
|
||||
describe('Correct population is shown for programme', () => {
|
||||
// TODO: Delete MUI
|
||||
it.skip('without study tracks', () => {
|
||||
cy.wait('@studyprogrammes').its('response.statusCode').should('be.oneOf', [200, 304])
|
||||
selectStudyProgramme('Matemaattisten tieteiden kandiohjelma')
|
||||
cy.wait('@studytracks').its('response.statusCode').should('be.oneOf', [200, 304])
|
||||
cy.contains('See class').click()
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma')
|
||||
cy.contains('Class of 2017 - 2018, 47 students')
|
||||
})
|
||||
|
||||
// TODO: Delete MUI
|
||||
it.skip('with study tracks', () => {
|
||||
selectStudyProgramme('Matematiikan ja tilastotieteen maisteriohjelma')
|
||||
cy.wait('@studytracks').its('response.statusCode').should('be.oneOf', [200, 304])
|
||||
selectStudyTrack('Matematiikka ja soveltava matematiikka')
|
||||
cy.contains('See class').click()
|
||||
cy.contains('Matematiikan ja tilastotieteen maisteriohjelma 2017 - 2018')
|
||||
cy.contains('studytrack MAST-MSM')
|
||||
cy.contains('Class size 1 students')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('Population statistics is usable on general level', () => {
|
||||
cy.visit(pathToMathBSc2020)
|
||||
cy.cs('filtered-students')
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma')
|
||||
cy.contains('Class of 2020 - 2021, 30 students')
|
||||
cy.contains('Excludes exchange students')
|
||||
cy.contains('Excludes students with non-degree study right')
|
||||
cy.contains('Excludes students who have transferred out of this programme')
|
||||
cy.cs('filtered-students')
|
||||
})
|
||||
|
||||
// This test sometimes fails on headless mode. It seems that the click on the
|
||||
// 'Fetch class with new settings' button doesn't always trigger history.push()
|
||||
// so the page doesn't reload. This is why waiting also doesn't help.
|
||||
it('Advanced settings work', { retries: 2 }, () => {
|
||||
cy.visit(pathToMathMSc2020)
|
||||
cy.get('[data-cy=advanced-toggle]').click()
|
||||
// only spring
|
||||
cy.cs('toggle-fall').click()
|
||||
cy.contains('Fetch class').click()
|
||||
cy.contains('Credit accumulation (for 17 students)')
|
||||
cy.url().should('not.include', 'semesters=FALL')
|
||||
// only fall
|
||||
cy.get('[data-cy=advanced-toggle]').click()
|
||||
cy.cs('toggle-fall').click()
|
||||
cy.cs('toggle-spring').click()
|
||||
cy.contains('Fetch class').click()
|
||||
cy.contains('Credit accumulation (for 9 students)')
|
||||
cy.url().should('not.include', 'semesters=SPRING')
|
||||
// spring + fall
|
||||
cy.get('[data-cy=advanced-toggle]').click()
|
||||
cy.cs('toggle-spring').click()
|
||||
cy.contains('Fetch class').click()
|
||||
cy.contains('Credit accumulation (for 26 students)')
|
||||
cy.url().should('include', 'semesters=FALL&semesters=SPRING')
|
||||
})
|
||||
|
||||
describe('Credit statistics', () => {
|
||||
it("'Credits gained' tab shows correct statistics for all students of the class and also students grouped by admission type", () => {
|
||||
cy.clock(new Date('2024-08-30').getTime(), ['Date'])
|
||||
cy.visit(pathToMathBSc2020)
|
||||
const totalStudents = 27
|
||||
cy.contains('Credit statistics')
|
||||
.parent()
|
||||
.then($parentDiv => {
|
||||
if (!$parentDiv.hasClass('active')) cy.contains('Credit statistics').click()
|
||||
})
|
||||
cy.contains('Credits gained').click()
|
||||
const limits = [1, 45, 90, 135, 180, null]
|
||||
const ranges = limits.map((limit, i) => (i === 0 ? [null, 0] : [limits[i - 1], limit])).reverse()
|
||||
|
||||
const getTableData = (selector, numbersOfStudents) => {
|
||||
const studentsInCategory = numbersOfStudents.reduce((acc, val) => acc + val, 0)
|
||||
return ranges.map((range, index) => ({
|
||||
selector: `[data-cy='credits-gained-table-${selector}']`,
|
||||
start: range[0],
|
||||
end: range[1],
|
||||
students: numbersOfStudents[index],
|
||||
percentage: `${((numbersOfStudents[index] / studentsInCategory) * 100).toFixed(1)}%`,
|
||||
}))
|
||||
}
|
||||
|
||||
cy.cs('credits-gained-table-All students of the class').within(() => {
|
||||
cy.get('th').eq(1).contains('Credits gained between 01.08.2020 and 30.08.2024')
|
||||
cy.get('th').eq(1).contains('(49 months)')
|
||||
cy.get('th').eq(2).contains('Number of students')
|
||||
cy.get('th').eq(2).contains(`(n = ${totalStudents})`)
|
||||
cy.get('th').eq(3).contains('Percentage of population')
|
||||
})
|
||||
|
||||
for (const category of [
|
||||
getTableData('All students of the class', [9, 5, 7, 4, 2, 0]),
|
||||
getTableData('Avoin väylä', [0, 1, 3, 2, 0, 0]),
|
||||
getTableData('Muu', [0, 1, 1, 1, 0, 0]),
|
||||
getTableData('Todistusvalinta', [9, 3, 3, 1, 2, 0]),
|
||||
]) {
|
||||
category.forEach(({ selector, start, end, students, percentage }, index) => {
|
||||
let value
|
||||
if (start === null) {
|
||||
value = '0'
|
||||
} else if (end === null) {
|
||||
value = `${start} ≤ credits`
|
||||
} else {
|
||||
value = `${start} ≤ credits < ${end}`
|
||||
}
|
||||
cy.get(`${selector} [data-cy='credits-gained-table-body']`).within(() => {
|
||||
cy.get('tr')
|
||||
.eq(index)
|
||||
.within(() => {
|
||||
cy.get('td').eq(1).contains(value)
|
||||
cy.get('td').eq(2).contains(students)
|
||||
cy.get('td').eq(3).contains(percentage)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
cy.get(
|
||||
"[data-cy='credits-gained-table-All students of the class'] [data-cy='credits-gained-table-body'] td:nth-child(3)"
|
||||
).then(tds => {
|
||||
const sum = [...tds].reduce((acc, td) => acc + parseInt(td.innerText, 10), 0)
|
||||
expect(sum).to.equal(totalStudents)
|
||||
})
|
||||
})
|
||||
|
||||
it("'Statistics' tab shows correct statistics for all students of the class and also students grouped by admission type", () => {
|
||||
cy.visit(pathToMathBSc2020)
|
||||
cy.contains('Credit statistics')
|
||||
.parent()
|
||||
.then($parentDiv => {
|
||||
if (!$parentDiv.hasClass('active')) cy.contains('Credit statistics').click()
|
||||
})
|
||||
cy.cs('credit-statistics-tab').click()
|
||||
const rows = ['Total credits', 'Average', 'Median', 'Standard deviation', 'Minimum', 'Maximum']
|
||||
const categories = [
|
||||
{
|
||||
selector: 'All students of the population',
|
||||
data: ['6136.50', '227.28', '197.00', '117.94', '60', '533'],
|
||||
size: 27,
|
||||
},
|
||||
{
|
||||
selector: 'Muu',
|
||||
data: ['580.00', '193.33', '192.00', '36.75', '149', '239'],
|
||||
size: 3,
|
||||
},
|
||||
{
|
||||
selector: 'Todistusvalinta',
|
||||
data: ['3657.50', '203.19', '193.50', '98.35', '60', '460'],
|
||||
size: 18,
|
||||
},
|
||||
{
|
||||
selector: 'Avoin väylä',
|
||||
data: ['1899.00', '316.50', '257.00', '150.43', '150', '533'],
|
||||
size: 6,
|
||||
},
|
||||
]
|
||||
|
||||
for (const { selector, data, size } of categories) {
|
||||
cy.get(`[data-cy='statistics-table-${selector}']`).within(() => {
|
||||
cy.contains('h5', selector)
|
||||
cy.contains("[data-cy='credit-stats-population-size']", `n = ${size}`)
|
||||
cy.get('table tbody').within(() => {
|
||||
rows.forEach((text, index) => {
|
||||
cy.get('tr')
|
||||
.eq(index)
|
||||
.within(() => {
|
||||
cy.get('td').eq(0).contains(text)
|
||||
cy.get('td').eq(1).contains(data[index])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('Courses of class', () => {
|
||||
it('Is displayed and link to individual course stats page works', () => {
|
||||
cy.visit(pathToMathBSc2020)
|
||||
cy.contains('Courses of class').click()
|
||||
cy.intercept('/api/courseyearlystats**').as('coursePage')
|
||||
cy.cs('toggle-group-module-MAT110').click()
|
||||
cy.contains('td', 'MAT11001').siblings().find('[data-testid="NorthEastIcon"]').click()
|
||||
cy.wait('@coursePage')
|
||||
cy.url().should('include', '/coursestatistics')
|
||||
cy.contains('MAT11001') // Johdatus yliopistomatematiikkaan
|
||||
cy.contains('AYMAT11001') // Avoin yo: Johdatus yliopistomatematiikkaan
|
||||
cy.contains('57033') // Johdatus yliopistomatematiikkaan
|
||||
cy.contains('A57033') // Avoin yo: Johdatus yliopistomatematiikkaan
|
||||
})
|
||||
|
||||
it('Curriculum selection works', () => {
|
||||
cy.visit(pathToMathBSc2020)
|
||||
cy.contains('Courses of class').click()
|
||||
cy.get('[data-cy=curriculum-picker]').contains('2020–2023')
|
||||
cy.get('[data-cy=toggle-group-module-MAT-tyo]')
|
||||
cy.get('[data-cy=curriculum-picker]').click()
|
||||
cy.contains('2023–2026').click()
|
||||
cy.get('[data-cy=toggle-group-module-MAT-tyo]').should('not.exist')
|
||||
})
|
||||
|
||||
it('Courses data is changed when curriculum is changed', () => {
|
||||
cy.visit(pathToMathBSc2020)
|
||||
cy.contains('Courses of class').click()
|
||||
|
||||
cy.cs('curriculum-picker').scrollIntoView()
|
||||
cy.cs('curriculum-picker').should('be.visible')
|
||||
cy.cs('curriculum-picker').click()
|
||||
cy.contains('2020–2023').click({ force: true })
|
||||
cy.contains('Students (27)')
|
||||
cy.cs('toggle-group-module-DIGI-k').should('exist')
|
||||
cy.cs('toggle-group-module-DIGI-k').scrollIntoView()
|
||||
cy.cs('toggle-group-module-DIGI-k').should('be.visible')
|
||||
cy.cs('toggle-group-module-DIGI-k').click({ force: true })
|
||||
cy.contains('DIGI-100').should('exist')
|
||||
|
||||
cy.cs('curriculum-picker').scrollIntoView()
|
||||
cy.cs('toggle-group-module-DIGI-k').should('be.visible')
|
||||
cy.cs('curriculum-picker').click()
|
||||
cy.contains('2023–2026').click({ force: true })
|
||||
cy.cs('toggle-group-module-DIGI-k').should('exist')
|
||||
cy.contains('DIGI-100').should('not.exist')
|
||||
})
|
||||
|
||||
it('Courses data is changed when filtered students change', () => {
|
||||
cy.visit(pathToMathBSc2020)
|
||||
|
||||
cy.cs('graduatedFromProgrammeFilter-filter-card').within(() => {
|
||||
cy.cs('graduatedFromProgrammeFilter-header').click()
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="1"]').click()
|
||||
cy.get('input[name="graduatedFromProgrammeFilter"][value="1"]').should('be.checked')
|
||||
})
|
||||
|
||||
cy.contains('Students (16)')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Students', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit(pathToMathBSc2020)
|
||||
cy.contains('Students (27)')
|
||||
.parent()
|
||||
.then($parentDiv => {
|
||||
if (!$parentDiv.hasClass('active')) cy.contains('Students (27)').click()
|
||||
})
|
||||
})
|
||||
|
||||
it("'General tab' is usable", () => {
|
||||
cy.cs('ooditable-general').within(() => {
|
||||
cy.contains('522142')
|
||||
cy.contains('Tilastotiede')
|
||||
cy.contains('Matematiikka')
|
||||
cy.contains('Taloustieteen maisteriohjelma')
|
||||
cy.contains('Todistusvalinta')
|
||||
cy.contains('Saksa')
|
||||
cy.contains('Female')
|
||||
})
|
||||
})
|
||||
|
||||
it("'Courses tab' is usable", () => {
|
||||
cy.cs('student-table-tabs').within(() => {
|
||||
cy.contains('Courses').click()
|
||||
})
|
||||
cy.cs('ooditable-courses').within(() => {
|
||||
cy.contains('MAT12001')
|
||||
cy.contains('MAT21001')
|
||||
})
|
||||
})
|
||||
|
||||
it("'Modules tab' Displays correct modules based on the selected programme", () => {
|
||||
cy.cs('student-table-tabs').contains('Modules').click()
|
||||
cy.cs('ooditable-modules').within(() => {
|
||||
cy.contains('MAT011')
|
||||
cy.contains('MAT110')
|
||||
})
|
||||
cy.contains('Courses of class').click()
|
||||
cy.cs('curriculum-picker').click()
|
||||
cy.contains('2023–2026').click()
|
||||
cy.contains('Courses of class').click()
|
||||
cy.cs('ooditable-modules').within(() => {
|
||||
cy.contains('MAT011').should('not.exist')
|
||||
cy.contains('MAT110')
|
||||
})
|
||||
})
|
||||
|
||||
it("Empty 'tags' tab has a link to the page where tags can be created", () => {
|
||||
cy.cs('student-table-tabs').within(() => {
|
||||
cy.contains('Tags').click()
|
||||
})
|
||||
cy.contains('No tags defined. You can define them here.').find('a').click()
|
||||
cy.url().should('include', '/study-programme/KH50_001?tab=4')
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma')
|
||||
cy.contains('Create new tag')
|
||||
cy.cs('create-button').should('be.disabled')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('When using admin', () => {
|
||||
it('Student list checking works as intended', () => {
|
||||
cy.init(pathToMathBSc2020, 'admin')
|
||||
const existing = '433237'
|
||||
const nonExisting = '550004'
|
||||
cy.contains('Students (27)')
|
||||
.parent()
|
||||
.then($parentDiv => {
|
||||
if (!$parentDiv.hasClass('active')) cy.contains('Students (27)').click()
|
||||
})
|
||||
cy.contains(existing)
|
||||
cy.contains(nonExisting).should('not.exist')
|
||||
cy.contains('button', 'Check student numbers').click()
|
||||
cy.contains('Check for student numbers')
|
||||
cy.cs('check-student-numbers').type(`${existing}{enter}${nonExisting}`)
|
||||
cy.contains('button', 'Check students').click()
|
||||
cy.get('#checkstudentsresults').within(() => {
|
||||
cy.cs('found-title').click()
|
||||
cy.cs('found-data').contains(existing)
|
||||
cy.cs('not-found-title').click()
|
||||
cy.cs('not-found-data').contains(nonExisting)
|
||||
cy.cs('not-searched-title').click()
|
||||
cy.cs('not-searched-data').contains('457144')
|
||||
})
|
||||
cy.contains('button', 'Close').click()
|
||||
cy.contains('Student numbers in list and in Sisu').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('When using IAM user', () => {
|
||||
beforeEach(() => {
|
||||
cy.init(pathToMathBSc2020, 'onlyiamrights')
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma')
|
||||
cy.contains('Class of 2020 - 2021, 30 students')
|
||||
})
|
||||
|
||||
it('Population statistics is visible', () => {
|
||||
cy.cs('PopulationQueryCard').within(() => {
|
||||
cy.contains('Excludes exchange students')
|
||||
cy.contains('Excludes students with non-degree study right')
|
||||
cy.contains('Excludes students who have transferred out of this programme')
|
||||
})
|
||||
})
|
||||
|
||||
it('Only correct panels are visible', () => {
|
||||
cy.cs('panelview-parent').within(() => {
|
||||
cy.cs('Credit accumulation (for 27 students)')
|
||||
cy.cs('Credit statistics')
|
||||
cy.cs('Age distribution')
|
||||
cy.cs('Courses of class')
|
||||
})
|
||||
})
|
||||
|
||||
it('Ages cannot be ungrouped', () => {
|
||||
cy.contains('Age distribution')
|
||||
.parent()
|
||||
.then($parentDiv => {
|
||||
if (!$parentDiv.hasClass('active')) cy.contains('Age distribution').click()
|
||||
})
|
||||
cy.contains('ui.checked.toggle.checkbox', 'Group ages').should('not.exist')
|
||||
})
|
||||
|
||||
it('Age filter is not visible', () => {
|
||||
cy.get("[data-cy='filtered-students']")
|
||||
cy.get("[data-cy='Age-filter-card']").should('not.exist')
|
||||
})
|
||||
|
||||
it('Students tab is not available', () => {
|
||||
cy.contains('Students (27)').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,85 +0,0 @@
|
||||
import { userHeaders } from '../support/commands.js'
|
||||
|
||||
const getBaseRoutes = [
|
||||
['/', {}],
|
||||
['/changelog', {}],
|
||||
['/completedcoursessearch', {}],
|
||||
['/university', {}],
|
||||
['/feedback', {}],
|
||||
['/populations', { roles: ['fullSisuAccess'], programmeRights: [] }],
|
||||
['/study-programme', { roles: ['fullSisuAccess'], programmeRights: [] }],
|
||||
['/study-programme/KH50_001', { roles: ['fullSisuAccess'], programmeRights: ['KH50_001'] }],
|
||||
['/coursepopulation', { roles: ['fullSisuAccess'], programmeRights: [] }],
|
||||
['/users', { roles: ['admin'] }],
|
||||
['/users/334', { roles: ['admin'] }],
|
||||
['/updater', { roles: ['admin'] }],
|
||||
['/coursestatistics', { roles: ['fullSisuAccess', 'courseStatistics'], programmeRights: [] }],
|
||||
['/faculties', { roles: ['fullSisuAccess', 'facultyStatistics'] }],
|
||||
['/faculties/hy-org-1000000911', { roles: ['fullSisuAccess', 'facultyStatistics'] }],
|
||||
['/students', { roles: ['fullSisuAccess', 'studyGuidanceGroups'], programmeRights: [] }],
|
||||
['/students/545400', { roles: ['fullSisuAccess', 'studyGuidanceGroups'], programmeRights: [] }],
|
||||
['/custompopulation', { roles: ['fullSisuAccess', 'studyGuidanceGroups'], programmeRights: [] }],
|
||||
['/teachers', { roles: ['teachers'] }],
|
||||
['/teachers/hy-hlo-1463447', { roles: ['teachers'] }],
|
||||
['/studyguidancegroups', { roles: ['studyGuidanceGroups'] }],
|
||||
['/studyguidancegroups/otm-b3b52ff5-88f6-4d52-bd18-0588023b6322', { userId: '', roles: ['studyGuidanceGroups'] }],
|
||||
['/close-to-graduation', { roles: ['fullSisuAccess', 'studyGuidanceGroups'] }],
|
||||
['/languagecenterview', { iamGroups: ['grp-kielikeskus-esihenkilot'] }],
|
||||
]
|
||||
|
||||
for (const user of userHeaders) {
|
||||
if (user.uid === 'admin') continue
|
||||
describe(`${user.displayname} has access only to views that were intended`, () => {
|
||||
let userInfo
|
||||
before(() => {
|
||||
cy.request({ method: 'GET', url: '/api/login', headers: user }).then(({ body }) => (userInfo = body?.user))
|
||||
})
|
||||
|
||||
beforeEach(() => cy.wrap(userInfo).should('not.be.undefined'))
|
||||
beforeEach(() => {
|
||||
cy.intercept('**/api/**', req => {
|
||||
req.on('response', res => {
|
||||
expect(res.statusCode, `${req.method} ${req.url}`).to.be.lessThan(500)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
for (const [route, requirements] of getBaseRoutes) {
|
||||
it(`Checking access ${route}`, () => {
|
||||
cy.init(route, user.uid)
|
||||
|
||||
const requiredUserId = !requirements.userId || requirements.userId === userInfo.userId
|
||||
|
||||
const requiredRoles = !requirements.roles || requirements.roles?.some(role => userInfo.roles?.includes(role))
|
||||
|
||||
const requiredRights =
|
||||
!requirements.requireProgrammeRights ||
|
||||
userInfo.roles?.includes('fullSisuAccess') ||
|
||||
requirements.programmeRights.every(role => userInfo.programmeRights?.includes(role))
|
||||
|
||||
// This is defined in frontend ProtectedRoute component.
|
||||
const specialNeedsRoutes = [
|
||||
'populations',
|
||||
'study-programme',
|
||||
'coursepopulation',
|
||||
'coursestatistics',
|
||||
'students',
|
||||
'custompopulation',
|
||||
]
|
||||
|
||||
const mankeli = specialNeedsRoutes.some(path => route.includes(path))
|
||||
? requiredRoles || requiredRights
|
||||
: requiredRoles && requiredRights
|
||||
|
||||
const shouldHaveAccess = mankeli && requiredUserId
|
||||
|
||||
if (shouldHaveAccess) {
|
||||
cy.contains('Something broke').should('not.exist')
|
||||
cy.contains('Access denied').should('not.exist')
|
||||
} else {
|
||||
cy.contains('Access denied')
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,294 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
const student = {
|
||||
firstNames: 'Varpu Roope',
|
||||
lastName: 'Mårtensson',
|
||||
studentNumber: '550003',
|
||||
sisPersonId: 'hy-hlo-115926826',
|
||||
email: 'sisutestidata134902@testisisudata.fi',
|
||||
}
|
||||
|
||||
const typeToSearch = text => {
|
||||
cy.cs('student-search').type(text)
|
||||
}
|
||||
|
||||
const typeStudentNumberAndClick = studentNumber => {
|
||||
typeToSearch(studentNumber)
|
||||
cy.contains('td', studentNumber).click()
|
||||
}
|
||||
|
||||
describe('Students tests', () => {
|
||||
describe('When using basic user', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('')
|
||||
cy.contains('Students').click()
|
||||
cy.url().should('include', '/students')
|
||||
cy.contains('Show student names')
|
||||
})
|
||||
|
||||
// FIXME: Flaky
|
||||
it('Students search form is usable', () => {
|
||||
typeToSearch(student.lastName)
|
||||
cy.contains('Student number')
|
||||
cy.contains('Last name').should('not.exist')
|
||||
cy.contains('First names').should('not.exist')
|
||||
cy.contains('Started')
|
||||
cy.contains('Credits')
|
||||
cy.contains('Active study rights')
|
||||
cy.contains(student.firstNames).should('not.exist')
|
||||
cy.contains(student.lastName).should('not.exist')
|
||||
|
||||
cy.cs('toggleStudentNames').click()
|
||||
cy.contains(student.firstNames)
|
||||
cy.contains('Student number')
|
||||
cy.contains('Last name')
|
||||
cy.contains('First names')
|
||||
cy.contains('Started')
|
||||
cy.contains('Credits')
|
||||
cy.contains('Active study rights')
|
||||
cy.contains(student.firstNames)
|
||||
cy.contains(student.lastName)
|
||||
|
||||
cy.cs('toggleStudentNames').click()
|
||||
cy.contains('Student number')
|
||||
cy.contains('Last name').should('not.exist')
|
||||
cy.contains('First names').should('not.exist')
|
||||
cy.contains('Started')
|
||||
cy.contains('Credits')
|
||||
cy.contains('Active study rights')
|
||||
cy.contains(student.firstNames).should('not.exist')
|
||||
cy.contains(student.lastName).should('not.exist')
|
||||
})
|
||||
|
||||
it('Search term must be at least 4 characters long', () => {
|
||||
typeToSearch(student.lastName.slice(0, 3))
|
||||
cy.contains('Search term is not accurate enough')
|
||||
typeToSearch(student.lastName.slice(3))
|
||||
cy.get('table tbody tr').should('have.length', 1)
|
||||
})
|
||||
|
||||
it('Can search with student number too', () => {
|
||||
typeToSearch(student.studentNumber)
|
||||
cy.contains(student.studentNumber)
|
||||
})
|
||||
|
||||
it('Can get student specific page by clicking student', () => {
|
||||
typeStudentNumberAndClick(student.studentNumber)
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma (01.08.2020–31.07.2027)')
|
||||
cy.contains(student.lastName).should('not.exist')
|
||||
cy.contains(student.firstNames).should('not.exist')
|
||||
cy.contains(student.email).should('not.exist')
|
||||
|
||||
cy.cs('toggleStudentNames').click()
|
||||
cy.contains(student.lastName)
|
||||
cy.contains(student.firstNames)
|
||||
cy.contains(student.email)
|
||||
|
||||
cy.cs('toggleStudentNames').click()
|
||||
cy.contains(student.lastName).should('not.exist')
|
||||
cy.contains(student.firstNames).should('not.exist')
|
||||
cy.contains(student.email).should('not.exist')
|
||||
})
|
||||
|
||||
it("'Update student' button is not shown", () => {
|
||||
typeStudentNumberAndClick(student.studentNumber)
|
||||
cy.cs('student-info-card').within(() => {
|
||||
cy.contains('button', 'Update student').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
it('Can get back to search menu', () => {
|
||||
typeStudentNumberAndClick(student.studentNumber)
|
||||
cy.go('back')
|
||||
cy.contains('Student number').should('not.exist')
|
||||
cy.contains('Credits').should('not.exist')
|
||||
})
|
||||
|
||||
it('Can jump to course', () => {
|
||||
typeStudentNumberAndClick(student.studentNumber)
|
||||
cy.contains('Tilastollinen päättely I (MAT12004)')
|
||||
.parent()
|
||||
.siblings()
|
||||
.last()
|
||||
.within(() => {
|
||||
cy.get('a').click()
|
||||
})
|
||||
cy.url().should('include', '/coursestatistics')
|
||||
cy.contains('MAT12004') // Tilastollinen päättely I
|
||||
cy.contains('AYMAT12004') // Avoin yo: Tilastollinen päättely I
|
||||
cy.contains('57046') // Johdatus tilastolliseen päättelyyn
|
||||
})
|
||||
|
||||
it('Has correct Sisu link', () => {
|
||||
typeStudentNumberAndClick(student.studentNumber)
|
||||
cy.cs('sisu-link')
|
||||
.should('have.attr', 'href')
|
||||
.and('include', `https://sisu.helsinki.fi/tutor/role/staff/student/${student.sisPersonId}/basic/basic-info`)
|
||||
})
|
||||
|
||||
it('Semester enrollments can be toggled', () => {
|
||||
typeStudentNumberAndClick(student.studentNumber)
|
||||
const programmes = [
|
||||
'Oikeustieteen tohtoriohjelma',
|
||||
'Matemaattisten tieteiden kandiohjelma',
|
||||
'Oikeustieteen maisterin koulutusohjelmaOikeusnotaarin koulutusohjelma',
|
||||
]
|
||||
cy.cs('student-info-card').within(() => {
|
||||
cy.contains('Enrollments').click()
|
||||
cy.get('table tbody tr')
|
||||
.should('have.length', 3)
|
||||
.each(($tr, index) => {
|
||||
cy.wrap($tr).within(() => {
|
||||
cy.get('td').eq(0).should('have.text', programmes[index])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("Searching with bad name doesn't yield results", () => {
|
||||
typeToSearch('SWAG LITTINEN')
|
||||
cy.contains('Student number').should('not.exist')
|
||||
})
|
||||
|
||||
it("Searching with bad student number doesn't yield results", () => {
|
||||
typeToSearch('01114')
|
||||
cy.contains('Student number').should('not.exist')
|
||||
})
|
||||
|
||||
it('Can jump to population page', () => {
|
||||
typeStudentNumberAndClick(student.studentNumber)
|
||||
cy.cs('study-rights-section').within(() => {
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma')
|
||||
.parent()
|
||||
.within(() => cy.get('a').click())
|
||||
})
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma')
|
||||
cy.contains('Class of 2020 - 2021, 30 students')
|
||||
})
|
||||
|
||||
it('Grade graph works in all three different modes', () => {
|
||||
typeStudentNumberAndClick(student.studentNumber)
|
||||
cy.contains('button', 'Grade graph').click()
|
||||
cy.contains('button', 'Show group mean').click()
|
||||
cy.cs('group-size-input').within(() => {
|
||||
cy.contains('label', 'Group size')
|
||||
cy.get('input').should('have.value', '5')
|
||||
})
|
||||
cy.cs('group-size-input').within(() => {
|
||||
cy.contains('label', 'Group size')
|
||||
cy.get('input').clear()
|
||||
cy.get('input').type('10')
|
||||
cy.get('input').should('have.value', '10')
|
||||
})
|
||||
cy.contains('button', 'Show semester mean').click()
|
||||
})
|
||||
|
||||
describe('Bachelor Honours section', () => {
|
||||
it("Shows 'Qualified for Honours' tag and main modules info when the student is qualified", () => {
|
||||
cy.visit('/students/495976')
|
||||
cy.contains('h2', 'Bachelor Honours')
|
||||
cy.contains('[data-cy=honours-chip-qualified]', 'Qualified for Honours')
|
||||
cy.contains('Study modules').click()
|
||||
cy.get('[data-cy=main-modules] tbody tr')
|
||||
.should('have.length', 3)
|
||||
.each(($tr, index) => {
|
||||
const info = [
|
||||
['07.05.2020', 'Matemaattisten tieteiden kandiohjelma (KH50_001)', 'Hyv.'],
|
||||
['08.05.2018', 'Matematiikka, perusopinnot (MAT110)', '4'],
|
||||
['25.02.2020', 'Matematiikka, aineopinnot (MAT210)', '4'],
|
||||
]
|
||||
cy.wrap($tr).within(() => {
|
||||
info[index].forEach((text, i) => {
|
||||
cy.get('td').eq(i).contains(text)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it("Shows 'Did not graduate in time' when the student has graduated but not in time", () => {
|
||||
cy.visit('/students/540355')
|
||||
cy.contains('h2', 'Bachelor Honours')
|
||||
cy.contains('[data-cy=honours-chip-not-qualified]', 'Not qualified for Honours')
|
||||
cy.contains('[data-cy=honours-chip-error]', 'Did not graduate in time')
|
||||
})
|
||||
|
||||
it("Shows 'Module grades too low' when the student has graduated in time but has too low grades", () => {
|
||||
cy.visit('/students/547934')
|
||||
cy.contains('h2', 'Bachelor Honours')
|
||||
cy.contains('[data-cy=honours-chip-not-qualified]', 'Not qualified for Honours')
|
||||
cy.contains('[data-cy=honours-chip-error]', 'Module grades too low')
|
||||
})
|
||||
|
||||
it("Shows 'Might need further inspection' when the student has graduated in time but has more than four main modules", () => {
|
||||
cy.visit('/students/478837')
|
||||
cy.contains('h2', 'Bachelor Honours')
|
||||
cy.contains('[data-cy=honours-chip-inspection]', 'Might need further inspection')
|
||||
})
|
||||
|
||||
it("Shows 'Has not graduated' when the student has not graduated", () => {
|
||||
cy.visit(`students/${student.studentNumber}`)
|
||||
cy.contains('h2', 'Bachelor Honours')
|
||||
cy.contains('[data-cy=honours-chip-not-qualified]', 'Not qualified for Honours')
|
||||
cy.contains('[data-cy=honours-chip-error]', 'Has not graduated')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Use admin to see all students
|
||||
describe('When using admin user', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/students', 'admin')
|
||||
})
|
||||
|
||||
it('Does not crash if student has no study rights or courses', () => {
|
||||
typeStudentNumberAndClick('450730')
|
||||
cy.contains('Credits: 0')
|
||||
})
|
||||
|
||||
it("'Update student' button is shown", () => {
|
||||
typeStudentNumberAndClick(student.studentNumber)
|
||||
cy.cs('student-info-card').within(() => {
|
||||
cy.contains('button', 'Update student')
|
||||
})
|
||||
})
|
||||
|
||||
it('Bachelor Honours section is not shown for students outside of Faculty of Science', () => {
|
||||
cy.visit('/students/453146')
|
||||
cy.contains('h2', 'Bachelor Honours').should('not.exist')
|
||||
})
|
||||
|
||||
it('When a study plan is selected, courses included in the study plan are highlighted with a blue background', () => {
|
||||
cy.visit('/students/550789')
|
||||
cy.contains('Study rights')
|
||||
cy.get('[data-cy=KH40_005-0]').contains('Kulttuurien tutkimuksen kandiohjelma')
|
||||
cy.get('[data-cy=KH40_005-0]').within(() => {
|
||||
cy.get('td').eq(1).click()
|
||||
})
|
||||
cy.contains('table tbody tr', 'Kandidaatintutkielma (KUKA-LIS222)').should(
|
||||
'have.css',
|
||||
'background-color',
|
||||
'rgb(232, 244, 255)'
|
||||
)
|
||||
})
|
||||
|
||||
it("If there's a study plan corresponding to the degree programme, completed credits are displayed", () => {
|
||||
cy.visit('/students/550789')
|
||||
cy.contains('Study rights')
|
||||
cy.get('[data-cy=KH40_005-0]').contains('Kulttuurien tutkimuksen kandiohjelma')
|
||||
cy.get('[data-cy=KH40_005-0]').within(() => {
|
||||
cy.get('td')
|
||||
.eq(4)
|
||||
.contains(/^185 cr$/)
|
||||
})
|
||||
})
|
||||
|
||||
it("If there's a study plan corresponding to the degree programme and the student hasn't graduated, percentage of completion is also displayed", () => {
|
||||
cy.visit('/students/458723')
|
||||
cy.contains('Study rights')
|
||||
cy.get('[data-cy=KH20_001-0]').contains('Oikeusnotaarin koulutusohjelma')
|
||||
cy.get('[data-cy=KH20_001-0]').within(() => {
|
||||
cy.get('td').eq(4).contains('69% (125 cr)')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,164 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
describe('Study guidance group tests', () => {
|
||||
describe('Study guidance group overview page', () => {
|
||||
describe('without study guidance groups', () => {
|
||||
it('shows the correct notification', () => {
|
||||
cy.init('/studyguidancegroups', 'admin')
|
||||
cy.contains('Study guidance groups')
|
||||
cy.contains('You do not have access to any study guidance groups.')
|
||||
})
|
||||
})
|
||||
|
||||
describe('without correct rights', () => {
|
||||
it('shows the correct notification', () => {
|
||||
cy.init('/studyguidancegroups')
|
||||
cy.contains('Access denied')
|
||||
cy.contains(
|
||||
"You don't currently have permission to view this page. If you believe this is a mistake, please contact oodikone@helsinki.fi."
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with study guidance groups', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/studyguidancegroups', 'onlystudyguidancegroups')
|
||||
cy.intercept('/api/studyguidancegroups', { fixture: 'studyGuidanceGroups.json' })
|
||||
})
|
||||
|
||||
it('shows the correct data', () => {
|
||||
cy.contains('Study guidance groups')
|
||||
|
||||
const studyGuidanceGroupsTableContent = [
|
||||
['MAT kandit 2020', 3, 'Matemaattisten tieteiden kandiohjelma', '2020 - 2021'],
|
||||
['Oma ohjausryhmä', 2, 'Add degree programme', 'Add starting year'],
|
||||
]
|
||||
|
||||
cy.checkTableStats(studyGuidanceGroupsTableContent, 'study-guidance-group-overview')
|
||||
})
|
||||
|
||||
it('has working links to single study guidance groups', () => {
|
||||
cy.cs('study-guidance-group-link-sgg-cypress-1').click()
|
||||
cy.url().should('eq', `${Cypress.config().baseUrl}/studyguidancegroups/sgg-cypress-1`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Page for single study guidance group', () => {
|
||||
beforeEach(() => {
|
||||
cy.intercept('/api/studyguidancegroups', { fixture: 'studyGuidanceGroups.json' })
|
||||
})
|
||||
|
||||
it('has a working back button', () => {
|
||||
cy.init('/studyguidancegroups/sgg-cypress-1', 'onlystudyguidancegroups')
|
||||
|
||||
cy.get('button').contains('Back to groups').click()
|
||||
cy.url().should('eq', `${Cypress.config().baseUrl}/studyguidancegroups`)
|
||||
})
|
||||
|
||||
describe('without associated degree programme and year', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/studyguidancegroups/sgg-cypress-2', 'onlystudyguidancegroups')
|
||||
})
|
||||
|
||||
it('shows the correct panes', () => {
|
||||
cy.contains('Oma ohjausryhmä')
|
||||
cy.cs('Credit accumulation (for 2 students)')
|
||||
cy.cs('Age distribution')
|
||||
cy.cs('Courses of population')
|
||||
cy.contains('Students (2)')
|
||||
cy.cs('Credit statistics').should('not.exist')
|
||||
})
|
||||
|
||||
it.skip('students table has the correct tabs', () => {
|
||||
cy.contains('Students (2)').click()
|
||||
cy.get('[data-cy="student-table-tabs"] .ui.attached.tabular.menu').then($menu => {
|
||||
const tabNames = Array.from($menu[0].children).map(elem => elem.innerText)
|
||||
expect(tabNames).to.deep.equal(['General'])
|
||||
})
|
||||
})
|
||||
|
||||
it.skip('general tab of the students table has the correct columns', () => {
|
||||
const colHeaders = [
|
||||
'Student number',
|
||||
'All credits',
|
||||
'Credits since 1.1.1970',
|
||||
'Start year at uni',
|
||||
'Degree programmes',
|
||||
'Tags',
|
||||
]
|
||||
cy.contains('Students (2)').click()
|
||||
cy.get('[data-cy="student-table-tabs"] table thead tr').within(() => {
|
||||
colHeaders.every(heading => cy.contains(heading))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with associated degree programme and year', () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/studyguidancegroups/sgg-cypress-1', 'onlystudyguidancegroups')
|
||||
})
|
||||
|
||||
it('shows the correct labels', () => {
|
||||
cy.get('h4').contains('MAT kandit 2020')
|
||||
cy.get('.MuiChip-root:first').contains('Matemaattisten tieteiden kandiohjelma')
|
||||
cy.get('.MuiChip-root:last').contains('2020 - 2021')
|
||||
})
|
||||
|
||||
it('shows the correct panes', () => {
|
||||
cy.cs('Credit accumulation (for 3 students)')
|
||||
cy.cs('Credit statistics')
|
||||
cy.cs('Age distribution')
|
||||
cy.cs('Courses of population')
|
||||
cy.contains('Students (3)')
|
||||
})
|
||||
|
||||
it("clicking the 'Show credits starting from the associated academic year' filter", () => {
|
||||
cy.get('[data-cy="ParticipationDate-filter-card"][data-active="false"]')
|
||||
cy.cs('Credit accumulation (for 3 students)').click()
|
||||
cy.get('label').contains('Show credits starting from the associated academic year').click()
|
||||
cy.get('[data-cy="ParticipationDate-filter-card"][data-active="true"]')
|
||||
cy.get('.date-picker')
|
||||
.eq(0)
|
||||
.within(() => cy.get('input').should('have.value', '01.08.2020'))
|
||||
cy.contains('Reset All Filters')
|
||||
cy.get('label').contains('Show credits starting from the associated academic year').click()
|
||||
cy.get('[data-cy="ParticipationDate-filter-card"][data-active="false"]')
|
||||
})
|
||||
|
||||
it.skip('students table has the correct tabs', () => {
|
||||
cy.contains('Students (3)').click()
|
||||
cy.get('[data-cy="student-table-tabs"] .ui.attached.tabular.menu').then($menu => {
|
||||
const tabNames = Array.from($menu[0].children).map(elem => elem.innerText)
|
||||
expect(tabNames).to.deep.equal(['General', 'Courses', 'Modules', 'Progress'])
|
||||
})
|
||||
})
|
||||
|
||||
it.skip('general tab of the students table has the correct columns', () => {
|
||||
const colHeaders = [
|
||||
'Student number',
|
||||
'All credits',
|
||||
'Credits in HOPS',
|
||||
'Credits since 1.8.2020',
|
||||
'Start of study right',
|
||||
'Started in programme',
|
||||
'Semesters present',
|
||||
'Graduation date',
|
||||
'Start year at uni',
|
||||
'Other programmes',
|
||||
'Transferred from',
|
||||
'Admission type',
|
||||
'Gender',
|
||||
'Citizenships',
|
||||
'Curriculum period',
|
||||
'Latest attainment date',
|
||||
'Tags',
|
||||
]
|
||||
cy.contains('Students (3)').click()
|
||||
cy.get('[data-cy="student-table-tabs"] table thead tr').within(() => {
|
||||
colHeaders.every(heading => cy.contains(heading))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,64 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
describe('Teachers page tests', () => {
|
||||
beforeEach(() => {
|
||||
// login as admin = has teacher rights
|
||||
cy.init('/teachers', 'admin')
|
||||
cy.url().should('include', '/teachers')
|
||||
})
|
||||
|
||||
const teacher1 = 'Luokkanen Liisa Viljami'
|
||||
const teacher2 = 'Perälä Juhani Susanna'
|
||||
|
||||
const statisticsHeaders = ['Name', 'Credits', 'Credits transferred', 'Passed']
|
||||
|
||||
it('Check Statistics', () => {
|
||||
cy.cs('semester-start').click()
|
||||
cy.contains('Syksy 2020').click()
|
||||
cy.cs('course-providers').click()
|
||||
cy.contains('Matemaattisten tieteiden kandiohjelma').click()
|
||||
cy.get('body').click(0, 0) // Click outside of the select
|
||||
cy.cs('search-statistics').click()
|
||||
|
||||
cy.contains('Teacher')
|
||||
cy.get('table thead tr th').should('have.length', 4)
|
||||
statisticsHeaders.forEach((header, index) => {
|
||||
cy.get('table thead tr th').eq(index).should('contain', header)
|
||||
})
|
||||
cy.contains('td', teacher1).siblings().eq(0).contains('235')
|
||||
cy.contains('td', teacher1).siblings().eq(2).contains('97.40%')
|
||||
cy.contains('td', teacher2).siblings().eq(0).contains('395')
|
||||
cy.contains('td', teacher2).siblings().eq(2).contains('98.78%')
|
||||
})
|
||||
|
||||
it('Teacher search works', () => {
|
||||
cy.cs('Search').click()
|
||||
cy.cs('teacher-search').type(teacher1.split(' ')[0])
|
||||
cy.get('table tbody tr').should('have.length', 4)
|
||||
cy.get('table tbody tr').eq(2).contains('td', teacher1)
|
||||
})
|
||||
|
||||
it('Can check teacher page', () => {
|
||||
cy.cs('Search').click()
|
||||
cy.cs('teacher-search').type(teacher2)
|
||||
|
||||
// Prevent opening in new tab
|
||||
cy.contains('a', teacher2).invoke('removeAttr', 'target').click()
|
||||
cy.url().should('include', '/teachers/hy-hlo-49026530')
|
||||
cy.contains(teacher2)
|
||||
cy.contains('Syksy 2023').click()
|
||||
cy.contains('Kevät 2019').click()
|
||||
cy.contains('tr', 'MAT12004').within(() => {
|
||||
const rowContent = ['MAT12004', 'Tilastollinen päättely I', '120', '0', '92.31%']
|
||||
rowContent.forEach((content, index) => {
|
||||
cy.get('td').eq(index).contains(content)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('Check leaderboad works', () => {
|
||||
cy.cs('Leaderboard').click()
|
||||
cy.cs('academic-year').click()
|
||||
cy.contains('2020-2021').click()
|
||||
})
|
||||
})
|
||||
@@ -1,101 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
const progressLevels = ['bachelors', 'bachelor-masters', 'masters', 'doctoral']
|
||||
|
||||
const checkProgressBarCharts = () => {
|
||||
progressLevels.forEach(level => cy.cs(`faculty-${level}-progress-bar-chart-section`))
|
||||
}
|
||||
|
||||
const checkProgressTables = () => {
|
||||
progressLevels.forEach(level => cy.cs(`${level}-faculty-progress-table`))
|
||||
}
|
||||
|
||||
const graduationTimesLevels = ['bachelor', 'bcMsCombo', 'master', 'doctor']
|
||||
|
||||
const checkGraduationCharts = mode => {
|
||||
graduationTimesLevels.forEach(level => {
|
||||
cy.cs(`${level}-${mode}-bar-chart`).within(() => {
|
||||
// Check that bar has loaded
|
||||
cy.contains('Loading content').should('not.exist')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
describe('University view', { defaultCommandTimeout: 60 * 1000 }, () => {
|
||||
beforeEach(() => {
|
||||
cy.init('/university')
|
||||
cy.contains('University')
|
||||
})
|
||||
|
||||
describe('Faculty progress tab', () => {
|
||||
it('contains all the correct progress bar charts', () => {
|
||||
checkProgressBarCharts()
|
||||
})
|
||||
|
||||
it('contains all the correct progress tables', () => {
|
||||
checkProgressTables()
|
||||
})
|
||||
|
||||
it("'All study rights / Special study rights excluded' toggle works", () => {
|
||||
cy.cs('study-right-toggle').click()
|
||||
checkProgressBarCharts()
|
||||
checkProgressTables()
|
||||
})
|
||||
|
||||
// Nothing in this test is explained. Non of these values are verified.
|
||||
it.skip('years in the tables can be clicked to show faculty level breakdown', () => {
|
||||
cy.cs('study-right-toggle').click()
|
||||
cy.cs('bachelors-faculty-progress-table-show-button3').click()
|
||||
cy.contains('29.5%').hover()
|
||||
cy.contains('Matemaattis-luonnontieteellinen tiedekunta')
|
||||
cy.contains('H50')
|
||||
cy.contains('0 Credits: 0')
|
||||
cy.contains('1 ≤ Credits < 45: 13')
|
||||
cy.contains('45 ≤ Credits < 90: 10')
|
||||
cy.contains('90 ≤ Credits < 135: 16')
|
||||
cy.contains('135 ≤ Credits < 180: 3')
|
||||
cy.contains('180 ≤ Credits: 2')
|
||||
})
|
||||
|
||||
it('info boxes contain correct information', () => {
|
||||
cy.cs('faculty-progress-info-box-button').click()
|
||||
cy.cs('faculty-progress-info-box-content').contains('Kuvaa tiedekuntaan kuuluvien')
|
||||
cy.cs('faculty-bachelor-masters-progress-info-box-button').click()
|
||||
cy.cs('faculty-bachelor-masters-progress-info-box-content').contains('The starting year is the')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Faculty graduations tab', () => {
|
||||
beforeEach(() => {
|
||||
cy.cs('faculty-graduations-tab').click()
|
||||
})
|
||||
|
||||
describe('Different modes work', () => {
|
||||
it('Breakdown', () => {
|
||||
cy.cs('graduation-mode-selector').within(() => {
|
||||
cy.cs('select-breakdown').click()
|
||||
})
|
||||
checkGraduationCharts('breakdown')
|
||||
})
|
||||
|
||||
it('Median', () => {
|
||||
cy.cs('graduation-mode-selector').within(() => {
|
||||
cy.cs('select-median').click()
|
||||
})
|
||||
checkGraduationCharts('median')
|
||||
})
|
||||
|
||||
it('Average', () => {
|
||||
cy.cs('graduation-mode-selector').within(() => {
|
||||
cy.cs('select-average').click()
|
||||
})
|
||||
checkGraduationCharts('average')
|
||||
})
|
||||
})
|
||||
|
||||
it('info boxes contain correct information', () => {
|
||||
cy.cs('average-graduation-times-info-box-button').hover()
|
||||
cy.cs('average-graduation-times-info-box-content').contains('Opiskelijoiden keskimääräiset valmistumisajat')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"studentSet1": ["433237", "457144", "458090", "474270", "479440"],
|
||||
"coursesSet1": ["TKT10001", "TKT10002", "TKT10003", "TKT10004"]
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"studentNumbersForCSStudentsSet1": ["433237", "457144", "458090", "465136"],
|
||||
"studentNumbersForCSStudentsSet2": ["474270", "479440", "470391", "474789"]
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"courseCodesSet1": ["TKT10001", "TKT10002"],
|
||||
"courseCodesSet2": ["TKT10003", "TKT10004", "TKT10005"]
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": "sgg-cypress-1",
|
||||
"name": {
|
||||
"fi": "MAT kandit 2020"
|
||||
},
|
||||
"members": [
|
||||
{ "personStudentNumber": "433237" },
|
||||
{ "personStudentNumber": "457144" },
|
||||
{ "personStudentNumber": "458090" }
|
||||
],
|
||||
"tags": {
|
||||
"studyProgramme": "KH50_001",
|
||||
"year": "2020"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "sgg-cypress-2",
|
||||
"name": {
|
||||
"fi": "Oma ohjausryhmä"
|
||||
},
|
||||
"members": [{ "personStudentNumber": "474270" }, { "personStudentNumber": "479440" }],
|
||||
"tags": {
|
||||
"studyProgramme": null,
|
||||
"year": null
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,34 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
on('before:browser:launch', (browser = {}, launchOptions) => {
|
||||
// By manually setting the browser width and height in headless
|
||||
// mode, screenshots and videos will have a better quality
|
||||
// https://www.cypress.io/blog/generate-high-resolution-videos-and-screenshots
|
||||
const width = 2560
|
||||
const height = 1440
|
||||
|
||||
if (browser.name === 'chrome' && browser.isHeadless) {
|
||||
launchOptions.args.push(`--window-size=${width},${height}`)
|
||||
launchOptions.args.push('--force-device-scale-factor=1')
|
||||
}
|
||||
return launchOptions
|
||||
})
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
//
|
||||
// ! IMPORTANT: here we need to set keys to be all lowercase, since
|
||||
// ! we're replacing headers after they've left browser / frontend.
|
||||
// All of these users are available in anon user-db
|
||||
const adminUserHeaders = {
|
||||
uid: 'admin',
|
||||
displayname: 'Admin User',
|
||||
'shib-session-id': 'mock-cypress-session',
|
||||
hygroupcn: 'grp-oodikone-users;grp-oodikone-basic-users;grp-toska',
|
||||
mail: 'grp-toska+mockadminuser@helsinki.fi',
|
||||
hypersonsisuid: 'hy-hlo-6666666',
|
||||
}
|
||||
|
||||
const basicUserHeaders = {
|
||||
uid: 'basic',
|
||||
displayname: 'Basic User',
|
||||
'shib-session-id': 'mock-cypress-session',
|
||||
hygroupcn: 'grp-oodikone-users;grp-oodikone-basic-users',
|
||||
mail: 'grp-toska+mockbasicuser@helsinki.fi',
|
||||
hypersonsisuid: 'hy-hlo-1234567',
|
||||
}
|
||||
|
||||
const onlycoursestatisticsUserHeaders = {
|
||||
uid: 'onlycoursestatistics',
|
||||
displayname: 'Onlycoursestatistics User',
|
||||
'shib-session-id': 'mock-cypress-session',
|
||||
hygroupcn: 'grp-oodikone-basic-users',
|
||||
mail: 'grp-toska+mockonlycoursestatisticsuser@helsinki.fi',
|
||||
hypersonsisuid: 'hy-hlo-7654321',
|
||||
}
|
||||
|
||||
const norightsUserHeaders = {
|
||||
uid: 'norights',
|
||||
displayname: 'Norights User',
|
||||
'shib-session-id': 'mock-cypress-session',
|
||||
hygroupcn: 'grp-oodikone-users',
|
||||
mail: 'grp-toska+mocknorightuser@helsinki.fi',
|
||||
hypersonsisuid: 'hy-hlo-0000000',
|
||||
}
|
||||
|
||||
const onlyIamRightsUserHeaders = {
|
||||
uid: 'onlyiamrights',
|
||||
displayname: 'Only IAM rights user',
|
||||
'shib-session-id': 'mock-cypress-session',
|
||||
hygroupcn: 'hy-employees;hy-mltdk-mat-jory',
|
||||
mail: 'grp-toska+mockonlyiamrightsuser@helsinki.fi',
|
||||
hypersonsisuid: 'hy-hlo-1111111',
|
||||
}
|
||||
|
||||
// Also has element detail of "KH50_005" for the study guidance groups to work
|
||||
const onlyStudyGuidanceGroupsUser = {
|
||||
uid: 'onlystudyguidancegroups',
|
||||
displayname: 'Study Guidance Groups User',
|
||||
'shib-session-id': 'mock-cypress-session',
|
||||
hygroupcn: 'grp-oodikone-users',
|
||||
mail: 'grp-toska+mockonlystudyguidancegroupsuser@helsinki.fi',
|
||||
hypersonsisuid: 'hy-hlo-2222222',
|
||||
}
|
||||
|
||||
export const userHeaders = [
|
||||
adminUserHeaders,
|
||||
basicUserHeaders,
|
||||
onlycoursestatisticsUserHeaders,
|
||||
norightsUserHeaders,
|
||||
onlyIamRightsUserHeaders,
|
||||
onlyStudyGuidanceGroupsUser,
|
||||
]
|
||||
|
||||
/**
|
||||
* Set up headers to login, set up correct user (admin / basic / etc.) and open given path.
|
||||
*/
|
||||
Cypress.Commands.add('init', { prevSubject: false }, (path, userId = 'basic') => {
|
||||
const headersToUse = userHeaders.find(({ uid }) => uid === userId)
|
||||
if (!headersToUse) throw Error(`${userId} is not valid user id!`)
|
||||
|
||||
cy.intercept('*', req => {
|
||||
req.headers = headersToUse
|
||||
})
|
||||
|
||||
// TODO: Add wait for visit url.
|
||||
// This is block by course population query.
|
||||
cy.visit({ method: 'GET', url: path, headers: headersToUse })
|
||||
})
|
||||
|
||||
/**
|
||||
* Shorthand for using "Cypress Selectors" (CS), i.e., `data-cy` attributes.
|
||||
*/
|
||||
Cypress.Commands.add('cs', { prevSubject: 'optional' }, (subject, name) => {
|
||||
const selector = `[data-cy="${name}"]`
|
||||
|
||||
if (subject === undefined) {
|
||||
return cy.get(selector)
|
||||
}
|
||||
return cy.wrap(subject).find(selector)
|
||||
})
|
||||
|
||||
/**
|
||||
* Select item from FilterSelect dropdown.
|
||||
* If the index is a number, select index-th item.
|
||||
* Otherwise select the item containing index text.
|
||||
*/
|
||||
Cypress.Commands.add('selectFromDropdown', { prevSubject: false }, (label, index, isMultiSelect = false) => {
|
||||
cy.cs(`${label}-selector`).click()
|
||||
|
||||
cy.get(`[role="listbox"][aria-labelledby="${label}"]`).within(() => {
|
||||
if (typeof index === 'number') cy.get('li').eq(index).click()
|
||||
else cy.get('li').contains(index).click()
|
||||
})
|
||||
|
||||
if (isMultiSelect) cy.get('#menu- > .MuiModal-backdrop').click()
|
||||
})
|
||||
|
||||
/**
|
||||
* Select item from FilterSearchableSelect dropdown.
|
||||
* If the index is a number, select index-th item.
|
||||
* Otherwise select the item containing index text.
|
||||
*/
|
||||
Cypress.Commands.add('selectFromAutocomplete', { prevSubject: false }, (label, index) => {
|
||||
cy.cs(`${label}-selector`).click()
|
||||
cy.get(`#${label}-popper.MuiAutocomplete-popper [role="listbox"]`).within(() => {
|
||||
if (typeof index === 'number') cy.get('li').eq(index).click()
|
||||
else cy.get('li').contains(index).click()
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Set range selector values FilterRange.
|
||||
* If the reset flag is set, the function tries to reset the original values.
|
||||
*/
|
||||
Cypress.Commands.add('setRangeSelect', { prevSubject: false }, (filter, min, max, expected, reset) => {
|
||||
const minText = min.toString()
|
||||
const maxText = max.toString()
|
||||
const expectedText = expected.toString()
|
||||
|
||||
const parent = `${filter}-filter-card`
|
||||
|
||||
cy.cs(parent)
|
||||
.cs('FilterRangeStart')
|
||||
.find('input')
|
||||
.invoke('val')
|
||||
.then(initialMin => {
|
||||
cy.cs(parent)
|
||||
.cs('FilterRangeEnd')
|
||||
.find('input')
|
||||
.invoke('val')
|
||||
.then(initialMax => {
|
||||
cy.cs(parent).cs('FilterRangeStart').find('input').clear()
|
||||
cy.cs(parent).cs('FilterRangeStart').find('input').type(minText)
|
||||
cy.cs(parent).cs('FilterRangeEnd').find('input').clear()
|
||||
cy.cs(parent).cs('FilterRangeEnd').find('input').type(maxText)
|
||||
|
||||
// This should be linked to other checking functions.
|
||||
// Maybe one day.
|
||||
cy.contains(`Students (${expectedText})`)
|
||||
|
||||
if (reset) {
|
||||
cy.cs(parent).cs('FilterRangeStart').find('input').clear()
|
||||
cy.cs(parent).cs('FilterRangeStart').find('input').type(initialMin)
|
||||
cy.cs(parent).cs('FilterRangeEnd').find('input').clear()
|
||||
cy.cs(parent).cs('FilterRangeEnd').find('input')?.type(initialMax)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add('checkTableStats', (correctStats, tableName) => {
|
||||
cy.get(`[data-cy=${tableName}-data-table] tbody`).within(() => {
|
||||
correctStats.forEach((values, trIndex) => {
|
||||
cy.get('tr')
|
||||
.filter(':visible')
|
||||
.eq(trIndex)
|
||||
.within(() => {
|
||||
values.forEach((value, tdIndex) => {
|
||||
cy.get('td').eq(tdIndex).contains(value)
|
||||
})
|
||||
})
|
||||
})
|
||||
cy.get('tr').filter(':visible').should('have.length', correctStats.length)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Hover on the selected element.
|
||||
*/
|
||||
Cypress.Commands.add('hover', { prevSubject: 'element' }, (subject, options = {}) => {
|
||||
cy.wrap(subject).trigger('mouseover', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
...options,
|
||||
})
|
||||
|
||||
cy.wrap(subject).trigger('mousemove', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
...options,
|
||||
})
|
||||
})
|
||||
@@ -1,21 +0,0 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
require('./commands')
|
||||
|
||||
Cypress.on('uncaught:exception', error => {
|
||||
/* returning false here prevents Cypress from failing the test */
|
||||
return true
|
||||
})
|
||||
Generated
+8
-1268
File diff suppressed because it is too large
Load Diff
@@ -5,8 +5,6 @@
|
||||
"node": ">=24.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"cypress": "cypress",
|
||||
"cypress:run": "cypress run --browser firefox",
|
||||
"playwright": "playwright test -c playwright.config.ts",
|
||||
"playwright:ui": "playwright test --ui -c playwright.config.ts",
|
||||
"playwright:headed": "playwright test --headed -c playwright.config.ts",
|
||||
@@ -46,14 +44,9 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/UniversityOfHelsinkiCS/oodikone/issues"
|
||||
},
|
||||
"allowScripts": {
|
||||
"cypress": true
|
||||
},
|
||||
"homepage": "https://github.com/UniversityOfHelsinkiCS/oodikone#readme",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "1.61.0",
|
||||
"cypress": "15.18.1",
|
||||
"eslint-plugin-cypress": "^6.2.3",
|
||||
"eslint-plugin-import-x": "^4.16.1",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
|
||||
Reference in New Issue
Block a user