diff --git a/backend/authentication/views.py b/backend/authentication/views.py index 85af6b5a..f5745821 100644 --- a/backend/authentication/views.py +++ b/backend/authentication/views.py @@ -1,3 +1,5 @@ +from api.models.assistant import Assistant +from api.models.teacher import Teacher from django.http import HttpResponseRedirect from authentication.cas.client import client @@ -66,20 +68,23 @@ def echo(self, request: Request) -> Response: raise AuthenticationFailed(token_serializer.errors) -def create_user(self, request) -> Response: +def create_user(self, request, data) -> tuple[User, bool]: """General function to create a user, log them in and which returns an empty html page""" # log in user, or retrieve if they already exist - user, created = User.objects.get_or_create(id=settings.TEST_USER_DATA["id"], defaults=settings.TEST_USER_DATA) + user, created = User.objects.get_or_create(id=data["id"], defaults=data) # if it has just been created, send the signal to user_created Signal(), to also activate it as a student if created: - user_created.send(sender=self, attributes=settings.TEST_USER_ATTRIBUTES, user=user) + user_created.send(sender=self, attributes={**data, "ugentStudentID": data.id}, user=user) # login the user login(request, user) # return Response with empty html page - return Response('', + return user, created + + +response = Response('', status=HTTP_200_OK, headers={"Location": "/"}, content_type="text/html") @@ -88,14 +93,31 @@ class TestUser(ViewSet): permission_classes = [IsDebug] - @action(detail=False, methods=['GET'], permission_classes=[IsDebug], url_path='admin') - def login_admin(self, request, *__) -> Response: - """This endpoint lets you log in an admin""" - settings.TEST_USER_DATA["is_staff"] = True - return create_user(self, request) - - @action(detail=False, methods=['GET'], permission_classes=[IsDebug], url_path='student') + @action(detail=False, methods=['POST'], permission_classes=[IsDebug], url_path='student') def login_student(self, request, *__) -> Response: """This endpoint lets you log in as a student who's not an admin""" - settings.TEST_USER_DATA["is_staff"] = False - return create_user(self, request) + create_user(self, request, settings.TEST_STUDENT_DATA) + return response + + @action(detail=False, methods=['POST'], permission_classes=[IsDebug], url_path='professor') + def login_professor(self, request, *__) -> Response: + """This endpoint lets you log in as a professor""" + user, created = create_user(self, request, settings.TEST_PROFESSOR_DATA) + if created: + Teacher.create(user) + return response + + @action(detail=False, methods=['POST'], permission_classes=[IsDebug], url_path='multi') + def login_multi(self, request, *__) -> Response: + """This endpoint lets you log in as a user who's a student, an assistant and a professor at the same time""" + user, created = create_user(self, request, settings.TEST_MULTI_DATA) + if created: + Assistant.create(user) + Teacher.create(user) + return response + + @action(detail=False, methods=['POST'], permission_classes=[IsDebug], url_path='admin') + def login_admin(self, request, *__) -> Response: + """This endpoint lets you log in an admin""" + create_user(self, request, settings.TEST_ADMIN_DATA) + return response diff --git a/backend/ypovoli/settings.py b/backend/ypovoli/settings.py index f0e3186e..36527c9f 100644 --- a/backend/ypovoli/settings.py +++ b/backend/ypovoli/settings.py @@ -28,16 +28,34 @@ # TESTING TESTING_BASE_LINK = "http://testserver" -TEST_USER_DATA = { - "id": "1234", - "username": "test", - "email": "test@test", - "first_name": "test", - "last_name": "test", +TEST_ADMIN_DATA = { + "id": "0", + "username": "admin", + "email": "admin@test", + "first_name": "admin", + "last_name": "admin", + "is_staff": True } -TEST_USER_ATTRIBUTES = { - **TEST_USER_DATA, - "ugentStudentID": "1234" +TEST_STUDENT_DATA = { + "id": "6", + "username": "student", + "email": "student@test", + "first_name": "student", + "last_name": "student", +} +TEST_PROFESSOR_DATA = { + "id": "1", + "username": "professor", + "email": "professor@test", + "first_name": "professor", + "last_name": "professor", +} +TEST_MULTI_DATA = { + "id": "10", + "username": "multi", + "email": "multi@test", + "first_name": "multi", + "last_name": "multi", } # SECURITY WARNING: keep the secret key used in production secret! diff --git a/frontend/cypress.config.js b/frontend/cypress.config.js index 83abcaba..fbde2fec 100644 --- a/frontend/cypress.config.js +++ b/frontend/cypress.config.js @@ -1,7 +1,13 @@ import { defineConfig } from 'cypress'; +import vitePreprocessor from 'cypress-vite'; export default defineConfig({ e2e: { + setupNodeEvents(on, config) { + on('file:preprocessor', + vitePreprocessor('./vite.config.ts') + ); + }, baseUrl: 'https://nginx', specPattern: 'src/test/e2e/**/*.cy.{js,jsx,ts,tsx}', }, diff --git a/frontend/cypress/support/e2e.ts b/frontend/cypress/support/e2e.ts index f80f74f8..f553c558 100644 --- a/frontend/cypress/support/e2e.ts +++ b/frontend/cypress/support/e2e.ts @@ -14,7 +14,45 @@ // *********************************************************** // Import commands.js using ES2015 syntax: -import './commands' +import './commands.ts' // Alternatively you can use CommonJS syntax: -// require('./commands') \ No newline at end of file +// require('./commands') + +Cypress.on('uncaught:exception', (err, runnable) => { + // log uncaught error + console.error('Uncaught exception:', err.message); + + return !err.message.includes('401'); +}); + +const logout = () => { + cy.getCookie('csrftoken').then((cookie) => { + cy.getCookie('sessionid').then((cookie2) => { + if (cookie && cookie2) { + cy.request({ + method: 'POST', + url: '/api/auth/cas/logout/', + headers: { + 'Referer': Cypress.config('baseUrl'), + 'X-CSRFToken': cookie.value, + }, + }); + } + }) + + }); +} + +// before(() => { +// cy.request('POST', '/api/auth/test-user/student/'); +// logout(); +// cy.request('POST', '/api/auth/test-user/multi/'); +// logout(); +// cy.request('POST', '/api/auth/test-user/admin/'); +// logout(); +// }) + +afterEach(() => { + logout(); +}) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 6189c3b4..b38c986e 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -33,6 +33,7 @@ "@typescript-eslint/eslint-plugin": "^6.21.0", "@vitejs/plugin-vue": "^5.0.4", "cypress": "^13.7.1", + "cypress-vite": "^1.5.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-config-standard-with-typescript": "^43.0.1", @@ -2812,6 +2813,19 @@ "node": "^16.0.0 || ^18.0.0 || >=20.0.0" } }, + "node_modules/cypress-vite": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/cypress-vite/-/cypress-vite-1.5.0.tgz", + "integrity": "sha512-vvTMqJZgI3sN2ylQTi4OQh8LRRjSrfrIdkQD5fOj+EC/e9oHkxS96lif1SyDF1PwailG1tnpJE+VpN6+AwO/rg==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.3", + "debug": "^4.3.4" + }, + "peerDependencies": { + "vite": "^2.9.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, "node_modules/cypress/node_modules/proxy-from-env": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 38241a94..a6a82480 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,6 +11,7 @@ "test": "vitest run", "cypress:open": "cypress open", "cypress:test": "cypress run", + "cypress:install": "cypress install", "lint": "eslint src --ext .ts,.vue", "lint-fix": "eslint src --ext .ts,.vue --fix" }, @@ -40,6 +41,7 @@ "@typescript-eslint/eslint-plugin": "^6.21.0", "@vitejs/plugin-vue": "^5.0.4", "cypress": "^13.7.1", + "cypress-vite": "^1.5.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-config-standard-with-typescript": "^43.0.1", diff --git a/frontend/src/components/courses/CourseDetailCard.vue b/frontend/src/components/courses/CourseDetailCard.vue index 049ee0f3..ce92fc59 100644 --- a/frontend/src/components/courses/CourseDetailCard.vue +++ b/frontend/src/components/courses/CourseDetailCard.vue @@ -19,7 +19,7 @@ const { getImport } = useGlob(import.meta.glob('@/assets/img/faculties/*.png', { @@ -95,7 +103,7 @@ watchImmediate( - +