Skip to content

Commit 25d32e5

Browse files
authored
(SIO-2489) End-to-end testing with Cypress (#71)
* Initial cypress after patch * updates for cypress testing
1 parent df32fbc commit 25d32e5

27 files changed

+1968
-23
lines changed

.github/workflows/cypress.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Cypress nightly tests
2+
3+
on:
4+
schedule:
5+
- cron: '30 5 * * 1,3,5'
6+
workflow_dispatch:
7+
8+
jobs:
9+
build:
10+
11+
runs-on: ubuntu-latest
12+
# Kill this job after 60 minutes - used when server fails, but Cypress waits on port.
13+
timeout-minutes: 60
14+
15+
steps:
16+
- uses: actions/checkout@v3
17+
- name: Install `easy_toolbox.py` requirements
18+
run: |
19+
python -m pip install --upgrade pip
20+
pip install -U inquirer
21+
22+
- name: Build OIOIOI
23+
run: |
24+
python easy_toolbox.py build --no-input
25+
26+
- name: Containers `up`
27+
run: |
28+
python easy_toolbox.py up --no-input
29+
30+
- name: Wait for migrations
31+
uses: whatnick/wait-action@master
32+
with:
33+
time: 30s
34+
35+
- name: Apply CyPress settings
36+
run: |
37+
python easy_toolbox.py cypress-apply-settings --no-input
38+
39+
- name: Run test server
40+
run: |
41+
python easy_toolbox.py run --no-input &
42+
43+
- name: Run tests
44+
run: |
45+
./test_cypress.sh
46+
47+
- name: Upload screenshots
48+
uses: actions/upload-artifact@v3
49+
if: failure()
50+
with:
51+
name: cypress-screenshots
52+
path: oioioi_cypress/cypress/screenshots

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@
2424
/deployment/
2525
/venv*/
2626
/.idea/
27+
/.vscode/

easy_toolbox.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,24 @@
2525
" -f extra/docker/docker-compose-dev-noserver.yml"
2626

2727
RAW_COMMANDS = [
28-
("build", "Build whole OIOIOI from source.", "build", True),
28+
("build", "Build OIOIOI container from source.", "build", True),
2929
("up", "Run all SIO2 containers", "up -d"),
3030
("down", "Stop all SIO2 containers", "down", True),
31-
("run", "Run server", "exec web python3 manage.py runserver 0.0.0.0:8000"),
32-
("bash", "Open command prompt on web container.", "exec web bash"),
33-
("bash_db", "Open command prompt on database container.", "exec db bash"),
31+
("run", "Run server", "{exec} web python3 manage.py runserver 0.0.0.0:8000"),
32+
("bash", "Open command prompt on web container.", "{exec} web bash"),
33+
("bash-db", "Open command prompt on database container.", "{exec} db bash"),
3434
# This one CLEARS the database. Use wisely.
35-
("flush-db", "Clear database.", "exec web python manage.py flush --noinput", True),
36-
("add-superuser", "Create admin_admin.", "exec web python manage.py createsuperuser"),
37-
("test", "Run unit tests.", "exec web ../oioioi/test.sh"),
38-
("test-slow", "Run unit tests. (--runslow)", "exec web ../oioioi/test.sh --runslow"),
35+
("flush-db", "Clear database.", "{exec} web python manage.py flush --noinput", True),
36+
("add-superuser", "Create admin_admin.",
37+
"{exec} web python manage.py loaddata ../oioioi/oioioi_cypress/cypress/fixtures/admin_admin.json"),
38+
("test", "Run unit tests.", "{exec} web ../oioioi/test.sh"),
39+
("test-slow", "Run unit tests. (--runslow)", "{exec} web ../oioioi/test.sh --runslow"),
3940
("test-abc", "Run specific test file. (edit the toolbox)",
40-
"exec web ../oioioi/test.sh -v oioioi/problems/tests/test_task_archive.py"),
41+
"{exec} web ../oioioi/test.sh -v oioioi/problems/tests/test_task_archive.py"),
4142
("test-coverage", "Run coverage tests.",
42-
"exec 'web' ../oioioi/test.sh oioioi/problems --cov-report term --cov-report xml:coverage.xml --cov=oioioi"),
43+
"{exec} 'web' ../oioioi/test.sh oioioi/problems --cov-report term --cov-report xml:coverage.xml --cov=oioioi"),
4344
("cypress-apply-settings", "Apply settings for CyPress.",
44-
"exec web bash -c \"echo CAPTCHA_TEST_MODE=True >> settings.py\""),
45+
"{exec} web bash -c \"echo CAPTCHA_TEST_MODE=True >> settings.py\""),
4546
]
4647

4748
longest_command_arg = max([len(command[0]) for command in RAW_COMMANDS])
@@ -59,9 +60,8 @@ def __init__(self, _arg, _help, _command, _warn=False):
5960
self.warn = _warn
6061

6162
# If we use exec we should add -T for GitHub actions (disable tty).
62-
def disable_tty(self):
63-
if (self.command.startswith("exec")):
64-
self.command = self.command.replace("exec", "exec -T", 1)
63+
def fill_tty(self, disable=False):
64+
self.command = self.command.format(exec="exec -T" if disable else "exec")
6565

6666
def long_str(self) -> str:
6767
return f"Option({self.arg}, Description='{self.help}', Command='{self.command}')"
@@ -83,7 +83,8 @@ def check_commands() -> None:
8383

8484

8585
def get_action_from_args() -> Option:
86-
no_flag = []
86+
# not flags
87+
arguments = []
8788

8889
for arg in sys.argv[1:]:
8990
if arg in ['--help', '-h']:
@@ -92,14 +93,14 @@ def get_action_from_args() -> Option:
9293
global NO_INPUT
9394
NO_INPUT = True
9495
else:
95-
no_flag.append(arg)
96+
arguments.append(arg)
9697

97-
if len(no_flag) < 1:
98+
if len(arguments) < 1:
9899
return None
99-
if len(no_flag) > 1:
100+
if len(arguments) > 1:
100101
raise Exception("Too many arguments!")
101102

102-
candidates = list(filter(lambda opt: opt.arg == no_flag[0], COMMANDS))
103+
candidates = list(filter(lambda opt: opt.arg == arguments[0], COMMANDS))
103104
if len(candidates) < 1:
104105
raise Exception("No argument was found!")
105106
if len(candidates) > 1:
@@ -132,18 +133,17 @@ def warn_user(action: Option) -> bool:
132133
print(f"You are going to execute command [{action.command}] marked as `dangerous`. Are you sure? [y/N]")
133134
while True:
134135
choice = input().lower()
135-
if len(choice) == 0 or "no"[:len(choice)] == choice:
136+
if not choice or "no".startswith(choice):
136137
return False
137-
elif "yes"[:len(choice)] == choice:
138+
elif "yes".startswith(choice):
138139
return True
139140
else:
140141
print("Please answer [yes] or [no].")
141142

142143

143144
def run() -> None:
144145
action = get_action_from_args() or get_action_from_cli()
145-
if NO_INPUT:
146-
action.disable_tty()
146+
action.fill_tty(disable=NO_INPUT)
147147
if action.warn and not NO_INPUT:
148148
if not warn_user(action):
149149
print("Aborting.")

oioioi/cypress_settings.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# pylint: disable=wildcard-import
2+
from settings import *
3+
4+
# Enable optional modules.
5+
INSTALLED_APPS = (
6+
'oioioi.teachers',
7+
'oioioi.ipdnsauth',
8+
'oioioi.zeus',
9+
'oioioi.oireports',
10+
'oioioi.oisubmit',
11+
'oioioi.complaints',
12+
'oioioi.exportszu',
13+
'oioioi.similarsubmits',
14+
'oioioi.disqualification',
15+
'oioioi.submitservice',
16+
'oioioi.amppz',
17+
'oioioi.teams',
18+
'oioioi.pa',
19+
'oioioi.notifications',
20+
'oioioi.mailsubmit',
21+
'oioioi.portals',
22+
'oioioi.newsfeed',
23+
'oioioi.simpleui',
24+
'oioioi.livedata',
25+
) + INSTALLED_APPS
26+
27+
DATABASES = {
28+
'default': {
29+
'ENGINE': 'django.db.backends.sqlite3',
30+
'ATOMIC_REQUESTS': True,
31+
}
32+
}
33+
34+
TEMPLATES[0]['OPTIONS']['context_processors'] += [
35+
'oioioi.portals.processors.portal_processor',
36+
]
37+
38+
AUTHENTICATION_BACKENDS += (
39+
'oioioi.base.tests.IgnorePasswordAuthBackend',
40+
'oioioi.teachers.auth.TeacherAuthBackend',
41+
)
42+
43+
MIDDLEWARE += ('oioioi.base.tests.FakeTimeMiddleware',)
44+
45+
TESTS = True
46+
MOCK_RANKINGSD = True
47+
48+
SECRET_KEY = 'no_secret'
49+
OISUBMIT_MAGICKEY = 'abcdef'
50+
USE_UNSAFE_EXEC = True
51+
USE_UNSAFE_CHECKER = True
52+
53+
COMPLAINTS_EMAIL = '[email protected]'
54+
COMPLAINTS_SUBJECT_PREFIX = '[oioioi-complaints] '
55+
56+
WARN_ABOUT_REPEATED_SUBMISSION = False
57+
58+
PROBLEM_SOURCES += ('oioioi.zeus.problem_sources.ZeusProblemSource',)
59+
60+
ZEUS_INSTANCES = {
61+
'dummy': ('__use_object__', 'oioioi.zeus.tests.ZeusDummyServer', ('', '', '')),
62+
}
63+
64+
CACHES = {'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}}
65+
66+
# Do not print migrations DEBUG to console.
67+
LOGGING['loggers']['django.db.backends.schema'] = {
68+
'handlers': ['console'],
69+
'level': 'INFO',
70+
}
71+
72+
CAPTCHA_TEST_MODE = True
73+
DEBUG = True

oioioi_cypress/.gitignore

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
# misc
15+
.DS_Store
16+
.env.local
17+
.env.development.local
18+
.env.test.local
19+
.env.production.local
20+
21+
npm-debug.log*
22+
yarn-debug.log*
23+
yarn-error.log*
24+
25+
/.vscode
26+
/cypress/screenshots
27+
28+
/.idea
29+
*.iml
30+
package-lock.json
31+

oioioi_cypress/cypress.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"chromeWebSecurity": false,
3+
"browser": "electron",
4+
"video": false
5+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[
2+
{
3+
"pk": 1,
4+
"model": "auth.user",
5+
"fields": {
6+
"username": "admin",
7+
"first_name": "Admin",
8+
"last_name": "Admin",
9+
"is_active": true,
10+
"is_superuser": true,
11+
"is_staff": true,
12+
"last_login": "2012-07-31T20:27:58.768Z",
13+
"groups": [],
14+
"user_permissions": [],
15+
"password": "pbkdf2_sha256$10000$xWTWx2IvUptP$s1g7RDNT2Be2fvDbp+XK+DBTstDGOKY66w9x65n/l/Y=",
16+
"email": "[email protected]",
17+
"date_joined": "2012-07-31T20:27:58.768Z"
18+
}
19+
}
20+
]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"admin": {
3+
"username": "admin",
4+
"password": "admin"
5+
},
6+
"user": {
7+
"username": "test_username",
8+
"first_name": "test_name",
9+
"last_name": "test_surname",
10+
"email": "[email protected]",
11+
"password": "test_password"
12+
}
13+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* Zadanie: Inwazja kosmitów
2+
Autor: Tomasz Idziaszek
3+
AMPPZ 2012
4+
5+
Rozwiązanie wzorcowe O(n)
6+
*/
7+
8+
#include <cstdio>
9+
#include <algorithm>
10+
using namespace std;
11+
12+
const int N=1000000;
13+
int n,a[N];
14+
long long d[N+1];
15+
16+
int main() {
17+
scanf("%d",&n);
18+
for(int i=0; i<n; ++i)
19+
scanf("%d",&a[i]);
20+
d[0] = 0;
21+
d[1] = a[0];
22+
for(int i=1; i<n; ++i)
23+
d[i+1] = max(d[i], d[i-1] + a[i]);
24+
printf("%lld\n", d[n]);
25+
}
372 KB
Binary file not shown.

0 commit comments

Comments
 (0)