diff --git a/Dockerfile b/Dockerfile index 04278a6..7bad904 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,10 +29,11 @@ RUN poetry config virtualenvs.create false && poetry install --no-interaction -- # Web build FROM node:17-alpine AS web-builder + FROM web-builder as web-dev WORKDIR /app/frontend + COPY ./frontend/package*.json ./ + RUN npm install -COPY ./frontend/ ./ -# EXPOSE 3000 CMD npm start diff --git a/Makefile b/Makefile index 27b8ea4..f2a9d8d 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,8 @@ TARGET_ENV ?= dev bootstrap: \ up \ - migrate + migrate \ + load-fixtures up: docker compose up -d --no-deps --remove-orphans @@ -11,7 +12,9 @@ up: docker-compose up -d $$(echo $* | tr + " ") load-fixtures: - docker compose run --rm app bash -c "./manage.py loaddata backend/fixtures/users.json" + docker compose run --rm app bash -c "./manage.py loaddata backend/fixtures/users.json \ + backend/fixtures/conversations.json \ + backend/fixtures/messages.json" restart: docker-compose restart @@ -68,6 +71,13 @@ app-test: app-lint: docker-compose run --rm app-test bash -c "poetry run pylint backend" +web-test: + docker-compose run --rm web-test sh -c "npm run test" + +test: \ + web-test \ + app-test + ps: for i in $$(docker container ls --format "{{.ID}}"); do \ docker inspect -f '{{.State.Pid}} {{.Name}}' $$i; \ diff --git a/backend/api/chats/test_views.py b/backend/api/chats/test_views.py new file mode 100644 index 0000000..82c56be --- /dev/null +++ b/backend/api/chats/test_views.py @@ -0,0 +1,2 @@ +def test_simple(): + assert 1 + 1 == 2 diff --git a/backend/poetry.lock b/backend/poetry.lock index c56ed34..b08671b 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -1053,4 +1053,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = "~3.11" -content-hash = "b125dffa86989dbeeb37aba10a4eea263f5508b0bf5d522d4b20c05d1529a3a6" +content-hash = "9b611ceb7ef1afdb113d78bd5d89b4c44642d16b9f921456b1591c4755972b6f" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index ee9b275..051876e 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -15,6 +15,7 @@ gunicorn = "~21.2.0" django-environ = "~0.11.2" psycopg2-binary = "~2.9.8" djangorestframework = "^3.14.0" +channels = "^4.0.0" [tool.poetry.group.test] optional = true @@ -28,6 +29,9 @@ pylint-django = "^2.5.5" requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" +[tool.pytest.ini_options] +python_files = "test_*.py" + [tool.pylint.MASTER] ignore = "migrations" load-plugins = "pylint_django" diff --git a/docker-compose.yml b/docker-compose.yml index a815b61..78056c3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,6 +24,7 @@ services: container_name: chat-web volumes: - ./frontend:/app/frontend + - node_modules:/app/frontend/node_modules ports: - "3000:3000" env_file: @@ -62,6 +63,18 @@ services: - ./backend:/app/backend depends_on: - db + + web-test: + image: web-test + build: + context: . + target: web-dev + profiles: + - test + volumes: + - ./frontend:/app/frontend + - node_modules:/app/frontend/node_modules + # nginx: # container_name: chat-nginx # build: ./backend/services/nginx @@ -73,6 +86,7 @@ services: volumes: pgdata: redis_data: + node_modules: # networks: # chat-network: # driver: bridge diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 301b528..68da6a7 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -18,6 +18,7 @@ "@types/react-dom": "^18.2.7", "axios": "^1.5.0", "formik": "^2.4.5", + "jest": "^27.5.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-infinite-scroll-component": "^6.1.0", @@ -4201,9 +4202,9 @@ } }, "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" }, "node_modules/@types/testing-library__jest-dom": { "version": "5.14.9", @@ -11286,9 +11287,9 @@ } }, "node_modules/jest-watch-typeahead/node_modules/@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "version": "17.0.31", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.31.tgz", + "integrity": "sha512-bocYSx4DI8TmdlvxqGpVNXOgCNR1Jj0gNPhhAY+iz1rgKDAaYrAYdFYnhDV1IFuiuVc9HkOwyDcFxaTElF3/wg==", "dependencies": { "@types/yargs-parser": "*" } @@ -20650,9 +20651,9 @@ } }, "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" }, "@types/testing-library__jest-dom": { "version": "5.14.9", @@ -25777,9 +25778,9 @@ } }, "@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "version": "17.0.31", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.31.tgz", + "integrity": "sha512-bocYSx4DI8TmdlvxqGpVNXOgCNR1Jj0gNPhhAY+iz1rgKDAaYrAYdFYnhDV1IFuiuVc9HkOwyDcFxaTElF3/wg==", "requires": { "@types/yargs-parser": "*" } diff --git a/frontend/package.json b/frontend/package.json index 1a42324..6f91639 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,6 +13,7 @@ "@types/react-dom": "^18.2.7", "axios": "^1.5.0", "formik": "^2.4.5", + "jest": "^27.5.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-infinite-scroll-component": "^6.1.0", @@ -25,8 +26,13 @@ "scripts": { "start": "react-scripts start", "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" + "test": "jest --coverage" + }, + "jest": { + "collectCoverageFrom": [ + "src/**/*.{js,jsx}", + "!/node_modules/" + ] }, "eslintConfig": { "extends": [ diff --git a/frontend/src/components/ActiveConversations.test.jsx b/frontend/src/components/ActiveConversations.test.jsx new file mode 100644 index 0000000..4a5f9cc --- /dev/null +++ b/frontend/src/components/ActiveConversations.test.jsx @@ -0,0 +1,6 @@ +describe("", () => { + it("simple test", () => { + const a = 1 + 1; + expect(a).toEqual(2); + }); +}); diff --git a/frontend/src/components/Chat.tsx b/frontend/src/components/Chat.tsx index cb336ef..cd566ba 100644 --- a/frontend/src/components/Chat.tsx +++ b/frontend/src/components/Chat.tsx @@ -1,13 +1,11 @@ import { useState, useContext, KeyboardEvent } from "react"; import useWebSocket, { ReadyState } from "react-use-websocket"; import { useParams } from "react-router-dom"; -import InfiniteScroll from "react-infinite-scroll-component"; import { AuthContext } from '../context/AuthContext'; import { MessageModel } from "../models/Message"; import { ConversationModel } from "../models/Conversation"; import { Message } from "./Message"; -import { ChatLoader } from "./ChatLoader"; export function Chat() { const { user } = useContext(AuthContext); @@ -17,8 +15,6 @@ export function Chat() { const [message, setMessage] = useState(""); const { conversationName } = useParams(); - console.log(participants); - const { readyState, sendJsonMessage } = useWebSocket(user ? `ws://localhost:8000/ws/chat/${conversationName}` : null, { diff --git a/frontend/src/context/AuthContext.tsx b/frontend/src/context/AuthContext.tsx index 204aa69..9b2af36 100644 --- a/frontend/src/context/AuthContext.tsx +++ b/frontend/src/context/AuthContext.tsx @@ -25,7 +25,6 @@ export interface AuthProps { export const AuthContext = createContext(DefaultProps); export const AuthContextProvider: React.FC<{ children: ReactNode }> = ({ children }) => { - const navigate = useNavigate(); const [user, setUser] = useState(() => AuthService.getCurrentUser());