diff --git a/.gitignore b/.gitignore index 0d14ca4dd081d5d9be6e064a717f862bab407cb1..9f28e5cb447949081556e27b2b1702613de93bbc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ __pycache__ *.db */env -*.coverage \ No newline at end of file +*.coverage +.pytest_cache \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e43fa9fd794202ccad087c6bc0ce54e8cc63fcce..1c7b2a5c5eb9a5a43d2253b905e66efe5a1b61f4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,49 +1,6 @@ -image: node:10 - stages: - - install - - build - - quality - -install: - stage: install - script: - - cd client - - npm install - artifacts: - name: "artifacts" - untracked: true - expire_in: 60 mins - paths: - - client/.npm/ - - client/node_modules/ - -build: - stage: build - script: - - cd client - - CI=false npm run build - artifacts: - paths: - - client/build - expire_in: 60 mins - dependencies: - - install - -linting: - stage: quality - script: - - cd client - - npm run lint - dependencies: - - install + - setup + - test -test:unit: - stage: quality - script: - - cd client - - npm run test:coverage - dependencies: - - install - coverage: /All files\s*\|\s*([\d\.]+)/ - +include: + - local: .gitlab/server.gitlab-ci.yml diff --git a/.gitlab/client.gitlab-ci.yml b/.gitlab/client.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..2d5697d62324505dd7580d55e136cab7a9d6b4f7 --- /dev/null +++ b/.gitlab/client.gitlab-ci.yml @@ -0,0 +1,48 @@ +image: node:10 + +stages: + - install + - build + - quality + +install: + stage: install + script: + - cd client + - npm install + artifacts: + name: "artifacts" + untracked: true + expire_in: 60 mins + paths: + - client/.npm/ + - client/node_modules/ + +build: + stage: build + script: + - cd client + - CI=false npm run build + artifacts: + paths: + - client/build + expire_in: 60 mins + dependencies: + - install + +linting: + stage: quality + script: + - cd client + - npm run lint + dependencies: + - install + +test:unit: + stage: quality + script: + - cd client + - npm run test:coverage + dependencies: + - install + coverage: /All files\s*\|\s*([\d\.]+)/ diff --git a/.gitlab/server.gitlab-ci.yml b/.gitlab/server.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..481e31bb7575c6cf3248c0eeb6174437b40ed3e2 --- /dev/null +++ b/.gitlab/server.gitlab-ci.yml @@ -0,0 +1,18 @@ +image: python + +cache: + paths: + - server/env/ + +before_script: + - python --version + - pip install virtualenv + - cd server/ + - python -m venv env + - source env/bin/activate + - pip install -r requirements.txt + +test-server: + stage: test + script: + - pytest --cov app tests/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json index d849a6dbc7b056bc12847f11a15a051a228c74f5..9421e18e7ae549bdc1f6a80582081e6b1e238bec 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -5,6 +5,7 @@ "pranaygp.vscode-css-peek", "dbaeumer.vscode-eslint", "ms-vsliveshare.vsliveshare", - "cssho.vscode-svgviewer" + "cssho.vscode-svgviewer", + "esbenp.prettier-vscode" ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 81f7de10352790e4039c19232e5dbb7f3072e177..896cb9470959cc24e9d343173561d9d728f3b206 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,13 @@ { + //editor "editor.formatOnSave": true, "editor.formatOnPaste": false, "editor.tabCompletion": "on", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true, + "source.organizeImports": true + }, + //python "python.venvPath": "${workspaceFolder}\\server", "python.analysis.extraPaths": ["server"], "python.terminal.activateEnvironment": true, @@ -11,5 +17,18 @@ "--line-length", "119" ], - "git.ignoreLimitWarning": true + //eslint + "eslint.workingDirectories": ["./client"], + "eslint.options": { + "configFile":"./.eslintrc" + }, + //git + "git.ignoreLimitWarning": true, + //language specific + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 415547a1d5edc3d08d5826ace0d132008d43609f..7178e876f0199277a05d047212b5e11e17644315 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -29,14 +29,12 @@ "label": "Test Server", "type": "shell", "group": "build", - "command": "${workspaceFolder}/server/env/Scripts/python test.py", + "command": "env/Scripts/pytest.exe --cov app tests/", "problemMatcher": [], "options": { "cwd": "${workspaceFolder}/server" }, - "presentation": { - "group": "Client/Server" - } + }, { "label": "Client + Server", diff --git a/README.md b/README.md index 339bd33f68207530a254edefd3688a6b817bbe83..d924ff12c507de2858b703daffa4ca8ca116cd4e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ + + # Scoring system for Teknikåttan This is the scoring system for Teknikåttan! diff --git a/client/.eslintrc b/client/.eslintrc new file mode 100644 index 0000000000000000000000000000000000000000..193fae78d75468a8048fb0f1206d340ebdff44bc --- /dev/null +++ b/client/.eslintrc @@ -0,0 +1,34 @@ + { + "env": { + "browser": true, + "es6": true, + "node": true + }, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "project": ["tsconfig.json"], + "ecmaVersion": 2021, + "sourceType": "module" + }, + + "settings": { + "react": { + "version": "detect" + } + }, + "extends": [ + "airbnb-typescript", + "plugin:@typescript-eslint/recommended", + "plugin:react/recommended", + "prettier/@typescript-eslint", + "plugin:prettier/recommended" + ], + "rules": { + "semi":"off", + "react/jsx-one-expression-per-line": "off" + + } +} diff --git a/client/.eslintrc.js b/client/.eslintrc.js deleted file mode 100644 index 6bd7839fd79e778fe90fc570691fed09d2d3678d..0000000000000000000000000000000000000000 --- a/client/.eslintrc.js +++ /dev/null @@ -1,26 +0,0 @@ -module.exports = { - "env": { - "browser": true, - "es2021": true, - "node": true - }, - "extends": [ - "eslint:recommended", - "plugin:react/recommended", - "plugin:@typescript-eslint/recommended" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "ecmaVersion": 12, - "sourceType": "module" - }, - "plugins": [ - "react", - "@typescript-eslint" - ], - "rules": { - } -}; diff --git a/client/.prettierrc b/client/.prettierrc new file mode 100644 index 0000000000000000000000000000000000000000..76ee677f4c1ae67d6af00360ff4b6e4b260c61b8 --- /dev/null +++ b/client/.prettierrc @@ -0,0 +1,6 @@ +{ + "semi": false, + "trailingComma": "none", + "singleQuote": true, + "printWidth": 80 + } \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index 4a876ccdd16e0b716d901d1a0653bb10a567ea9c..c8b2a0485fc314d64cfea0eda58b6892c57a9391 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -2393,67 +2393,73 @@ "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==" }, "@typescript-eslint/eslint-plugin": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.1.tgz", - "integrity": "sha512-yW2epMYZSpNJXZy22Biu+fLdTG8Mn6b22kR3TqblVk50HGNV8Zya15WAXuQCr8tKw4Qf1BL4QtI6kv6PCkLoJw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.2.0.tgz", + "integrity": "sha512-zBNRkzvLSwo6y5TG0DVcmshZIYBHKtmzD4N+LYnfTFpzc4bc79o8jNRSb728WV7A4Cegbs+MV5IRAj8BKBgOVQ==", + "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.15.1", - "@typescript-eslint/scope-manager": "4.15.1", + "@typescript-eslint/experimental-utils": "4.2.0", + "@typescript-eslint/scope-manager": "4.2.0", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", - "lodash": "^4.17.15", "regexpp": "^3.0.0", "semver": "^7.3.2", "tsutils": "^3.17.1" }, "dependencies": { "@typescript-eslint/experimental-utils": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.1.tgz", - "integrity": "sha512-9LQRmOzBRI1iOdJorr4jEnQhadxK4c9R2aEAsm7WE/7dq8wkKD1suaV0S/JucTL8QlYUPU1y2yjqg+aGC0IQBQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.2.0.tgz", + "integrity": "sha512-5BBj6BjgHEndBaQQpUVzRIPERz03LBc0MCQkHwUaH044FJFL08SwWv/sQftk7gf0ShZ2xZysz0LTwCwNt4Xu3w==", + "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.15.1", - "@typescript-eslint/types": "4.15.1", - "@typescript-eslint/typescript-estree": "4.15.1", + "@typescript-eslint/scope-manager": "4.2.0", + "@typescript-eslint/types": "4.2.0", + "@typescript-eslint/typescript-estree": "4.2.0", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" } }, "@typescript-eslint/scope-manager": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.1.tgz", - "integrity": "sha512-ibQrTFcAm7yG4C1iwpIYK7vDnFg+fKaZVfvyOm3sNsGAerKfwPVFtYft5EbjzByDJ4dj1WD8/34REJfw/9wdVA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.2.0.tgz", + "integrity": "sha512-Tb402cxxObSxWIVT+PnBp5ruT2V/36yj6gG4C9AjkgRlZpxrLAzWDk3neen6ToMBGeGdxtnfFLoJRUecGz9mYQ==", + "dev": true, "requires": { - "@typescript-eslint/types": "4.15.1", - "@typescript-eslint/visitor-keys": "4.15.1" + "@typescript-eslint/types": "4.2.0", + "@typescript-eslint/visitor-keys": "4.2.0" } }, "@typescript-eslint/types": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.1.tgz", - "integrity": "sha512-iGsaUyWFyLz0mHfXhX4zO6P7O3sExQpBJ2dgXB0G5g/8PRVfBBsmQIc3r83ranEQTALLR3Vko/fnCIVqmH+mPw==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.2.0.tgz", + "integrity": "sha512-xkv5nIsxfI/Di9eVwN+G9reWl7Me9R5jpzmZUch58uQ7g0/hHVuGUbbn4NcxcM5y/R4wuJIIEPKPDb5l4Fdmwg==", + "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.1.tgz", - "integrity": "sha512-z8MN3CicTEumrWAEB2e2CcoZa3KP9+SMYLIA2aM49XW3cWIaiVSOAGq30ffR5XHxRirqE90fgLw3e6WmNx5uNw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.2.0.tgz", + "integrity": "sha512-iWDLCB7z4MGkLipduF6EOotdHNtgxuNKnYD54nMS/oitFnsk4S3S/TE/UYXQTra550lHtlv9eGmp+dvN9pUDtA==", + "dev": true, "requires": { - "@typescript-eslint/types": "4.15.1", - "@typescript-eslint/visitor-keys": "4.15.1", + "@typescript-eslint/types": "4.2.0", + "@typescript-eslint/visitor-keys": "4.2.0", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", + "lodash": "^4.17.15", "semver": "^7.3.2", "tsutils": "^3.17.1" } }, "@typescript-eslint/visitor-keys": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.1.tgz", - "integrity": "sha512-tYzaTP9plooRJY8eNlpAewTOqtWW/4ff/5wBjNVaJ0S0wC4Gpq/zDVRTJa5bq2v1pCNQ08xxMCndcvR+h7lMww==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.2.0.tgz", + "integrity": "sha512-WIf4BNOlFOH2W+YqGWa6YKLcK/EB3gEj2apCrqLw6mme1RzBy0jtJ9ewJgnrZDB640zfnv8L+/gwGH5sYp/rGw==", + "dev": true, "requires": { - "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/types": "4.2.0", "eslint-visitor-keys": "^2.0.0" } } @@ -2473,50 +2479,56 @@ } }, "@typescript-eslint/parser": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.1.tgz", - "integrity": "sha512-V8eXYxNJ9QmXi5ETDguB7O9diAXlIyS+e3xzLoP/oVE4WCAjssxLIa0mqCLsCGXulYJUfT+GV70Jv1vHsdKwtA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.2.0.tgz", + "integrity": "sha512-54jJ6MwkOtowpE48C0QJF9iTz2/NZxfKVJzv1ha5imigzHbNSLN9yvbxFFH1KdlRPQrlR8qxqyOvLHHxd397VA==", + "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.15.1", - "@typescript-eslint/types": "4.15.1", - "@typescript-eslint/typescript-estree": "4.15.1", + "@typescript-eslint/scope-manager": "4.2.0", + "@typescript-eslint/types": "4.2.0", + "@typescript-eslint/typescript-estree": "4.2.0", "debug": "^4.1.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.1.tgz", - "integrity": "sha512-ibQrTFcAm7yG4C1iwpIYK7vDnFg+fKaZVfvyOm3sNsGAerKfwPVFtYft5EbjzByDJ4dj1WD8/34REJfw/9wdVA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.2.0.tgz", + "integrity": "sha512-Tb402cxxObSxWIVT+PnBp5ruT2V/36yj6gG4C9AjkgRlZpxrLAzWDk3neen6ToMBGeGdxtnfFLoJRUecGz9mYQ==", + "dev": true, "requires": { - "@typescript-eslint/types": "4.15.1", - "@typescript-eslint/visitor-keys": "4.15.1" + "@typescript-eslint/types": "4.2.0", + "@typescript-eslint/visitor-keys": "4.2.0" } }, "@typescript-eslint/types": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.1.tgz", - "integrity": "sha512-iGsaUyWFyLz0mHfXhX4zO6P7O3sExQpBJ2dgXB0G5g/8PRVfBBsmQIc3r83ranEQTALLR3Vko/fnCIVqmH+mPw==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.2.0.tgz", + "integrity": "sha512-xkv5nIsxfI/Di9eVwN+G9reWl7Me9R5jpzmZUch58uQ7g0/hHVuGUbbn4NcxcM5y/R4wuJIIEPKPDb5l4Fdmwg==", + "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.1.tgz", - "integrity": "sha512-z8MN3CicTEumrWAEB2e2CcoZa3KP9+SMYLIA2aM49XW3cWIaiVSOAGq30ffR5XHxRirqE90fgLw3e6WmNx5uNw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.2.0.tgz", + "integrity": "sha512-iWDLCB7z4MGkLipduF6EOotdHNtgxuNKnYD54nMS/oitFnsk4S3S/TE/UYXQTra550lHtlv9eGmp+dvN9pUDtA==", + "dev": true, "requires": { - "@typescript-eslint/types": "4.15.1", - "@typescript-eslint/visitor-keys": "4.15.1", + "@typescript-eslint/types": "4.2.0", + "@typescript-eslint/visitor-keys": "4.2.0", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", + "lodash": "^4.17.15", "semver": "^7.3.2", "tsutils": "^3.17.1" } }, "@typescript-eslint/visitor-keys": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.1.tgz", - "integrity": "sha512-tYzaTP9plooRJY8eNlpAewTOqtWW/4ff/5wBjNVaJ0S0wC4Gpq/zDVRTJa5bq2v1pCNQ08xxMCndcvR+h7lMww==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.2.0.tgz", + "integrity": "sha512-WIf4BNOlFOH2W+YqGWa6YKLcK/EB3gEj2apCrqLw6mme1RzBy0jtJ9ewJgnrZDB640zfnv8L+/gwGH5sYp/rGw==", + "dev": true, "requires": { - "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/types": "4.2.0", "eslint-visitor-keys": "^2.0.0" } } @@ -5700,6 +5712,100 @@ } } }, + "eslint-config-airbnb": { + "version": "18.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-18.2.1.tgz", + "integrity": "sha512-glZNDEZ36VdlZWoxn/bUR1r/sdFKPd1mHPbqUtkctgNG4yT2DLLtJ3D+yCV+jzZCc2V1nBVkmdknOJBZ5Hc0fg==", + "dev": true, + "requires": { + "eslint-config-airbnb-base": "^14.2.1", + "object.assign": "^4.1.2", + "object.entries": "^1.1.2" + } + }, + "eslint-config-airbnb-base": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz", + "integrity": "sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.2" + } + }, + "eslint-config-airbnb-typescript": { + "version": "12.3.1", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-12.3.1.tgz", + "integrity": "sha512-ql/Pe6/hppYuRp4m3iPaHJqkBB7dgeEmGPQ6X0UNmrQOfTF+dXw29/ZjU2kQ6RDoLxaxOA+Xqv07Vbef6oVTWw==", + "dev": true, + "requires": { + "@typescript-eslint/parser": "^4.4.1", + "eslint-config-airbnb": "^18.2.0", + "eslint-config-airbnb-base": "^14.2.0" + }, + "dependencies": { + "@typescript-eslint/parser": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.1.tgz", + "integrity": "sha512-V8eXYxNJ9QmXi5ETDguB7O9diAXlIyS+e3xzLoP/oVE4WCAjssxLIa0mqCLsCGXulYJUfT+GV70Jv1vHsdKwtA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.15.1", + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/typescript-estree": "4.15.1", + "debug": "^4.1.1" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.1.tgz", + "integrity": "sha512-ibQrTFcAm7yG4C1iwpIYK7vDnFg+fKaZVfvyOm3sNsGAerKfwPVFtYft5EbjzByDJ4dj1WD8/34REJfw/9wdVA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/visitor-keys": "4.15.1" + } + }, + "@typescript-eslint/types": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.1.tgz", + "integrity": "sha512-iGsaUyWFyLz0mHfXhX4zO6P7O3sExQpBJ2dgXB0G5g/8PRVfBBsmQIc3r83ranEQTALLR3Vko/fnCIVqmH+mPw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.1.tgz", + "integrity": "sha512-z8MN3CicTEumrWAEB2e2CcoZa3KP9+SMYLIA2aM49XW3cWIaiVSOAGq30ffR5XHxRirqE90fgLw3e6WmNx5uNw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/visitor-keys": "4.15.1", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.1.tgz", + "integrity": "sha512-tYzaTP9plooRJY8eNlpAewTOqtWW/4ff/5wBjNVaJ0S0wC4Gpq/zDVRTJa5bq2v1pCNQ08xxMCndcvR+h7lMww==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.15.1", + "eslint-visitor-keys": "^2.0.0" + } + } + } + }, + "eslint-config-prettier": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz", + "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==", + "dev": true + }, "eslint-config-react-app": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz", @@ -5738,6 +5844,19 @@ } } }, + "eslint-import-resolver-typescript": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.4.0.tgz", + "integrity": "sha512-useJKURidCcldRLCNKWemr1fFQL1SzB3G4a0li6lFGvlc5xGe1hY343bvG07cbpCzPuM/lK19FIJB3XGFSkplA==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + } + }, "eslint-module-utils": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", @@ -5874,6 +5993,16 @@ "@typescript-eslint/experimental-utils": "^4.0.1" } }, + "eslint-plugin-json": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-json/-/eslint-plugin-json-2.1.2.tgz", + "integrity": "sha512-isM/fsUxS4wN1+nLsWoV5T4gLgBQnsql3nMTr8u+cEls1bL8rRQO5CP5GtxJxaOfbcKqnz401styw+H/P+e78Q==", + "dev": true, + "requires": { + "lodash": "^4.17.19", + "vscode-json-languageservice": "^3.7.0" + } + }, "eslint-plugin-jsx-a11y": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz", @@ -5899,6 +6028,15 @@ } } }, + "eslint-plugin-prettier": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz", + "integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, "eslint-plugin-react": { "version": "7.22.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz", @@ -6414,6 +6552,12 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "fast-glob": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", @@ -9575,6 +9719,12 @@ "minimist": "^1.2.5" } }, + "jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "dev": true + }, "jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -12004,6 +12154,21 @@ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, + "prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "pretty-bytes": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.5.0.tgz", @@ -12477,6 +12642,84 @@ "webpack-dev-server": "3.11.0", "webpack-manifest-plugin": "2.2.0", "workbox-webpack-plugin": "5.1.4" + }, + "dependencies": { + "@typescript-eslint/eslint-plugin": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.1.tgz", + "integrity": "sha512-yW2epMYZSpNJXZy22Biu+fLdTG8Mn6b22kR3TqblVk50HGNV8Zya15WAXuQCr8tKw4Qf1BL4QtI6kv6PCkLoJw==", + "requires": { + "@typescript-eslint/experimental-utils": "4.15.1", + "@typescript-eslint/scope-manager": "4.15.1", + "debug": "^4.1.1", + "functional-red-black-tree": "^1.0.1", + "lodash": "^4.17.15", + "regexpp": "^3.0.0", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.1.tgz", + "integrity": "sha512-9LQRmOzBRI1iOdJorr4jEnQhadxK4c9R2aEAsm7WE/7dq8wkKD1suaV0S/JucTL8QlYUPU1y2yjqg+aGC0IQBQ==", + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.15.1", + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/typescript-estree": "4.15.1", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.1.tgz", + "integrity": "sha512-V8eXYxNJ9QmXi5ETDguB7O9diAXlIyS+e3xzLoP/oVE4WCAjssxLIa0mqCLsCGXulYJUfT+GV70Jv1vHsdKwtA==", + "requires": { + "@typescript-eslint/scope-manager": "4.15.1", + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/typescript-estree": "4.15.1", + "debug": "^4.1.1" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.1.tgz", + "integrity": "sha512-ibQrTFcAm7yG4C1iwpIYK7vDnFg+fKaZVfvyOm3sNsGAerKfwPVFtYft5EbjzByDJ4dj1WD8/34REJfw/9wdVA==", + "requires": { + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/visitor-keys": "4.15.1" + } + }, + "@typescript-eslint/types": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.1.tgz", + "integrity": "sha512-iGsaUyWFyLz0mHfXhX4zO6P7O3sExQpBJ2dgXB0G5g/8PRVfBBsmQIc3r83ranEQTALLR3Vko/fnCIVqmH+mPw==" + }, + "@typescript-eslint/typescript-estree": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.1.tgz", + "integrity": "sha512-z8MN3CicTEumrWAEB2e2CcoZa3KP9+SMYLIA2aM49XW3cWIaiVSOAGq30ffR5XHxRirqE90fgLw3e6WmNx5uNw==", + "requires": { + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/visitor-keys": "4.15.1", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.1.tgz", + "integrity": "sha512-tYzaTP9plooRJY8eNlpAewTOqtWW/4ff/5wBjNVaJ0S0wC4Gpq/zDVRTJa5bq2v1pCNQ08xxMCndcvR+h7lMww==", + "requires": { + "@typescript-eslint/types": "4.15.1", + "eslint-visitor-keys": "^2.0.0" + } + } } }, "read-pkg": { @@ -15002,6 +15245,43 @@ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" }, + "vscode-json-languageservice": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.11.0.tgz", + "integrity": "sha512-QxI+qV97uD7HHOCjh3MrM1TfbdwmTXrMckri5Tus1/FQiG3baDZb2C9Y0y8QThs7PwHYBIQXcAc59ZveCRZKPA==", + "dev": true, + "requires": { + "jsonc-parser": "^3.0.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "3.16.0-next.2", + "vscode-nls": "^5.0.0", + "vscode-uri": "^2.1.2" + } + }, + "vscode-languageserver-textdocument": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz", + "integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==", + "dev": true + }, + "vscode-languageserver-types": { + "version": "3.16.0-next.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz", + "integrity": "sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q==", + "dev": true + }, + "vscode-nls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.0.0.tgz", + "integrity": "sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA==", + "dev": true + }, + "vscode-uri": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz", + "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==", + "dev": true + }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -16496,4 +16776,4 @@ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" } } -} +} \ No newline at end of file diff --git a/client/package.json b/client/package.json index e1e298dc1298b0835845e56c5ca6a1b504ea4082..0b20527e57672e7595b683aa120c876b3e05825f 100644 --- a/client/package.json +++ b/client/package.json @@ -17,19 +17,27 @@ "axios": "^0.21.1", "web-vitals": "^1.1.0" }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "4.2.0", + "@typescript-eslint/parser": "4.2.0", + "eslint": "7.19.0", + "eslint-config-airbnb": "^18.2.1", + "eslint-config-airbnb-typescript": "^12.3.1", + "eslint-config-prettier": "^7.2.0", + "eslint-import-resolver-typescript": "^2.4.0", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-json": "^2.1.2", + "eslint-plugin-jsx-a11y": "^6.4.1", + "eslint-plugin-prettier": "^3.3.1", + "eslint-plugin-react": "^7.22.0", + "prettier": "^2.2.1" + }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", - "lint": "eslint --ignore-path .gitignore .", - "test:coverage": "react-scripts test --coverage" - }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] + "lint": "eslint \"./src/**/*.{js,ts,tsx}\"" }, "browserslist": { "production": [ diff --git a/client/src/App.test.tsx b/client/src/App.test.tsx index 2a68616d9846ed7d3bfb9f28ca1eb4d51b2c2f84..3a7a8cc56fc10c8204edd16bb784b72ca3ad50ac 100644 --- a/client/src/App.test.tsx +++ b/client/src/App.test.tsx @@ -1,9 +1,9 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import App from './App'; +import React from 'react' +import { render, screen } from '@testing-library/react' +import App from './App' test('renders learn react link', () => { - render(<App />); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); + render(<App />) + const linkElement = screen.getByText(/learn react/i) + expect(linkElement).toBeInTheDocument() +}) diff --git a/client/src/App.tsx b/client/src/App.tsx index 6d9c9bdb4137f17dad9187f58bb29321b70c81a7..931b58fa3cac3893f9b343cff3dc423a544ba577 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,20 +1,19 @@ -import React from 'react'; -import logo from './logo.svg'; -import './App.css'; -import { useState, useEffect } from "react"; -import axios from "axios"; +import axios from 'axios' +import React, { useEffect, useState } from 'react' +import './App.css' +import logo from './logo.svg' interface Message { - message: string; + message: string } -function App() { - const [currentMessage, setCurrentMessage] = useState<Message>(); +const App: React.FC = () => { + const [currentMessage, setCurrentMessage] = useState<Message>() useEffect(() => { - axios.get<Message>("users/test").then(response=> { - setCurrentMessage(response.data); - }); - }, []); + axios.get<Message>('users/test').then((response) => { + setCurrentMessage(response.data) + }) + }, []) return ( <div className="App"> @@ -34,7 +33,7 @@ function App() { <p>Current message is {currentMessage?.message}</p> </header> </div> - ); + ) } -export default App; +export default App diff --git a/client/src/index.tsx b/client/src/index.tsx index ef2edf8ea3fc42258464231e29140c8723458c1e..e7b11a230f0a06760e23141dc90d09baee11479a 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -1,17 +1,17 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import './index.css'; -import App from './App'; -import reportWebVitals from './reportWebVitals'; +import React from 'react' +import ReactDOM from 'react-dom' +import App from './App' +import './index.css' +import reportWebVitals from './reportWebVitals' ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') -); +) // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); +reportWebVitals() diff --git a/client/src/reportWebVitals.ts b/client/src/reportWebVitals.ts index 49a2a16e0fbc7636ee16bf907257a5282b856493..57a24a21eae1de4e00842390a8e04a76e7c68bad 100644 --- a/client/src/reportWebVitals.ts +++ b/client/src/reportWebVitals.ts @@ -1,15 +1,15 @@ -import { ReportHandler } from 'web-vitals'; +import { ReportHandler } from 'web-vitals' const reportWebVitals = (onPerfEntry?: ReportHandler) => { if (onPerfEntry && onPerfEntry instanceof Function) { import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); - }); + getCLS(onPerfEntry) + getFID(onPerfEntry) + getFCP(onPerfEntry) + getLCP(onPerfEntry) + getTTFB(onPerfEntry) + }) } -}; +} -export default reportWebVitals; +export default reportWebVitals diff --git a/client/src/setupTests.ts b/client/src/setupTests.ts index 8f2609b7b3e0e3897ab3bcaad13caf6876e48699..52aaef1d2452104517b38ed65ea62c9a305aaa66 100644 --- a/client/src/setupTests.ts +++ b/client/src/setupTests.ts @@ -2,4 +2,4 @@ // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; +import '@testing-library/jest-dom' diff --git a/server/requirements.txt b/server/requirements.txt index 15f3fb46c43a7c2d2eee3959e3fce08db255efc2..31bb42fb147e77cea0e83c9af0230046efacb0b4 100644 Binary files a/server/requirements.txt and b/server/requirements.txt differ diff --git a/server/test.py b/server/test.py deleted file mode 100644 index f69c5a7b6da694e040f1a3980cae855cbea71bb3..0000000000000000000000000000000000000000 --- a/server/test.py +++ /dev/null @@ -1,69 +0,0 @@ -from app import create_app, db -import unittest -import json - - -class Test(unittest.TestCase): - def setUp(self): - """Before each test, set up a blank database""" - self.app = create_app("configmodule.TestingConfig") - self.app.testing = True - - self.client = self.app.test_client() - - with self.app.app_context(): - db.drop_all() - db.create_all() - - # Called after every test - def tearDown(self): - with self.app.app_context(): - db.session.remove() - db.drop_all() - - def test_user(self): - # Create user - rv = self.client.post( - "/api/users/", - data=json.dumps({"email": "test@test.se", "password": "abc123"}), - ) - rv_dict = json.loads(rv.data.decode()) - - assert rv.status_code == 200 - assert rv_dict["id"] == 1 - assert "password" not in rv_dict - assert rv_dict["email"] == "test@test.se" - - # Try loggin with wrong PASSWORD - rv = self.client.post("/api/users/login", data=json.dumps({"email": "test@test.se", "password": "abc1234"})) - assert rv.status_code == 401 - - # Try loggin with wrong Email - rv = self.client.post("/api/users/login", data=json.dumps({"email": "test1@test.se", "password": "abc1234"})) - assert rv.status_code == 401 - - # Try loggin with right PASSWORD - rv = self.client.post("/api/users/login", data=json.dumps({"email": "test@test.se", "password": "abc123"})) - rv_dict = json.loads(rv.data.decode()) - assert rv.status_code == 200 - headers = {"Authorization": "Bearer " + rv_dict["access_token"]} - - # Get the current user - rv = self.client.get("/api/users/", headers=headers) - rv_dict = json.loads(rv.data.decode()) - assert rv.status_code == 200 - assert rv_dict["email"] == "test@test.se" - - rv = self.client.put("/api/users/", data=json.dumps({"name": "carl carlsson"}), headers=headers) - rv_dict = json.loads(rv.data.decode()) - assert rv.status_code == 200 - assert rv_dict["name"] == "Carl Carlsson" - - def test_empty(self): - # Try loggin withou any users - rv = self.client.post("/api/users/login", data=json.dumps({"email": "test@test.se", "password": "abc123"})) - assert rv.status_code == 401 - - -if __name__ == "__main__": - unittest.main() diff --git a/server/tests/__init__.py b/server/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..0d8c1354ffd04237f06f2b2883e86c175bd511d4 --- /dev/null +++ b/server/tests/__init__.py @@ -0,0 +1,18 @@ +import pytest +from app import create_app, db + + +@pytest.fixture +def app(): + app = create_app("configmodule.TestingConfig") + + with app.app_context(): + db.drop_all() + db.create_all() + + return app + + +@pytest.fixture +def client(app): + return app.test_client() diff --git a/server/tests/test_app.py b/server/tests/test_app.py new file mode 100644 index 0000000000000000000000000000000000000000..2ee2664724c4a273d5c3f26a4539ebecb1cfcb70 --- /dev/null +++ b/server/tests/test_app.py @@ -0,0 +1,42 @@ +from tests import app, client +import json + + +def test_app(client): + + # Create user + rv = client.post( + "/api/users/", + data=json.dumps({"email": "test@test.se", "password": "abc123"}), + ) + rv_dict = json.loads(rv.data.decode()) + + assert rv.status_code == 200 + assert rv_dict["id"] == 1 + assert "password" not in rv_dict + assert rv_dict["email"] == "test@test.se" + + # Try loggin with wrong PASSWORD + rv = client.post("/api/users/login", data=json.dumps({"email": "test@test.se", "password": "abc1234"})) + assert rv.status_code == 401 + + # Try loggin with wrong Email + rv = client.post("/api/users/login", data=json.dumps({"email": "test1@test.se", "password": "abc1234"})) + assert rv.status_code == 401 + + # Try loggin with right PASSWORD + rv = client.post("/api/users/login", data=json.dumps({"email": "test@test.se", "password": "abc123"})) + rv_dict = json.loads(rv.data.decode()) + assert rv.status_code == 200 + headers = {"Authorization": "Bearer " + rv_dict["access_token"]} + + # Get the current user + rv = client.get("/api/users/", headers=headers) + rv_dict = json.loads(rv.data.decode()) + assert rv.status_code == 200 + assert rv_dict["email"] == "test@test.se" + + rv = client.put("/api/users/", data=json.dumps({"name": "carl carlsson"}), headers=headers) + rv_dict = json.loads(rv.data.decode()) + assert rv.status_code == 200 + assert rv_dict["name"] == "Carl Carlsson"