Skip to content
Snippets Groups Projects
Commit f3d37205 authored by robinwilliam.hundt's avatar robinwilliam.hundt
Browse files

Getting frontend e2e tests working

parent 42802b09
No related branches found
No related tags found
No related merge requests found
Pipeline #325306 passed
......@@ -35,6 +35,7 @@ coverage_html/
.vscode/
anon-export/
public/
geckodriver.log
# node
node_modules
......
......@@ -2,6 +2,7 @@ stages:
- build
- test
- build_image
- test_build
- pages
- staging
......@@ -25,6 +26,27 @@ build_test_env:
key: "$CI_JOB_NAME"
paths:
- .venv
tags:
- docker
build_frontend:
image: node:carbon
stage: build
script:
- cd frontend
- yarn
- yarn build
artifacts:
paths:
- frontend/dist
expire_in: 20 minutes
cache:
key: "$CI_JOB_NAME"
paths:
- frontend/dist
- frontend/node_modules/
tags:
- docker
# ============================== Testing section ============================= #
# ----------------------------- Backend subsection --------------------------- #
......@@ -34,6 +56,8 @@ build_test_env:
- source .venv/bin/activate
dependencies:
- build_test_env
tags:
- docker
test_pytest:
<<: *test_definition_virtualenv
......@@ -58,32 +82,43 @@ test_flake8:
# ----------------------------- Frontend subsection -------------------------- #
.test_template_frontend: &test_definition_frontend
image: crbanman/nightwatch
when: manual
image: docker.gitlab.gwdg.de/robinwilliam.hundt/python-geckodriver:master
before_script:
- cd frontend/
- source .venv/bin/activate
dependencies:
- build_test_env
- build_frontend
tags:
- docker
test_frontend:
<<: *test_definition_frontend
# when: manual
stage: test
services:
- postgres:9.6
script:
- yarn install
- yarn test:e2e
cache:
key: "$CI_JOB_NAME"
paths:
- frontend/node_modules/
- cp frontend/dist/index.html core/templates
- python util/format_index.py
- python manage.py collectstatic --no-input
- HEADLESS_TESTS=True pytest --ds=grady.settings.test functional_tests
# =========================== Build Image section ============================ #
build_backend:
image: docker:latest
stage: build_image
services:
- docker:dind
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- docker build -t $IMAGE_TAG .
- docker tag $IMAGE_TAG $IMAGE_TAG-$CI_COMMIT_SHA
- docker push $IMAGE_TAG
tags:
- docker
# =========================== Gitlab pages section =========================== #
pages:
......@@ -101,6 +136,7 @@ pages:
only:
- master
# ============================== Staging section ============================= #
.staging_template: &staging_definition
stage: staging
......@@ -109,6 +145,8 @@ pages:
- master
before_script:
- apk add --update py-pip && pip install docker-compose
tags:
- grady-staging
staging:
<<: *staging_definition
......
......@@ -31,7 +31,9 @@ class TutorSerializer(DynamicFieldsModelSerializer):
return t.feedback_validated if hasattr(t, 'feedback_validated') else 0
def create(self, validated_data) -> models.UserAccount:
log.info("Crating tutor from data %s", validated_data)
log_validated_data = dict(validated_data)
log_validated_data['password'] = '******'
log.info("Crating tutor from data %s", log_validated_data)
return user_factory.make_tutor(
username=validated_data['username'],
password=validated_data.get('password'),
......
......@@ -15,7 +15,7 @@ import {
function getInstanceBaseUrl (): string {
if (process.env.NODE_ENV === 'production') {
return `https://${window.location.host}${window.location.pathname}`.replace(/\/+$/, '')
return `${window.location.protocol}//${window.location.host}${window.location.pathname}`.replace(/\/+$/, '')
} else {
return 'http://localhost:8000/'
}
......
......@@ -4,10 +4,10 @@
Datenschutzerklärung
</v-card-title>
<v-card-text>
<GDPRNotice/>
<GDPRNotice id="gdpr-notice"/>
</v-card-text>
<v-card-actions>
<v-btn @click="acceptedGDPR = true">Einwilligen</v-btn>
<v-btn @click="acceptedGDPR = true" id="accept-gdpr-notice">Einwilligen</v-btn>
</v-card-actions>
</v-card>
<v-card v-else>
......@@ -20,16 +20,18 @@
required
autofocus
v-model="credentials.username"
id="input-register-username"
/>
<v-text-field
label="Password"
required
type="password"
v-model="credentials.password"
id="input-register-password"
/>
</v-card-text>
<v-card-actions class="justify-center">
<v-btn flat :loading="loading" @click="register">submit</v-btn>
<v-btn flat :loading="loading" @click="register" id="register-submit">submit</v-btn>
</v-card-actions>
</v-card>
</template>
......
......@@ -30,7 +30,7 @@
type="password"
required
/>
<v-btn @click="registerDialog = true">register</v-btn>
<v-btn @click="registerDialog = true" id="register">register</v-btn>
<v-btn :loading="loading" type="submit" color="primary">Access</v-btn>
</v-form>
</v-flex>
......
import os
import time
from django.test import LiveServerTestCase
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.firefox.options import Options
from core.models import UserAccount
from functional_tests.util import get_frontend_url
from util.factories import make_test_data
LiveServerTestCase.port = int(os.environ.get('LIVE_SERVER_PORT', 0))
class LoginPageTest(LiveServerTestCase):
def setUp(self):
self.live_server_url = get_frontend_url(self.live_server_url)
options = Options()
# funnily the method is marked deprecated but the alternative setter is not working...
options.headless = bool(os.environ.get('HEADLESS_TESTS', False))
self.browser = webdriver.Firefox(options=options)
self.browser.implicitly_wait(5)
self.test_data = make_test_data(data_dict={
'submission_types': [
{
'name': '01. Sort this or that',
'full_score': 35,
'description': 'Very complicated',
'solution': 'Trivial!'
},
{
'name': '02. Merge this or that or maybe even this',
'full_score': 35,
'description': 'Very complicated',
'solution': 'Trivial!'
}
],
'students': [
{'username': 'student01', 'password': 'p'},
{'username': 'student02', 'password': 'p'}
],
'tutors': [
{'username': 'tutor01', 'password': 'p'},
{'username': 'tutor02', 'password': 'p'}
],
'reviewers': [
{'username': 'reviewer', 'password': 'p'}
],
'submissions': [
{
'text': 'function blabl\n'
' on multi lines\n'
' for blabla in bla:\n'
' lorem ipsum und so\n',
'type': '01. Sort this or that',
'user': 'student01',
'feedback': {
'score': 5,
'is_final': True,
'feedback_lines': {
'1': [{
'text': 'This is very bad!',
'of_tutor': 'tutor01'
}],
}
}
},
{
'text': 'function blabl\n'
' asasxasx\n'
' lorem ipsum und so\n',
'type': '02. Merge this or that or maybe even this',
'user': 'student01'
},
{
'text': 'function blabl\n'
' on multi lines\n'
' asasxasx\n'
' lorem ipsum und so\n',
'type': '01. Sort this or that',
'user': 'student02'
},
{
'text': 'function lorem ipsum etc\n',
'type': '02. Merge this or that or maybe even this',
'user': 'student02'
},
]}
)
def tearDown(self):
self.browser.quit()
def _login(self, account):
self.browser.get(self.live_server_url)
username_input = self.browser.find_element_by_xpath('//input[@aria-label="Username"]')
username_input.send_keys(account.username)
password_input = self.browser.find_element_by_xpath('//input[@aria-label="Password"]')
password_input.send_keys('p')
self.browser.find_element_by_xpath('//button[@type="submit"]').send_keys(Keys.ENTER)
time.sleep(1)
def test_tutor_can_login(self):
tutor = self.test_data['tutors'][0]
self._login(tutor)
self.assertTrue(self.browser.current_url.endswith('#/home'))
def test_reviewer_can_login(self):
reviewer = self.test_data['reviewers'][0]
self._login(reviewer)
self.assertTrue(self.browser.current_url.endswith('#/home'))
def test_student_can_login(self):
student = self.test_data['students'][0]
self._login(student)
self.assertTrue(self.browser.current_url.endswith('#/home'))
def test_can_register_account(self):
username = 'danny'
password = 'redrum-is-murder-reversed'
self.browser.get(self.live_server_url)
self.browser.find_element_by_id('register').click()
self.browser.find_element_by_id('gdpr-notice')
self.browser.find_element_by_id('accept-gdpr-notice').click()
username_input = self.browser.find_element_by_id('input-register-username')
username_input.send_keys(username)
password_input = self.browser.find_element_by_id('input-register-password')
password_input.send_keys(password)
self.browser.find_element_by_id('register-submit').click()
time.sleep(1)
tutor = UserAccount.objects.get(username=username)
self.assertEqual(UserAccount.TUTOR, tutor.role)
self.assertFalse(tutor.is_active, "Tutors should be inactive after registered")
import os
def get_frontend_url(live_server_url):
return os.environ.get('FRONTEND_URL', live_server_url)
......@@ -127,6 +127,7 @@ AUTH_USER_MODEL = 'core.UserAccount'
AUTH_PASSWORD_VALIDATORS = []
CORS_ORIGIN_WHITELIST = (
'localhost:8080'
'localhost:8000'
)
REST_FRAMEWORK = {
......
......@@ -2,3 +2,4 @@ flake8~=3.5.0
pre-commit~=1.4.1
pytest-cov~=2.5.1
pytest-django~=3.1.2
selenium~=3.14.1
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment