From a459763eb2e5568581d2823854fa3b07d7b97a56 Mon Sep 17 00:00:00 2001 From: itzik Date: Sun, 24 Jan 2021 19:34:18 +0200 Subject: [PATCH 01/32] feat: added models Task and WeeklyTasks. added the weekly_tasks routers and basic functions for- edit, remove and add + demo functions for demo operations. added basic pages - add_weekly_task.html, weekly_tasks_manager.html --- app/database/models.py | 34 ++++ app/main.py | 5 +- app/media/fake_user.png | Bin 0 -> 3556 bytes app/routers/weekly_tasks.py | 233 ++++++++++++++++++++++++ app/templates/add_weekly_task.html | 67 +++++++ app/templates/weekly_tasks_manager.html | 56 ++++++ 6 files changed, 393 insertions(+), 2 deletions(-) create mode 100644 app/media/fake_user.png create mode 100644 app/routers/weekly_tasks.py create mode 100644 app/templates/add_weekly_task.html create mode 100644 app/templates/weekly_tasks_manager.html diff --git a/app/database/models.py b/app/database/models.py index 0c92ae94..fb38e63a 100644 --- a/app/database/models.py +++ b/app/database/models.py @@ -17,8 +17,14 @@ class User(Base): is_active = Column(Boolean, default=True) + weekly_tasks = relationship( + "WeeklyTask", cascade="all, delete", back_populates="owner") + events = relationship( "Event", cascade="all, delete", back_populates="owner") + + tasks = relationship( + "Task", cascade="all, delete", back_populates="owner") class Event(Base): @@ -32,3 +38,31 @@ class Event(Base): owner_id = Column(Integer, ForeignKey("users.id")) owner = relationship("User", back_populates="events") + + +class Task(Base): + __tablename__ = "tasks" + + id = Column(Integer, primary_key=True, index=True) + title = Column(String) + content = Column(String) + is_done = Column(Boolean, nullable=False) + is_important = Column(Boolean, nullable=False) + date_time = Column(DateTime, nullable=False) + owner_id = Column(Integer, ForeignKey("users.id")) + + owner = relationship("User", back_populates="tasks") + + +class WeeklyTask(Base): + __tablename__ = "weekly_task" + + id = Column(Integer, primary_key=True, index=True) + title = Column(String) + days = Column(String, nullable=False) + content = Column(String) + is_important = Column(Boolean, nullable=False) + the_time = Column(String, nullable=False) + owner_id = Column(Integer, ForeignKey("users.id")) + + owner = relationship("User", back_populates="weekly_tasks") \ No newline at end of file diff --git a/app/main.py b/app/main.py index b48bdae5..2f8ca315 100644 --- a/app/main.py +++ b/app/main.py @@ -5,7 +5,7 @@ from app.database.database import engine from app.dependencies import ( MEDIA_PATH, STATIC_PATH, templates) -from app.routers import agenda, event, profile +from app.routers import agenda, event, profile, weekly_tasks models.Base.metadata.create_all(bind=engine) @@ -17,6 +17,7 @@ app.include_router(profile.router) app.include_router(event.router) app.include_router(agenda.router) +app.include_router(weekly_tasks.router) @app.get("/") @@ -24,4 +25,4 @@ async def home(request: Request): return templates.TemplateResponse("home.html", { "request": request, "message": "Hello, World!" - }) + }) \ No newline at end of file diff --git a/app/media/fake_user.png b/app/media/fake_user.png new file mode 100644 index 0000000000000000000000000000000000000000..bd856aaa02ed8fc75fb310971827e4734b8785d5 GIT binary patch literal 3556 zcmb7Hc{Ei2-yfP7HADtumo4GT*lOxaWp9cQ!&tvV2-%e=iIF8^DH^_E$Ox(Ip(q;L zgv1zs`$|4e%r-X$qqvmDZg=MdLBxwl+=+Tu^3xCQ#d3fmnGRuf~@FAzZs%q3rvo>tw zH1ovj`8TSa{hY&lNQPN(XO}uSh?t0+llJuT>bQMK9^Hm>bfos? zp3p*}V#>;nMZ9%Gh=>$cS8Ek+2~ov6-@Su4IXfRomd9o7r-k50+V#L)m?h(}uLQ!> z5YaKcM53G$(nkD`LY4(ss~f>9Q>H0tX(e?so}y%Br9y26=1Ci zeGQFQA@$mAp!kemJzJ%t_QCIa%Z0z=s zj#)$TkRp20n>YG{LqjZ*gPUP^_*#9BFqF&I))px)PGvIXmd2ZSF&WF7oXVryC(dQu zm5pBKii?Yz=Z=?yJ*})Xx3y&?d~c|$D=aPLRqrv%@`A=0_O|j^GSD}cq;}WY>HITq zeox#2k6OK|sK&wBY&KF_I-bU+e)s^V(4TH*&~?cYRJsqMA#l8PrYBoVODon#_dtUC zpvHwr+hI}oi*R3p96mf;G$0`0>*AtmSeTBB#&CW2uLyl~*eu+rP!J5>)CQH?i@8Cf z;ss9^Sfx@xYhdw4&e1nQLWIC*C{Hb&r@Olk5U7u5b!-qq_e`dqW&gObpPS32DV+aA z&_p|^#@^n35L^2T${jlmoqT&sZ0;kujr{kGL3>{mQVz!L>6k#pLueuIdwb)%JdM;v z+kX7eZe^jMhLD~bJdy|A_Kv;6%nfR$mKH=O$MGK8y)yFP928XKT`LYbz9=JX7#f~Gb)@GAA^pU${b#Wda8gIabHNFJ``NI1@D+epO{Fi zuRjiX&Z&4e?;O6q?5?Y;`}oNdlK@AKmPBdJ3Atai;MHGI#6&?QPJhq zzB6p1W^)V`pVV+O{h@K90IR>y7!m{c5F5*-uBrKaPoqcM&(Cjpim0jV0^qc~wSz<= zA#JGpihMkAT)YBOXI)*TT{OfN!kbF6S2m(v1+%y{TpJNBctgQ{24f#4Lzg`$8T2N0 zc6K%(Jr>XbK=%khOJif>;H?m;#KOWO*KXW6s>c^O=&whd@aK`%JRhWlIlT6LGQD9k zS`v%JI!8|iHn0cFY*CLa?p>!NOnptdYf@TUTVEYT!`mL0mGLPkC@gP8%}1EqAWoe+ zW$o;oYhBea0cr%?^YQm@zgqdWzC1s*#8+2OuQ;$!fxdjPX*^BAJk4j~T26_Uj!xX} z?yem+XjmR|I5aG51x$+Fdtx%>>Sv1YDINP7&;oolZcyXmJ>De_=K@BoA@_loH~`ev z+Tw+;n<;`WI9$^9c9f;&I~2T=MjNvHNfY-fRu$4V3bwZw&5xMk>s5>|@dYhy-3E`hBH^|GlbqA)g}zWmWH$J%o!ZeDg%&I4)|%@3Cn-NJJtxrx#gY;eA7lGyFsZZrRlkiH>Hv`_6sU)kYs(uO0^{*Xs26DH$ z5&p8GDK$lKY;=@}M?LkWW+<|l)VM0A@?5t}5-I-03-w-^P+f_R#nA>?40*Vy{Z`Og zljzJVEvRFCS%6%~O!oY2tF`($$YqkrkTsm;x&)ipGf?Xo>7 zx~XOg7Rs4sPZco$jeL_jB2P?EZKzk*IimV9RxZP)@l+YU{Bk_iz3k z$1tw$NS>miqCfJMe{1Qal)+7eKqC7e*@wd%Q)g$%vA~Ae8x?Y};8SFD^!9p77RCmV zCjEE9?r!wCj3;YyQnWv6tl!55RNm`zj6h3ue*TR7GCB$@fJ<>Aqo=zY7+vY^i8j<9 zl?Qg4ckznRZ;PylGs;@yLtzthXOsY!(yqd;HT_J6-4X8 zg8I_f>wOKQsVgfXpw!pq@`Il~O$`)Zz~OM#3=DVdA1kMijin3>445}h%|z zy?xe2cXt$xJqwYRmi{_FPoVqQT^R?;HWz6kFJz45GRFo7@Exr86S#kZHpNy&zf0e)fGIeuvGn#2PJ`X)ei0SM!!>Nn9G)IZA zuCC6IT0+h!1v}Y4OKO@mAQgD9uW~pRxq*}=g)YFoq>Dj_Lg)N)r>BFU04{a z@@&LPe6)Y_bKnBN+N;o+1Dji0APf!ZI^pYhZGJ=yx7EDJnS62gkYsA--KMpN*XiBH z)uW3Mobra?h0j_R78XnpApRwjO;Jb_6!I<=A2Z~Km0jB1*=pD>m(&E7R&aYwe0FXw zWNR$|Bs-A2falbXz%#p`xxEP>nkvJ3Hguec7Vz@&@)IS?!I+V5mfI7@ zRFaK=A0{U!5B4cyzN~#%XSF3tI$h8fRsbKJpZBwKa0udT0a%F=l~_MMt-epw_H;a6 zR`f0NNPd9SJ!wp=ITh@W9k8q z2Rym{f#fA_|6I>2^WC+x&`Ng@O57?P7=+&oBXN0odAh^uAxTWVZ9vx~v!WcwRa+|q z(wa^|W-M&?Ow?)FKR|ZW(?-HacOx^)1gSXJvGo<2td@a6dA)u9oQ7Wl)(g45)B zgE2eGRcg24WBtC%(a|ztVPXH~<+V>wD}vFL$}~OA(-S9lSX*1iq@UjO8BTwDfRArN z{j34wzL)qPS}iQxo&0XDD**!Gyg+8nb4AQyk7^`3t*uA1B_;Ey73J|`x$z+@@sNWh zDhKSJV-3=^$7y_l@inpES0Z#r1G=k;6cwWk#m|f353{q2nww=rL_`{Uf>WGPJvBbQ zzBa#a(`YoH^BKF7kC&ju#l;}%<-iWdQ6a<*?ovisf{4;h6MA4wMkY)Q)CB4WF)^O; z&BW5uQk9dX3ldn%-tONqLjh>uy#xX`P-WM*%~FRjd~QVbo<`2Z&$D0lP4fMH!TaNV n*s-|(yjA%RyO{s~(%c=neK`Ysl~63$y+JUh7fmXR@Pz*Yw5`1? literal 0 HcmV?d00001 diff --git a/app/routers/weekly_tasks.py b/app/routers/weekly_tasks.py new file mode 100644 index 00000000..f1a84bcc --- /dev/null +++ b/app/routers/weekly_tasks.py @@ -0,0 +1,233 @@ +import datetime + +from fastapi import APIRouter, Depends, Request +from starlette.responses import RedirectResponse +from starlette.status import HTTP_302_FOUND + +from app.database.database import get_db +from app.database.models import User, Task, WeeklyTask +from app.dependencies import templates + + +router = APIRouter( + prefix="/weekly-tasks", + tags=["weekly-tasks"], + responses={404: {"description": "Not found"}}, +) + + +def get_demo_user(): + user = User( + username='demo_user', + email='demo@email.po', + password='s3jsd183b13', + full_name='The Demo' + ) + return user + + +def make_weekly_task(weekly_task, user, session): + user_titles = (weekly_tasks.title for weekly_tasks in user.weekly_tasks) + if weekly_task.title in user_titles: + return False + session.add(weekly_task) + session.commit() + return True + + +def make_task(task, user, session): + user_tasks_query = session.query(Task).filter_by(owner_id=user.id) + same_date_task = user_tasks_query.filter_by(date_time=task.date_time).first() + if not same_date_task: + session.add(task) + session.commit() + return True + return False + + +def set_demo_weekly_task(user, session): + weekly_task_demo_1 = WeeklyTask( + title="demo_test1", + days="Sun, Tue", + content="make the demo test 1", + is_important=True, + the_time="14:00", + owner_id=user.id + ) + weekly_task_demo_2 = WeeklyTask( + title="demo_test2", + days="Wed, Fri", + content="make the demo test 2", + is_important=False, + the_time="16:00", + owner_id=user.id + ) + + make_weekly_task(weekly_task_demo_1, user, session) + make_weekly_task(weekly_task_demo_2, user, session) + + +def generate_tasks(session, user): + + current_date = datetime.date.today() + current_week_num = current_date.strftime("%W") + current_year = current_date.strftime("%Y") + + for weekly_task in user.weekly_tasks: + the_time = weekly_task.the_time + days = weekly_task.days.split(", ") + for day in days: + date_string = f"{day} {the_time} {current_week_num} {current_year}" + date_time = datetime.datetime.strptime(date_string, "%a %H:%M %W %Y") + task = Task( + title=weekly_task.title, + content=weekly_task.content, + is_done=False, + is_important=weekly_task.is_important, + date_time=date_time, + owner_id=user.id + ) + make_task(task, user, session) + + +def get_user(demo_user, session): + user = session.query(User).filter_by(username=demo_user.username).first() + if not user: + session.add(demo_user) + session.commit() + user = session.query(User).filter_by(id=1).first() + return user + + +def remove_weekly_task(weekly_task, session): + if weekly_task: + session.query(WeeklyTask).filter_by(id=weekly_task.id).delete() + session.commit() + return True + return False + + +@router.get("/demo/remove") +async def weekly_tasks_demo_remove( + session=Depends(get_db), + demo_user=Depends(get_demo_user)): + + user = get_user(demo_user, session) + weekly_task = user.weekly_tasks + if weekly_task: + weekly_task = weekly_task[0] + removed = remove_weekly_task(weekly_task, session) + + return {"weekly_tasks_demo_remove": removed} + + +@router.get("/demo") +async def weekly_tasks_demo( + session=Depends(get_db), + demo_user=Depends(get_demo_user)): + + user = get_user(demo_user, session) + set_demo_weekly_task(user, session) + return {"set_demo_weekly_task": "True"} + + +@router.get("/") +async def weekly_tasks_manager( + request: Request, + session=Depends(get_db), + demo_user=Depends(get_demo_user)): + + user = get_user(demo_user, session) + generate_tasks(session, user) + + return templates.TemplateResponse("weekly_tasks_manager.html", { + "request": request, + "weekly_tasks": user.weekly_tasks + }) + + +@router.post("/add-weeklytask") +async def weekly_task_make_add( + request: Request, + session=Depends(get_db), + demo_user=Depends(get_demo_user)): + + user = get_user(demo_user, session) + data = await request.form() + + weekly_task = WeeklyTask( + title=data['title'], + days=data['days'], + content=data['content'], + is_important=data['is_important'], + the_time=data['the_time'], + owner_id=user.id + ) + + made = make_weekly_task(weekly_task, user, session) + if not made: + massage = "could not add The Weekly Task" + return templates.TemplateResponse("add_weekly_task.html", { + "request": request, + "massage": massage + }) + + url = router.url_path_for("weekly-tasks") + return RedirectResponse(url=url, status_code=HTTP_302_FOUND) + + +@router.get("/add") +async def weekly_task_add( + request: Request,): + + return templates.TemplateResponse("add_weekly_task.html", { + "request": request + }) + + +@router.post("/edit-weeklytask") +async def weekly_task_make_edit( + request: Request, + session=Depends(get_db), + demo_user=Depends(get_demo_user)): + + user = get_user(demo_user, session) + data = await request.form() + + weekly_task = WeeklyTask( + title=data['title'], + days=data['days'], + content=data['content'], + is_important=data['is_important'], + the_time=data['the_time'], + owner_id=user.id + ) + + made = make_weekly_task(weekly_task, user, session) + + if not made: + massage = "These changes could not be made to the Weekly Task" + return templates.TemplateResponse("add_weekly_task.html", { + "request": request, + "massage": massage, + "weekly_task": weekly_task + }) + + session.query(WeeklyTask).filter_by(id=data['id']).delete() + session.commit() + url = router.url_path_for("weekly-tasks") + return RedirectResponse(url=url, status_code=HTTP_302_FOUND) + + +@router.post("/edit") +async def weekly_task_edit( + request: Request, + session=Depends(get_db),): + + data = await request.form() + weekly_task = session.query(WeeklyTask).filter_by(id=data['id']).first + + return templates.TemplateResponse("add_weekly_task.html", { + "request": request, + "weekly_task": weekly_task + }) \ No newline at end of file diff --git a/app/templates/add_weekly_task.html b/app/templates/add_weekly_task.html new file mode 100644 index 00000000..9d6e41ae --- /dev/null +++ b/app/templates/add_weekly_task.html @@ -0,0 +1,67 @@ +{% extends "base.html" %} + +{% block content %} + +
+

Add Weekly Tasks

+
+ +
+
+ + +
+ + +
+
    +
  • + + Sunday +
  • +
  • + + Monday +
  • +
  • + + Tuesday +
  • +
  • + + Wednesday +
  • +
  • + + Thursday +
  • +
  • + + Friday +
  • +
  • + + Saturday +
  • +
+
+ +
+ + +
+ +
+ Description: + +
+ +
+ + +
+ + +
+ +{% endblock %} \ No newline at end of file diff --git a/app/templates/weekly_tasks_manager.html b/app/templates/weekly_tasks_manager.html new file mode 100644 index 00000000..a4d61bca --- /dev/null +++ b/app/templates/weekly_tasks_manager.html @@ -0,0 +1,56 @@ +{% extends "base.html" %} + + +{% block content %} + +
+

Weekly Tasks

+
+ + +
+ + {% for weekly_task in weekly_tasks %} +
+
+ + Every: {{ weekly_task.days }} + at: {{ weekly_task.the_time }} + + + + + + + + +
+
+

+ {{ weekly_task.title }}:
{{ weekly_task.content }} +

+
+ important: {{ weekly_task.is_important }} +
+
+ {% endfor %} + +
+ + + + + + +{% endblock %} \ No newline at end of file From 75015bb8c581a3f29599462a1d879017f8440232 Mon Sep 17 00:00:00 2001 From: itzik Date: Tue, 26 Jan 2021 16:12:22 +0200 Subject: [PATCH 02/32] fix: made a connection between the HTML pages and the functions. deleted all the demo functions. Arrange the code to be clearer and shorter. --- app/routers/weekly_tasks.py | 227 ++++++++++++------------ app/templates/add_edit_weekly_task.html | 131 ++++++++++++++ app/templates/add_weekly_task.html | 67 ------- app/templates/weekly_tasks_manager.html | 29 ++- 4 files changed, 263 insertions(+), 191 deletions(-) create mode 100644 app/templates/add_edit_weekly_task.html delete mode 100644 app/templates/add_weekly_task.html diff --git a/app/routers/weekly_tasks.py b/app/routers/weekly_tasks.py index f1a84bcc..a8a17d24 100644 --- a/app/routers/weekly_tasks.py +++ b/app/routers/weekly_tasks.py @@ -1,6 +1,6 @@ import datetime -from fastapi import APIRouter, Depends, Request +from fastapi import APIRouter, Depends, Request, Form from starlette.responses import RedirectResponse from starlette.status import HTTP_302_FOUND @@ -27,14 +27,35 @@ def get_demo_user(): def make_weekly_task(weekly_task, user, session): + + # make more Conditions + user_titles = (weekly_tasks.title for weekly_tasks in user.weekly_tasks) if weekly_task.title in user_titles: return False + session.add(weekly_task) session.commit() return True +def change_weekly_task(weekly_task, user, session): + + # make more Conditions + + if not weekly_task.owner_id == user.id: + return False + + old_weekly_task = session.query(WeeklyTask).filter_by(id=weekly_task.id).first() + old_weekly_task.title = weekly_task.title + old_weekly_task.days = weekly_task.days + old_weekly_task.content = weekly_task.content + old_weekly_task.is_important = weekly_task.is_important + old_weekly_task.the_time = weekly_task.the_time + session.commit() + return True + + def make_task(task, user, session): user_tasks_query = session.query(Task).filter_by(owner_id=user.id) same_date_task = user_tasks_query.filter_by(date_time=task.date_time).first() @@ -45,28 +66,6 @@ def make_task(task, user, session): return False -def set_demo_weekly_task(user, session): - weekly_task_demo_1 = WeeklyTask( - title="demo_test1", - days="Sun, Tue", - content="make the demo test 1", - is_important=True, - the_time="14:00", - owner_id=user.id - ) - weekly_task_demo_2 = WeeklyTask( - title="demo_test2", - days="Wed, Fri", - content="make the demo test 2", - is_important=False, - the_time="16:00", - owner_id=user.id - ) - - make_weekly_task(weekly_task_demo_1, user, session) - make_weekly_task(weekly_task_demo_2, user, session) - - def generate_tasks(session, user): current_date = datetime.date.today() @@ -99,38 +98,15 @@ def get_user(demo_user, session): return user -def remove_weekly_task(weekly_task, session): +def remove_weekly_task(weekly_task_id, session): + weekly_task = session.query(WeeklyTask).filter_by(id=weekly_task_id).first() if weekly_task: - session.query(WeeklyTask).filter_by(id=weekly_task.id).delete() + session.query(WeeklyTask).filter_by(id=weekly_task_id).delete() session.commit() return True return False -@router.get("/demo/remove") -async def weekly_tasks_demo_remove( - session=Depends(get_db), - demo_user=Depends(get_demo_user)): - - user = get_user(demo_user, session) - weekly_task = user.weekly_tasks - if weekly_task: - weekly_task = weekly_task[0] - removed = remove_weekly_task(weekly_task, session) - - return {"weekly_tasks_demo_remove": removed} - - -@router.get("/demo") -async def weekly_tasks_demo( - session=Depends(get_db), - demo_user=Depends(get_demo_user)): - - user = get_user(demo_user, session) - set_demo_weekly_task(user, session) - return {"set_demo_weekly_task": "True"} - - @router.get("/") async def weekly_tasks_manager( request: Request, @@ -146,88 +122,107 @@ async def weekly_tasks_manager( }) -@router.post("/add-weeklytask") -async def weekly_task_make_add( - request: Request, - session=Depends(get_db), - demo_user=Depends(get_demo_user)): - - user = get_user(demo_user, session) - data = await request.form() - - weekly_task = WeeklyTask( - title=data['title'], - days=data['days'], - content=data['content'], - is_important=data['is_important'], - the_time=data['the_time'], - owner_id=user.id - ) - - made = make_weekly_task(weekly_task, user, session) - if not made: - massage = "could not add The Weekly Task" - return templates.TemplateResponse("add_weekly_task.html", { - "request": request, - "massage": massage - }) - - url = router.url_path_for("weekly-tasks") - return RedirectResponse(url=url, status_code=HTTP_302_FOUND) - - @router.get("/add") async def weekly_task_add( - request: Request,): + request: Request): - return templates.TemplateResponse("add_weekly_task.html", { - "request": request + return templates.TemplateResponse("add_edit_weekly_task.html", { + "request": request, + "weekly_task": None, + "mode": "add" }) -@router.post("/edit-weeklytask") -async def weekly_task_make_edit( +@router.post("/remove") +async def weekly_task_remove( request: Request, session=Depends(get_db), - demo_user=Depends(get_demo_user)): - - user = get_user(demo_user, session) - data = await request.form() + remove_id: int = Form(...)): - weekly_task = WeeklyTask( - title=data['title'], - days=data['days'], - content=data['content'], - is_important=data['is_important'], - the_time=data['the_time'], - owner_id=user.id - ) - - made = make_weekly_task(weekly_task, user, session) - - if not made: - massage = "These changes could not be made to the Weekly Task" - return templates.TemplateResponse("add_weekly_task.html", { - "request": request, - "massage": massage, - "weekly_task": weekly_task - }) - - session.query(WeeklyTask).filter_by(id=data['id']).delete() - session.commit() - url = router.url_path_for("weekly-tasks") + removed = remove_weekly_task(remove_id, session) + url = router.url_path_for("weekly_tasks_manager") return RedirectResponse(url=url, status_code=HTTP_302_FOUND) @router.post("/edit") async def weekly_task_edit( request: Request, - session=Depends(get_db),): + session=Depends(get_db), + edit_id: int = Form(...)): - data = await request.form() - weekly_task = session.query(WeeklyTask).filter_by(id=data['id']).first + weekly_task = session.query(WeeklyTask).filter_by(id=edit_id).first() - return templates.TemplateResponse("add_weekly_task.html", { + return templates.TemplateResponse("add_edit_weekly_task.html", { "request": request, - "weekly_task": weekly_task - }) \ No newline at end of file + "weekly_task": weekly_task, + "mode": "edit" + }) + +@router.post("/make-change") +async def weekly_task_make_change( + request: Request, + session=Depends(get_db), + demo_user=Depends(get_demo_user), + title: str = Form(...), + sun: bool = Form(False), + mon: bool = Form(False), + tue: bool = Form(False), + wed: bool = Form(False), + thu: bool = Form(False), + fri: bool = Form(False), + sat: bool = Form(False), + content: str = Form(...), + is_important: bool = Form(False), + the_time: datetime.time = Form(...), + weekly_task_id: int = Form(...), + mode: str = Form(...)): + + user = get_user(demo_user, session) + + days_dict = { + "Sun": sun, + "Mon": mon, + "Tue": tue, + "Wed": wed, + "Thu": thu, + "Fri": fri, + "Sat": sat + } + days_list = [day for day, is_true in days_dict.items() if is_true] + days = ", ".join(days_list) + + weekly_task = WeeklyTask( + title=title, + days=days, + content=content, + is_important=is_important, + the_time=the_time.strftime("%H:%M"), + owner_id=user.id + ) + if weekly_task_id: + weekly_task.id = weekly_task_id + + + if mode == "add": + made = make_weekly_task(weekly_task, user, session) + if not made: + massage = "could not add The Weekly Task" + return templates.TemplateResponse("add_edit_weekly_task.html", { + "request": request, + "massage": massage, + "weekly_task": weekly_task, + "mode": mode + }) + else: + changed = change_weekly_task(weekly_task, user, session) + if not changed: + massage = "These changes could not be made to the Weekly Task" + return templates.TemplateResponse("add_edit_weekly_task.html", { + "request": request, + "massage": massage, + "weekly_task": weekly_task, + "mode": mode + }) + + url = router.url_path_for("weekly_tasks_manager") + return RedirectResponse(url=url, status_code=HTTP_302_FOUND) \ No newline at end of file diff --git a/app/templates/add_edit_weekly_task.html b/app/templates/add_edit_weekly_task.html new file mode 100644 index 00000000..128f373b --- /dev/null +++ b/app/templates/add_edit_weekly_task.html @@ -0,0 +1,131 @@ +{% extends "base.html" %} + +{% block content %} + +
+ +

{{weekly_task.id}}

+ {% if mode == "edit" %} +

Edit Weekly Tasks

+ + {% set weekly_task_id = weekly_task.id %} + + {% else %} +

Add Weekly Tasks

+ + {% set weekly_task_id = "0" %} + + {% endif %} +
+ + {% if massage %} + + {% endif %} + + + {% if weekly_task %} + {% if "Sun" in weekly_task.days %} + {% set c_sun = "checked" %} + {% endif %} + + {% if "Mon" in weekly_task.days %} + {% set c_mon = "checked" %} + {% endif %} + + {% if "Tue" in weekly_task.days %} + {% set c_tue = "checked" %} + {% endif %} + + {% if "Wed" in weekly_task.days %} + {% set c_wed = "checked" %} + {% endif %} + + {% if "Thu" in weekly_task.days %} + {% set c_thu = "checked" %} + {% endif %} + + {% if "Fri" in weekly_task.days %} + {% set c_fri = "checked" %} + {% endif %} + + {% if "Sat" in weekly_task.days %} + {% set c_sat = "checked" %} + {% endif %} + + {% if weekly_task.is_important %} + {% set is_important = "checked" %} + {% endif %} + {% endif %} + + + +
+
+ + +
+ + + + +
+
    +
  • + + Sunday +
  • +
  • + + Monday +
  • +
  • + + Tuesday +
  • +
  • + + Wednesday +
  • +
  • + + Thursday +
  • +
  • + + Friday +
  • +
  • + + Saturday +
  • +
+
+ +
+ + +
+ +
+ Description: + +
+ + +
+ + +
+ + + + + + + + +
+ +{% endblock %} \ No newline at end of file diff --git a/app/templates/add_weekly_task.html b/app/templates/add_weekly_task.html deleted file mode 100644 index 9d6e41ae..00000000 --- a/app/templates/add_weekly_task.html +++ /dev/null @@ -1,67 +0,0 @@ -{% extends "base.html" %} - -{% block content %} - -
-

Add Weekly Tasks

-
- -
-
- - -
- - -
-
    -
  • - - Sunday -
  • -
  • - - Monday -
  • -
  • - - Tuesday -
  • -
  • - - Wednesday -
  • -
  • - - Thursday -
  • -
  • - - Friday -
  • -
  • - - Saturday -
  • -
-
- -
- - -
- -
- Description: - -
- -
- - -
- - -
- -{% endblock %} \ No newline at end of file diff --git a/app/templates/weekly_tasks_manager.html b/app/templates/weekly_tasks_manager.html index a4d61bca..6a843322 100644 --- a/app/templates/weekly_tasks_manager.html +++ b/app/templates/weekly_tasks_manager.html @@ -14,8 +14,8 @@

Weekly Tasks

- Every: {{ weekly_task.days }} - at: {{ weekly_task.the_time }} + Every: {{ weekly_task.days }} + at: {{ weekly_task.the_time }} @@ -25,10 +25,23 @@

Weekly Tasks

options - + + + +
@@ -36,7 +49,7 @@

Weekly Tasks

- {{ weekly_task.title }}:
{{ weekly_task.content }} + {{ weekly_task.title }}
{{ weekly_task.content }}


important: {{ weekly_task.is_important }} @@ -50,7 +63,7 @@

Weekly Tasks

{% endblock %} \ No newline at end of file From cad6d100f662d5a6034d643a75a5ce3dcdbff820 Mon Sep 17 00:00:00 2001 From: itzik Date: Wed, 27 Jan 2021 01:27:51 +0200 Subject: [PATCH 03/32] fix: Arrange the code in all the files and add a description to the code. and added wekly_tasks.py on the intertnal directory --- app/internal/weekly_tasks.py | 129 +++++++++++++++++++ app/routers/weekly_tasks.py | 160 +++++++----------------- app/templates/add_edit_weekly_task.html | 90 ++++++++----- app/templates/weekly_tasks_manager.html | 57 +++++---- 4 files changed, 263 insertions(+), 173 deletions(-) create mode 100644 app/internal/weekly_tasks.py diff --git a/app/internal/weekly_tasks.py b/app/internal/weekly_tasks.py new file mode 100644 index 00000000..6711c338 --- /dev/null +++ b/app/internal/weekly_tasks.py @@ -0,0 +1,129 @@ +from datetime import date ,datetime, time +from typing import Tuple + +from app.database.models import User, Task, WeeklyTask +from sqlalchemy.orm.session import Session + + +def check_inputs(days: str, the_time: time, title: str) -> bool: + """Checks inputs, used by the make_or_change_weekly_task function""" + if not days or days == "" or not the_time or not title or title == "": + return False + return True + + +def make_or_change_weekly_task( + user: User, session: Session, + mode: str, weekly_task_id: int, + title: str, days: str, + content: str, is_important: bool, + the_time: time) -> Tuple[bool, WeeklyTask]: + """This function is being used to add a Weekly Task to the user + or to edit an existing Weekly Task the user have. + + Args: + user (User): The user who wants to add or edit the Weekly Task. + session (Session): The session to redirect to the database. + mode (str): Determines whether in Add or Edit mode. + weekly_task_id (int): In edit mode, represents the weekly task being edited. + title (str): Title of the Weekly Task. + days (str): Return days of the Weekly Task. + content (str): Content of the Weekly Task. + is_important (bool): If the task is important. + the_time (time): Return time of the Weekly Task. + + Returns: + Tuple: Boolean variable which shows if the change has been made to the db. + and the model WeeklyTask which the function made so far. + """ + weekly_task = WeeklyTask( + title=title, + content=content, + is_important=is_important, + owner_id=user.id + ) + + if weekly_task_id: + weekly_task.id = weekly_task_id + + inputs_ok = check_inputs(days, the_time, title) + if not inputs_ok: + return False, weekly_task + + weekly_task.days = days + weekly_task.the_time = the_time.strftime("%H:%M") + + if mode == "add": + user_titles = (user_weekly_task.title for user_weekly_task in user.weekly_tasks) + if title in user_titles: + return False, weekly_task + session.add(weekly_task) + session.commit() + return True, weekly_task + + else: # if mode == "edit" + old_weekly_task = session.query(WeeklyTask).filter_by(id=weekly_task.id).first() + + user_titles = ( + user_weekly_task.title for user_weekly_task in user.weekly_tasks + if user_weekly_task.title != old_weekly_task.title + ) + + if title in user_titles: + return False, weekly_task + + if old_weekly_task.owner_id != weekly_task.owner_id: + return False, weekly_task + + old_weekly_task.title = weekly_task.title + old_weekly_task.days = weekly_task.days + old_weekly_task.content = weekly_task.content + old_weekly_task.is_important = weekly_task.is_important + old_weekly_task.the_time = weekly_task.the_time + session.commit() + return True, weekly_task + + +def make_task(task: Task, user: User, session: Session) -> bool: + """Make a task, used by the generate_tasks function""" + user_tasks_query = session.query(Task).filter_by(owner_id=user.id) + task_exist = user_tasks_query.filter_by(date_time=task.date_time, title=task.title).first() + if not task_exist: + session.add(task) + session.commit() + return True + return False + + +def generate_tasks(session: Session, user: User): + """Generates tasks for the week + based on all the weekly tasks the user have""" + current_date = date.today() + current_week_num = current_date.strftime("%W") + current_year = current_date.strftime("%Y") + + for weekly_task in user.weekly_tasks: + the_time = weekly_task.the_time + days = weekly_task.days.split(", ") + for day in days: + date_string = f"{day} {the_time} {current_week_num} {current_year}" + date_time = datetime.strptime(date_string, "%a %H:%M %W %Y") + task = Task( + title=weekly_task.title, + content=weekly_task.content, + is_done=False, + is_important=weekly_task.is_important, + date_time=date_time, + owner_id=user.id + ) + make_task(task, user, session) + + +def remove_weekly_task(weekly_task_id: int, session: Session) -> bool: + """Removes a weekly task from the db based on the weekly task id""" + weekly_task = session.query(WeeklyTask).filter_by(id=weekly_task_id).first() + if weekly_task: + session.query(WeeklyTask).filter_by(id=weekly_task_id).delete() + session.commit() + return True + return False \ No newline at end of file diff --git a/app/routers/weekly_tasks.py b/app/routers/weekly_tasks.py index a8a17d24..6686be90 100644 --- a/app/routers/weekly_tasks.py +++ b/app/routers/weekly_tasks.py @@ -5,8 +5,9 @@ from starlette.status import HTTP_302_FOUND from app.database.database import get_db -from app.database.models import User, Task, WeeklyTask +from app.database.models import User, WeeklyTask from app.dependencies import templates +from app.internal.weekly_tasks import generate_tasks, make_or_change_weekly_task, remove_weekly_task router = APIRouter( @@ -16,7 +17,7 @@ ) -def get_demo_user(): +def get_placeholder_user(): user = User( username='demo_user', email='demo@email.po', @@ -26,69 +27,6 @@ def get_demo_user(): return user -def make_weekly_task(weekly_task, user, session): - - # make more Conditions - - user_titles = (weekly_tasks.title for weekly_tasks in user.weekly_tasks) - if weekly_task.title in user_titles: - return False - - session.add(weekly_task) - session.commit() - return True - - -def change_weekly_task(weekly_task, user, session): - - # make more Conditions - - if not weekly_task.owner_id == user.id: - return False - - old_weekly_task = session.query(WeeklyTask).filter_by(id=weekly_task.id).first() - old_weekly_task.title = weekly_task.title - old_weekly_task.days = weekly_task.days - old_weekly_task.content = weekly_task.content - old_weekly_task.is_important = weekly_task.is_important - old_weekly_task.the_time = weekly_task.the_time - session.commit() - return True - - -def make_task(task, user, session): - user_tasks_query = session.query(Task).filter_by(owner_id=user.id) - same_date_task = user_tasks_query.filter_by(date_time=task.date_time).first() - if not same_date_task: - session.add(task) - session.commit() - return True - return False - - -def generate_tasks(session, user): - - current_date = datetime.date.today() - current_week_num = current_date.strftime("%W") - current_year = current_date.strftime("%Y") - - for weekly_task in user.weekly_tasks: - the_time = weekly_task.the_time - days = weekly_task.days.split(", ") - for day in days: - date_string = f"{day} {the_time} {current_week_num} {current_year}" - date_time = datetime.datetime.strptime(date_string, "%a %H:%M %W %Y") - task = Task( - title=weekly_task.title, - content=weekly_task.content, - is_done=False, - is_important=weekly_task.is_important, - date_time=date_time, - owner_id=user.id - ) - make_task(task, user, session) - - def get_user(demo_user, session): user = session.query(User).filter_by(username=demo_user.username).first() if not user: @@ -98,23 +36,14 @@ def get_user(demo_user, session): return user -def remove_weekly_task(weekly_task_id, session): - weekly_task = session.query(WeeklyTask).filter_by(id=weekly_task_id).first() - if weekly_task: - session.query(WeeklyTask).filter_by(id=weekly_task_id).delete() - session.commit() - return True - return False - - @router.get("/") -async def weekly_tasks_manager( +def weekly_tasks_manager( request: Request, session=Depends(get_db), - demo_user=Depends(get_demo_user)): + demo_user=Depends(get_placeholder_user)): user = get_user(demo_user, session) - generate_tasks(session, user) + # generate_tasks(session, user) return templates.TemplateResponse("weekly_tasks_manager.html", { "request": request, @@ -123,7 +52,7 @@ async def weekly_tasks_manager( @router.get("/add") -async def weekly_task_add( +def weekly_task_add( request: Request): return templates.TemplateResponse("add_edit_weekly_task.html", { @@ -134,36 +63,35 @@ async def weekly_task_add( @router.post("/remove") -async def weekly_task_remove( - request: Request, +def weekly_task_remove( session=Depends(get_db), remove_id: int = Form(...)): - removed = remove_weekly_task(remove_id, session) + remove_weekly_task(remove_id, session) url = router.url_path_for("weekly_tasks_manager") return RedirectResponse(url=url, status_code=HTTP_302_FOUND) @router.post("/edit") -async def weekly_task_edit( +def weekly_task_edit( request: Request, session=Depends(get_db), edit_id: int = Form(...)): weekly_task = session.query(WeeklyTask).filter_by(id=edit_id).first() - return templates.TemplateResponse("add_edit_weekly_task.html", { "request": request, "weekly_task": weekly_task, "mode": "edit" }) + @router.post("/make-change") -async def weekly_task_make_change( +def weekly_task_make_change( request: Request, session=Depends(get_db), - demo_user=Depends(get_demo_user), - title: str = Form(...), + demo_user=Depends(get_placeholder_user), + title: str = Form(None), sun: bool = Form(False), mon: bool = Form(False), tue: bool = Form(False), @@ -171,14 +99,13 @@ async def weekly_task_make_change( thu: bool = Form(False), fri: bool = Form(False), sat: bool = Form(False), - content: str = Form(...), + content: str = Form(None), is_important: bool = Form(False), - the_time: datetime.time = Form(...), + the_time: datetime.time = Form(None), weekly_task_id: int = Form(...), mode: str = Form(...)): user = get_user(demo_user, session) - days_dict = { "Sun": sun, "Mon": mon, @@ -191,38 +118,35 @@ async def weekly_task_make_change( days_list = [day for day, is_true in days_dict.items() if is_true] days = ", ".join(days_list) - weekly_task = WeeklyTask( - title=title, - days=days, - content=content, - is_important=is_important, - the_time=the_time.strftime("%H:%M"), - owner_id=user.id + made_change, weekly_task = make_or_change_weekly_task( + user, session, + mode, weekly_task_id, + title, days, + content, is_important, + the_time, ) - if weekly_task_id: - weekly_task.id = weekly_task_id - + massage = None if mode == "add": - made = make_weekly_task(weekly_task, user, session) - if not made: - massage = "could not add The Weekly Task" - return templates.TemplateResponse("add_edit_weekly_task.html", { - "request": request, - "massage": massage, - "weekly_task": weekly_task, - "mode": mode - }) + massage = "could not add The Weekly Task" else: - changed = change_weekly_task(weekly_task, user, session) - if not changed: - massage = "These changes could not be made to the Weekly Task" - return templates.TemplateResponse("add_edit_weekly_task.html", { - "request": request, - "massage": massage, - "weekly_task": weekly_task, - "mode": mode - }) + massage = "These changes could not be made to the Weekly Task" + + if not made_change: + massage = "could not add The Weekly Task" + return templates.TemplateResponse("add_edit_weekly_task.html", { + "request": request, + "massage": massage, + "weekly_task": weekly_task, + "mode": mode + }) url = router.url_path_for("weekly_tasks_manager") - return RedirectResponse(url=url, status_code=HTTP_302_FOUND) \ No newline at end of file + return RedirectResponse(url=url, status_code=HTTP_302_FOUND) + + +# session = get_db() +# demo_user = get_placeholder_user() +# user = get_user(demo_user, session) + +# generate_tasks(session, user) \ No newline at end of file diff --git a/app/templates/add_edit_weekly_task.html b/app/templates/add_edit_weekly_task.html index 128f373b..92285571 100644 --- a/app/templates/add_edit_weekly_task.html +++ b/app/templates/add_edit_weekly_task.html @@ -3,21 +3,20 @@ {% block content %}
- -

{{weekly_task.id}}

{% if mode == "edit" %} +

Edit Weekly Tasks

- {% set weekly_task_id = weekly_task.id %} - + {% else %} +

Add Weekly Tasks

- {% set weekly_task_id = "0" %} {% endif %}
+ {% if massage %} {% endif %} - + {% if weekly_task %} + {% if weekly_task.is_important %} + {% set is_important = "checked" %} + {% endif %} - - {% if weekly_task.days %} - {% if "Sun" in weekly_task.days %} - {% set c_sun = "checked" %} - {% endif %} - - {% if "Mon" in weekly_task.days %} - {% set c_mon = "checked" %} - {% endif %} - - {% if "Tue" in weekly_task.days %} - {% set c_tue = "checked" %} - {% endif %} - - {% if "Wed" in weekly_task.days %} - {% set c_wed = "checked" %} - {% endif %} - - {% if "Thu" in weekly_task.days %} - {% set c_thu = "checked" %} - {% endif %} - - {% if "Fri" in weekly_task.days %} - {% set c_fri = "checked" %} - {% endif %} - - {% if "Sat" in weekly_task.days %} - {% set c_sat = "checked" %} - {% endif %} + + {% if weekly_task.title == None %} + {% set title = "" %} + {% else %} + {% set title = weekly_task.title %} {% endif %} - + - {% if weekly_task.is_important %} - {% set is_important = "checked" %} + + {% if weekly_task.content == None %} + {% set content = "" %} + {% else %} + {% set content = weekly_task.content %} {% endif %} + {% endif %} - - {% if weekly_task.title == None %} - {% set title = "" %} - {% else %} - {% set title = weekly_task.title %} - {% endif %} - - - - {% if weekly_task.content == None %} - {% set content = "" %} - {% else %} - {% set content = weekly_task.content %} - {% endif %} - -
@@ -94,34 +61,14 @@

Add Weekly Tasks

    -
  • - - Sunday -
  • -
  • - - Monday -
  • -
  • - - Tuesday -
  • -
  • - - Wednesday -
  • -
  • - - Thursday -
  • -
  • - - Friday -
  • -
  • - - Saturday -
  • + {% for day_full_name, day, is_checked in checked_days %} + +
  • + + {{ day_full_name }} +
  • + + {% endfor %}
diff --git a/tests/test_weekly_tasks.py b/tests/test_weekly_tasks.py index 01c5fae5..12243539 100644 --- a/tests/test_weekly_tasks.py +++ b/tests/test_weekly_tasks.py @@ -3,8 +3,8 @@ from app.database.models import Task from app.routers.weekly_tasks import get_placeholder_user from app.internal.weekly_tasks import ( - check_inputs, generate_tasks, make_task, remove_weekly_task, - get_w_t_from_input, make_weekly_task, change_weekly_task + check_inputs, generate_tasks, create_task, remove_weekly_task, + get_w_t_from_input, create_weekly_task, change_weekly_task ) @@ -183,7 +183,7 @@ def test_internal_weekly_tasks_check_inputs( assert ok -def test_internal_weekly_tasks_make_task(user, session): +def test_internal_weekly_tasks_create_task(user, session): date_time = datetime(2021, 1, 21, 3, 19) task = Task( title="task1", @@ -193,22 +193,22 @@ def test_internal_weekly_tasks_make_task(user, session): date_time=date_time, owner_id=user.id ) - made = make_task(task, user, session) + made = create_task(task, user, session) assert made - made = make_task(task, user, session) + made = create_task(task, user, session) assert not made made_task = user.tasks[0] assert made_task.date_time == date_time -def test_internal_make_weekly_task( +def test_internal_create_weekly_task( user, session, weekly_task ): # When successful on making the weekly task weekly_task.owner_id = user.id - made = make_weekly_task( + made = create_weekly_task( user, session, weekly_task ) @@ -221,7 +221,7 @@ def test_internal_make_weekly_task( assert user_w_t.the_time == weekly_task.the_time # When trying to add weekly task with the same title - made = make_weekly_task( + made = create_weekly_task( user, session, weekly_task ) @@ -229,7 +229,7 @@ def test_internal_make_weekly_task( # when there is no title weekly_task.title = None - made = make_weekly_task( + made = create_weekly_task( user, session, weekly_task ) @@ -249,7 +249,7 @@ def test_internal_change_weekly_task( ): # making w_t for edit testing weekly_task.owner_id = user.id - made = make_weekly_task( + made = create_weekly_task( user, session, weekly_task ) @@ -257,7 +257,7 @@ def test_internal_change_weekly_task( # making another w_t for edit testing weekly_task2.owner_id = user.id - made = make_weekly_task( + made = create_weekly_task( user, session, weekly_task2 ) @@ -305,7 +305,7 @@ def test_internal_weekly_task_change_permission( ): # making the weekly task weekly_task.owner_id = user.id - made = make_weekly_task( + made = create_weekly_task( user, session, weekly_task ) @@ -367,7 +367,7 @@ def test_internal_remove_weekly_task( weekly_task ): weekly_task.owner_id = user.id - made = make_weekly_task( + made = create_weekly_task( user, session, weekly_task ) @@ -393,7 +393,7 @@ def test_internal_weekly_tasks_generate_tasks( weekly_task ): weekly_task.owner_id = user.id - made = make_weekly_task( + made = create_weekly_task( user, session, weekly_task ) diff --git a/tests/weekly_tasks_fixture.py b/tests/weekly_tasks_fixture.py index 9303d441..dd769d86 100644 --- a/tests/weekly_tasks_fixture.py +++ b/tests/weekly_tasks_fixture.py @@ -83,7 +83,6 @@ def get_weekly_task_id( while True: get_title_from_db = w_t_from_db_gen( my_session, title=w_t.title) - print(w_t.title) w_task_from_db = next(get_title_from_db) w_task_id = w_task_from_db.id yield w_task_id From 3eede59360227c8f58b6912328151b65ea441f39 Mon Sep 17 00:00:00 2001 From: itzik Date: Thu, 4 Feb 2021 03:04:07 +0200 Subject: [PATCH 15/32] fix: improved code for requested changes --- app/internal/weekly_tasks.py | 30 +++++++---- app/routers/weekly_tasks.py | 67 +++++++++++++----------- tests/client_fixture.py | 6 +-- tests/test_weekly_tasks.py | 98 ++++++++++++++++++++--------------- tests/weekly_tasks_fixture.py | 21 ++++---- 5 files changed, 128 insertions(+), 94 deletions(-) diff --git a/app/internal/weekly_tasks.py b/app/internal/weekly_tasks.py index 5742eb50..656b3f82 100644 --- a/app/internal/weekly_tasks.py +++ b/app/internal/weekly_tasks.py @@ -1,16 +1,18 @@ from datetime import date, datetime, time from typing import Iterator +from fastapi import Depends +from app.database.database import get_db from app.database.models import User, Task, WeeklyTask from sqlalchemy.orm.session import Session def check_inputs(days: str, the_time: time, title: str) -> bool: - """Checks inputs, used by the get_w_t_from_input function""" + """Checks inputs, used by the weekly_task_from_input function""" return days and the_time and title -def get_w_t_from_input( +def weekly_task_from_input( user: User, title: str, days: str, content: str, the_time: time, @@ -51,8 +53,9 @@ def get_w_t_from_input( def create_weekly_task( - user: User, session: Session, - weekly_task: WeeklyTask + user: User, + weekly_task: WeeklyTask, + session: Session = Depends(get_db) ) -> bool: """This function is being used to add a Weekly Task to the user. @@ -78,8 +81,9 @@ def create_weekly_task( def change_weekly_task( - user: User, session: Session, - weekly_task: WeeklyTask + user: User, + weekly_task: WeeklyTask, + session: Session = Depends(get_db) ) -> bool: """This function is being used to edit a Weekly Task the user have. @@ -117,7 +121,10 @@ def change_weekly_task( return True -def create_task(task: Task, user: User, session: Session) -> bool: +def create_task( + task: Task, user: User, + session: Session = Depends(get_db) +) -> bool: """Make a task, used by the generate_tasks function""" user_tasks_query = session.query(Task).filter_by(owner_id=user.id) task_by_time = user_tasks_query.filter_by(date_time=task.date_time) @@ -140,7 +147,9 @@ def get_datetime(day: str, the_time: str) -> datetime: return datetime.strptime(date_string, "%a %H:%M %W %Y") -def generate_tasks(session: Session, user: User) -> Iterator[bool]: +def generate_tasks( + user: User, session: Session = Depends(get_db) +) -> Iterator[bool]: """Generates tasks for the week based on all the weekly tasks the user have""" for weekly_task in user.weekly_tasks: @@ -160,7 +169,10 @@ def generate_tasks(session: Session, user: User) -> Iterator[bool]: yield False -def remove_weekly_task(weekly_task_id: int, session: Session) -> bool: +def remove_weekly_task( + weekly_task_id: int, + session: Session = Depends(get_db) +) -> bool: """Removes a weekly task from the db based on the weekly task id""" weekly_task_query = session.query(WeeklyTask) weekly_task = weekly_task_query.filter_by(id=weekly_task_id).first() diff --git a/app/routers/weekly_tasks.py b/app/routers/weekly_tasks.py index c3dd5517..3017d933 100644 --- a/app/routers/weekly_tasks.py +++ b/app/routers/weekly_tasks.py @@ -1,6 +1,9 @@ +import calendar import datetime +from typing import List, Tuple from fastapi import APIRouter, Depends, Request, Form +from sqlalchemy.orm.session import Session from starlette.responses import RedirectResponse from starlette.status import HTTP_302_FOUND @@ -8,7 +11,7 @@ from app.database.models import User, WeeklyTask from app.dependencies import templates from app.internal.weekly_tasks import ( - remove_weekly_task, get_w_t_from_input, + remove_weekly_task, weekly_task_from_input, create_weekly_task, change_weekly_task) @@ -19,7 +22,7 @@ ) -def get_placeholder_user(): +def get_placeholder_user() -> User: user = User( username='demo_user', email='demo@email.po', @@ -29,48 +32,52 @@ def get_placeholder_user(): return user -def get_user(demo_user, session): - user = session.query(User).filter_by(username=demo_user.username).first() +def get_user( + demo_user: User, + session: Session = Depends(get_db) +) -> User: + demo_username = demo_user.username + user = session.query(User).filter_by(username=demo_username).first() if not user: session.add(demo_user) session.commit() - user = session.query(User).filter_by(id=1).first() + user_query = session.query(User) + user = user_query.filter_by(username=demo_username).first() return user -def get_checked_days(days=""): +def get_checked_days(days: str = "") -> List[Tuple[str, str, str]]: + """Produces the input checked_days for the template add_edit_weekly_task""" days_list = days.split(", ") - day_names = { - 'Sun': 'Sunday', - 'Mon': 'Monday', - 'Tue': 'Tuesday', - 'Wed': 'Wednesday', - 'Thu': 'Thursday', - 'Fri': 'Friday', - 'Sat': 'Saturday' - } checked_days = [] - for day, day_full_name in day_names.items(): + for day_full_name in calendar.day_name: + day = day_full_name[:3] + day_lower = day.lower() if day in days_list: - day = day.lower() - checked_days.append((day_full_name, day, "checked")) + checked_days.append((day_full_name, day_lower, "checked")) else: - day = day.lower() - checked_days.append((day_full_name, day, "")) + checked_days.append((day_full_name, day_lower, "")) return checked_days -def get_days(sun, mon, tue, wed, thu, fri, sat): +def get_days_string( + sun: bool, mon: bool, + tue: bool, wed: bool, + thu: bool, fri: bool, + sat: bool +) -> str: + """Produces a string of all the days that were checked, + For use in the model weekly tasks.""" days_dict = { - "Sun": sun, "Mon": mon, "Tue": tue, "Wed": wed, "Thu": thu, "Fri": fri, - "Sat": sat + "Sat": sat, + "Sun": sun } - days_list = [day for day, is_true in days_dict.items() if is_true] + days_list = [day for day, is_checked in days_dict.items() if is_checked] days = ", ".join(days_list) return days @@ -84,11 +91,11 @@ def weekly_tasks_manager( user = get_user(demo_user, session) # TODO: Move the below function to a compatible location - # Need to run regularly whenever there are no tasks on the week + # Need to run regularly whenever there are tasks on the week # Or will run on the background after the user left the # weekly-tasks manager page # function: - # generate_tasks(session, user) # imported from app.internal.weekly_tasks + # generate_tasks(user, session) # imported from app.internal.weekly_tasks # session.close() return templates.TemplateResponse("weekly_tasks_manager.html", { @@ -156,11 +163,11 @@ def weekly_task_make_change( mode: str = Form(...)): user = get_user(demo_user, session) - days = get_days( + days = get_days_string( sun, mon, tue, wed, thu, fri, sat ) - weekly_task = get_w_t_from_input( + weekly_task = weekly_task_from_input( user, title, days, content, the_time, @@ -173,12 +180,12 @@ def weekly_task_make_change( if mode == "add": massage = "could not add The Weekly Task" made_change = create_weekly_task( - user, session, weekly_task + user, weekly_task, session ) else: # mode == "edit" massage = "These changes could not be made to the Weekly Task" made_change = change_weekly_task( - user, session, weekly_task + user, weekly_task, session ) if not made_change: diff --git a/tests/client_fixture.py b/tests/client_fixture.py index 1325ef91..0bdeae0c 100644 --- a/tests/client_fixture.py +++ b/tests/client_fixture.py @@ -5,7 +5,7 @@ from app.database.database import Base from app.database.models import User from app.main import app -from app.routers import agenda, event, invitation, profile +from app.routers import agenda, event, invitation, profile, weekly_tasks from tests.conftest import get_test_db, test_engine @@ -62,9 +62,9 @@ def profile_test_client(): @pytest.fixture(scope="session") def weekly_tasks_test_client(): Base.metadata.create_all(bind=test_engine) - app.dependency_overrides[profile.get_db] = get_test_db + app.dependency_overrides[weekly_tasks.get_db] = get_test_db app.dependency_overrides[ - profile.get_placeholder_user] = get_test_placeholder_user + weekly_tasks.get_placeholder_user] = get_test_placeholder_user with TestClient(app) as client: yield client diff --git a/tests/test_weekly_tasks.py b/tests/test_weekly_tasks.py index 12243539..7c8a4b36 100644 --- a/tests/test_weekly_tasks.py +++ b/tests/test_weekly_tasks.py @@ -4,7 +4,7 @@ from app.routers.weekly_tasks import get_placeholder_user from app.internal.weekly_tasks import ( check_inputs, generate_tasks, create_task, remove_weekly_task, - get_w_t_from_input, create_weekly_task, change_weekly_task + weekly_task_from_input, create_weekly_task, change_weekly_task ) @@ -70,17 +70,17 @@ def test_weekly_tasks_edit( weekly_tasks_test_client, weekly_task, session, input_weekly_task, - w_tasks_from_db_gen, + weekly_task_from_db_gen, weekly_task_id_gen ): - get_w_task_id = weekly_task_id_gen( - w_tasks_from_db_gen, + get_weekly_task_id = weekly_task_id_gen( + weekly_task_from_db_gen, session, - weekly_task + weekly_task.title ) # Get weekly tasks id from db for edit - w_task_id = next(get_w_task_id) + w_task_id = next(get_weekly_task_id) data = weekly_tasks_test_client.post( '/weekly-tasks/edit', @@ -134,15 +134,16 @@ def test_weekly_tasks_edit( def test_weekly_tasks_remove( weekly_tasks_test_client, session, input_weekly_task, weekly_task, - w_tasks_from_db_gen, + weekly_task_from_db_gen, weekly_task_id_gen ): - get_w_t_from_db = w_tasks_from_db_gen( + get_weekly_task_from_db = weekly_task_from_db_gen( session, title=weekly_task.title) - get_w_task_id = weekly_task_id_gen( - w_tasks_from_db_gen, + + get_weekly_task_id = weekly_task_id_gen( + weekly_task_from_db_gen, session, - weekly_task + weekly_task.title ) # adds weekly_task @@ -152,7 +153,7 @@ def test_weekly_tasks_remove( '/weekly-tasks/make-change', data=input_weekly_task).content # get weekly task id for removal - w_task_id = next(get_w_task_id) + w_task_id = next(get_weekly_task_id) # removes weekly_task weekly_tasks_test_client.post( @@ -160,7 +161,7 @@ def test_weekly_tasks_remove( data={'remove_id': w_task_id}) # Checking if removed successfully - weekly_task_from_db = next(get_w_t_from_db) + weekly_task_from_db = next(get_weekly_task_from_db) data = weekly_tasks_test_client.get('/weekly-tasks').content assert b'Weekly Tasks' in data assert weekly_task_from_db is None @@ -209,8 +210,9 @@ def test_internal_create_weekly_task( # When successful on making the weekly task weekly_task.owner_id = user.id made = create_weekly_task( - user, session, - weekly_task + user, + weekly_task, + session ) assert made # the weekly task should be added to the db @@ -222,16 +224,18 @@ def test_internal_create_weekly_task( # When trying to add weekly task with the same title made = create_weekly_task( - user, session, - weekly_task + user, + weekly_task, + session ) assert not made # when there is no title weekly_task.title = None made = create_weekly_task( - user, session, - weekly_task + user, + weekly_task, + session ) assert not made @@ -250,16 +254,18 @@ def test_internal_change_weekly_task( # making w_t for edit testing weekly_task.owner_id = user.id made = create_weekly_task( - user, session, - weekly_task + user, + weekly_task, + session ) assert made # making another w_t for edit testing weekly_task2.owner_id = user.id made = create_weekly_task( - user, session, - weekly_task2 + user, + weekly_task2, + session ) assert made user_w_t = user.weekly_tasks @@ -275,25 +281,27 @@ def test_internal_change_weekly_task( weekly_task.content = "new content" changed = change_weekly_task( - user, session, - weekly_task + user, + weekly_task, + session ) assert changed changed_user_w_t = user.weekly_tasks[0] - assert changed_user_w_t.content == "new content" - assert changed_user_w_t.title == "new title" + assert changed_user_w_t.title == weekly_task.title + assert changed_user_w_t.content == weekly_task.content # When trying to edit weekly task for an existing title # weekly_task3.title == weekly_task2.title weekly_task3.owner_id = user.id weekly_task3.id = edit_id changed = change_weekly_task( - user, session, - weekly_task3 + user, + weekly_task3, + session ) assert not changed edited_w_t = user.weekly_tasks[0] - assert edited_w_t.title != "Test Task 2" + assert edited_w_t.title != weekly_task3.title def test_internal_weekly_task_change_permission( @@ -306,8 +314,9 @@ def test_internal_weekly_task_change_permission( # making the weekly task weekly_task.owner_id = user.id made = create_weekly_task( - user, session, - weekly_task + user, + weekly_task, + session ) assert made user_w_task = user.weekly_tasks[0] @@ -317,8 +326,9 @@ def test_internal_weekly_task_change_permission( weekly_task2.id = user_w_task.id weekly_task2.owner_id = user2.id changed = change_weekly_task( - user2, session, - weekly_task + user2, + weekly_task, + session ) assert not changed user_w_t = user.weekly_tasks[0] @@ -327,9 +337,9 @@ def test_internal_weekly_task_change_permission( assert user_w_t.is_important != weekly_task2.is_important -def test_get_w_t_from_input(user, weekly_task, weekly_task_time): +def test_weekly_task_from_input(user, weekly_task, weekly_task_time): # when all inputs are ok - w_t = get_w_t_from_input( + w_t = weekly_task_from_input( user, weekly_task.title, weekly_task.days, @@ -347,7 +357,7 @@ def test_get_w_t_from_input(user, weekly_task, weekly_task_time): assert w_t.the_time == weekly_task.the_time # when not all inputs are ok - w_t = get_w_t_from_input( + w_t = weekly_task_from_input( user, "", weekly_task.days, @@ -368,8 +378,9 @@ def test_internal_remove_weekly_task( ): weekly_task.owner_id = user.id made = create_weekly_task( - user, session, - weekly_task + user, + weekly_task, + session ) assert made @@ -394,13 +405,14 @@ def test_internal_weekly_tasks_generate_tasks( ): weekly_task.owner_id = user.id made = create_weekly_task( - user, session, - weekly_task + user, + weekly_task, + session ) assert made # Activates the generator - task_gen = generate_tasks(session, user) + task_gen = generate_tasks(user, session) tasks_added = [task_added for task_added in task_gen] # the number of days defined in the weekly task is 3 @@ -423,7 +435,7 @@ def test_internal_weekly_tasks_generate_tasks( # another activation at the same day # shouldn't affect the db # Only after a week new tasks should be added - task_gen = generate_tasks(session, user) + task_gen = generate_tasks(user, session) tasks_added = [task_added for task_added in task_gen] assert tasks_added.count(True) == 0 tasks = user.tasks diff --git a/tests/weekly_tasks_fixture.py b/tests/weekly_tasks_fixture.py index dd769d86..1c5fc623 100644 --- a/tests/weekly_tasks_fixture.py +++ b/tests/weekly_tasks_fixture.py @@ -8,7 +8,7 @@ def weekly_task(): return WeeklyTask( title="Test Task 1", - days="Sun, Mon, Sat", + days="Mon, Sat, Sun", content="my content", is_important=True, the_time="11:00" @@ -19,7 +19,7 @@ def weekly_task(): def weekly_task2(): return WeeklyTask( title="Test Task 2", - days="Sun, Sat", + days="Sat, Sun", content="my content2", is_important=False, the_time="12:00" @@ -71,21 +71,24 @@ def get_from_db(my_session, title=None): @pytest.fixture -def w_tasks_from_db_gen(): +def weekly_task_from_db_gen(): return get_from_db def get_weekly_task_id( - w_t_from_db_gen, + from_db_gen, my_session, - w_t + title ): while True: - get_title_from_db = w_t_from_db_gen( - my_session, title=w_t.title) + get_title_from_db = from_db_gen( + my_session, title=title) w_task_from_db = next(get_title_from_db) - w_task_id = w_task_from_db.id - yield w_task_id + if w_task_from_db: + w_task_id = w_task_from_db.id + yield w_task_id + else: + yield None @pytest.fixture From cb6836ffd52062bd14367c1314e3cbefdf3cd6e8 Mon Sep 17 00:00:00 2001 From: itzik Date: Sun, 7 Feb 2021 01:40:58 +0200 Subject: [PATCH 16/32] fix: improved code for requested changes --- app/internal/weekly_tasks.py | 1 - app/templates/add_edit_weekly_task.html | 15 +++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/app/internal/weekly_tasks.py b/app/internal/weekly_tasks.py index 656b3f82..d183752c 100644 --- a/app/internal/weekly_tasks.py +++ b/app/internal/weekly_tasks.py @@ -166,7 +166,6 @@ def generate_tasks( owner_id=user.id ) yield create_task(task, user, session) - yield False def remove_weekly_task( diff --git a/app/templates/add_edit_weekly_task.html b/app/templates/add_edit_weekly_task.html index 60697a00..769cd333 100644 --- a/app/templates/add_edit_weekly_task.html +++ b/app/templates/add_edit_weekly_task.html @@ -25,25 +25,16 @@

Add Weekly Tasks

{% if weekly_task %} + {% if weekly_task.is_important %} {% set is_important = "checked" %} {% endif %} - {% if weekly_task.title == None %} - {% set title = "" %} - {% else %} - {% set title = weekly_task.title %} - {% endif %} - + {% set title = weekly_task.title or "" %} - {% if weekly_task.content == None %} - {% set content = "" %} - {% else %} - {% set content = weekly_task.content %} - {% endif %} - + {% set content = weekly_task.content or "" %} {% endif %} From 1855ce7cba98b1afafa5028d733e8213057d87a6 Mon Sep 17 00:00:00 2001 From: itzik Date: Sun, 7 Feb 2021 02:54:53 +0200 Subject: [PATCH 17/32] fix: minor change --- tests/test_weekly_tasks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_weekly_tasks.py b/tests/test_weekly_tasks.py index 7c8a4b36..33d04d89 100644 --- a/tests/test_weekly_tasks.py +++ b/tests/test_weekly_tasks.py @@ -413,7 +413,7 @@ def test_internal_weekly_tasks_generate_tasks( # Activates the generator task_gen = generate_tasks(user, session) - tasks_added = [task_added for task_added in task_gen] + tasks_added = list(task_gen) # the number of days defined in the weekly task is 3 assert tasks_added.count(True) == 3 @@ -436,7 +436,7 @@ def test_internal_weekly_tasks_generate_tasks( # shouldn't affect the db # Only after a week new tasks should be added task_gen = generate_tasks(user, session) - tasks_added = [task_added for task_added in task_gen] + tasks_added = list(task_gen) assert tasks_added.count(True) == 0 tasks = user.tasks assert len(tasks) == 3 From 2485084cb660871b9c637863dc10adc2b58f9bd7 Mon Sep 17 00:00:00 2001 From: itzik Date: Fri, 12 Feb 2021 04:51:39 +0200 Subject: [PATCH 18/32] fix: fixed for flake8 --- tests/client_fixture.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/client_fixture.py b/tests/client_fixture.py index 9404fb3e..bb6d005a 100644 --- a/tests/client_fixture.py +++ b/tests/client_fixture.py @@ -74,14 +74,14 @@ def profile_test_client() -> Iterator[TestClient]: @pytest.fixture(scope="session") def weekly_tasks_test_client(): Base.metadata.create_all(bind=test_engine) - app.dependency_overrides[weekly_tasks.get_db] = get_test_db - app.dependency_overrides[ + main.app.dependency_overrides[weekly_tasks.get_db] = get_test_db + main.app.dependency_overrides[ weekly_tasks.get_placeholder_user] = get_test_placeholder_user - with TestClient(app) as client: + with TestClient(main.app) as client: yield client - app.dependency_overrides = {} + main.app.dependency_overrides = {} Base.metadata.drop_all(bind=test_engine) From 4b3e3ee0582deb9a130375388fb84a5a3b09ac53 Mon Sep 17 00:00:00 2001 From: itzik Date: Fri, 12 Feb 2021 05:09:27 +0200 Subject: [PATCH 19/32] fix: fixed imports --- app/internal/weekly_tasks.py | 2 +- app/routers/weekly_tasks.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/internal/weekly_tasks.py b/app/internal/weekly_tasks.py index d183752c..441d66cd 100644 --- a/app/internal/weekly_tasks.py +++ b/app/internal/weekly_tasks.py @@ -2,8 +2,8 @@ from typing import Iterator from fastapi import Depends -from app.database.database import get_db from app.database.models import User, Task, WeeklyTask +from app.dependencies import get_db from sqlalchemy.orm.session import Session diff --git a/app/routers/weekly_tasks.py b/app/routers/weekly_tasks.py index 3017d933..7b278553 100644 --- a/app/routers/weekly_tasks.py +++ b/app/routers/weekly_tasks.py @@ -7,9 +7,8 @@ from starlette.responses import RedirectResponse from starlette.status import HTTP_302_FOUND -from app.database.database import get_db from app.database.models import User, WeeklyTask -from app.dependencies import templates +from app.dependencies import get_db, templates from app.internal.weekly_tasks import ( remove_weekly_task, weekly_task_from_input, create_weekly_task, change_weekly_task) From 62f2023fb0c62c30d1aad2df838401ff9ad5945f Mon Sep 17 00:00:00 2001 From: itzik Date: Sat, 13 Feb 2021 04:05:43 +0200 Subject: [PATCH 20/32] fix: fixed a mistake --- tests/client_fixture.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/client_fixture.py b/tests/client_fixture.py index bb6d005a..271fbb1c 100644 --- a/tests/client_fixture.py +++ b/tests/client_fixture.py @@ -85,5 +85,6 @@ def weekly_tasks_test_client(): Base.metadata.drop_all(bind=test_engine) +@pytest.fixture(scope="session") def salary_test_client() -> Iterator[TestClient]: yield from create_test_client(salary.get_db) From ce4bc71db20d669b638ffdbffe14b539634bbe5c Mon Sep 17 00:00:00 2001 From: itzik Date: Thu, 18 Feb 2021 18:24:07 +0200 Subject: [PATCH 21/32] fix: for flake8 --- tests/client_fixture.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/client_fixture.py b/tests/client_fixture.py index b0e9027d..2f00a51b 100644 --- a/tests/client_fixture.py +++ b/tests/client_fixture.py @@ -95,7 +95,7 @@ def weekly_tasks_test_client(): main.app.dependency_overrides = {} Base.metadata.drop_all(bind=test_engine) - + @pytest.fixture(scope="session") def security_test_client(): From bd8147c9612fb23934228613b925d7a7274f2085 Mon Sep 17 00:00:00 2001 From: itzik Date: Sun, 21 Feb 2021 02:28:01 +0200 Subject: [PATCH 22/32] fix: improved code for requested changes --- app/internal/weekly_tasks.py | 15 +- app/routers/weekly_tasks.py | 53 +-- app/templates/add_edit_weekly_task.html | 12 +- app/templates/weekly_tasks_manager.html | 27 +- tests/test_weekly_tasks.py | 442 ------------------------ tests/test_weekly_tasks_internal.py | 258 ++++++++++++++ tests/test_weekly_tasks_route.py | 149 ++++++++ tests/user_fixture.py | 2 +- tests/weekly_tasks_fixture.py | 37 -- 9 files changed, 463 insertions(+), 532 deletions(-) delete mode 100644 tests/test_weekly_tasks.py create mode 100644 tests/test_weekly_tasks_internal.py create mode 100644 tests/test_weekly_tasks_route.py diff --git a/app/internal/weekly_tasks.py b/app/internal/weekly_tasks.py index 441d66cd..20497124 100644 --- a/app/internal/weekly_tasks.py +++ b/app/internal/weekly_tasks.py @@ -1,9 +1,7 @@ from datetime import date, datetime, time from typing import Iterator -from fastapi import Depends from app.database.models import User, Task, WeeklyTask -from app.dependencies import get_db from sqlalchemy.orm.session import Session @@ -53,9 +51,8 @@ def weekly_task_from_input( def create_weekly_task( - user: User, - weekly_task: WeeklyTask, - session: Session = Depends(get_db) + user: User, weekly_task: WeeklyTask, + session: Session ) -> bool: """This function is being used to add a Weekly Task to the user. @@ -83,7 +80,7 @@ def create_weekly_task( def change_weekly_task( user: User, weekly_task: WeeklyTask, - session: Session = Depends(get_db) + session: Session ) -> bool: """This function is being used to edit a Weekly Task the user have. @@ -123,7 +120,7 @@ def change_weekly_task( def create_task( task: Task, user: User, - session: Session = Depends(get_db) + session: Session ) -> bool: """Make a task, used by the generate_tasks function""" user_tasks_query = session.query(Task).filter_by(owner_id=user.id) @@ -148,7 +145,7 @@ def get_datetime(day: str, the_time: str) -> datetime: def generate_tasks( - user: User, session: Session = Depends(get_db) + user: User, session: Session ) -> Iterator[bool]: """Generates tasks for the week based on all the weekly tasks the user have""" @@ -170,7 +167,7 @@ def generate_tasks( def remove_weekly_task( weekly_task_id: int, - session: Session = Depends(get_db) + session: Session ) -> bool: """Removes a weekly task from the db based on the weekly task id""" weekly_task_query = session.query(WeeklyTask) diff --git a/app/routers/weekly_tasks.py b/app/routers/weekly_tasks.py index 7b278553..19aaa921 100644 --- a/app/routers/weekly_tasks.py +++ b/app/routers/weekly_tasks.py @@ -5,7 +5,7 @@ from fastapi import APIRouter, Depends, Request, Form from sqlalchemy.orm.session import Session from starlette.responses import RedirectResponse -from starlette.status import HTTP_302_FOUND +from starlette.status import HTTP_302_FOUND, HTTP_303_SEE_OTHER from app.database.models import User, WeeklyTask from app.dependencies import get_db, templates @@ -18,6 +18,7 @@ prefix="/weekly-tasks", tags=["weekly-tasks"], responses={404: {"description": "Not found"}}, + dependencies=[Depends(get_db)] ) @@ -81,8 +82,8 @@ def get_days_string( return days -@router.get("/") -def weekly_tasks_manager( +@router.get('/') +async def weekly_tasks_manager( request: Request, session=Depends(get_db), demo_user=Depends(get_placeholder_user)): @@ -103,8 +104,8 @@ def weekly_tasks_manager( }) -@router.get("/add") -def weekly_task_add(request: Request): +@router.get('/add') +def add_weekly_task(request: Request): checked_days = get_checked_days() return templates.TemplateResponse("add_edit_weekly_task.html", { @@ -115,19 +116,19 @@ def weekly_task_add(request: Request): }) -@router.post("/delete") -def weekly_task_remove( - session=Depends(get_db), - remove_id: int = Form(...)): +@router.delete('/') +def delete_weekly_task( + remove_id: int, + session=Depends(get_db)): remove_weekly_task(remove_id, session) session.close() url = router.url_path_for("weekly_tasks_manager") - return RedirectResponse(url=url, status_code=HTTP_302_FOUND) + return RedirectResponse(url=url, status_code=HTTP_303_SEE_OTHER) -@router.post("/edit") -def weekly_task_edit( +@router.post('/edit') +def edit_weekly_task( request: Request, session=Depends(get_db), edit_id: int = Form(...)): @@ -142,8 +143,8 @@ def weekly_task_edit( }) -@router.post("/make-change") -def weekly_task_make_change( +@router.post('/execute') +def weekly_task_execute( request: Request, session=Depends(get_db), demo_user=Depends(get_placeholder_user), @@ -167,31 +168,35 @@ def weekly_task_make_change( ) weekly_task = weekly_task_from_input( - user, - title, days, + user, title, days, content, the_time, is_important, weekly_task_id=weekly_task_id ) - made_change = False - massage = None + fail_massage = None + executed = False if mode == "add": - massage = "could not add The Weekly Task" - made_change = create_weekly_task( + fail_massage = "could not add The Weekly Task" + # creating the weekly task + created = create_weekly_task( user, weekly_task, session ) + executed = created + else: # mode == "edit" - massage = "These changes could not be made to the Weekly Task" - made_change = change_weekly_task( + fail_massage = "These changes could not be made to the Weekly Task" + # editing the weekly task + edited = change_weekly_task( user, weekly_task, session ) + executed = edited - if not made_change: + if not executed: checked_days = get_checked_days(days) return templates.TemplateResponse("add_edit_weekly_task.html", { "request": request, - "massage": massage, + "massage": fail_massage, "weekly_task": weekly_task, "mode": mode, "checked_days": checked_days diff --git a/app/templates/add_edit_weekly_task.html b/app/templates/add_edit_weekly_task.html index 769cd333..ff1e81ef 100644 --- a/app/templates/add_edit_weekly_task.html +++ b/app/templates/add_edit_weekly_task.html @@ -23,26 +23,20 @@

Add Weekly Tasks

{% endif %} - {% if weekly_task %} - {% if weekly_task.is_important %} {% set is_important = "checked" %} {% endif %} - {% set title = weekly_task.title or "" %} - {% set content = weekly_task.content or "" %} {% endif %} - - + -
@@ -63,19 +57,16 @@

Add Weekly Tasks

-
-
Description:
-
@@ -83,7 +74,6 @@

Add Weekly Tasks

- diff --git a/app/templates/weekly_tasks_manager.html b/app/templates/weekly_tasks_manager.html index 1a6eb9a1..2019b051 100644 --- a/app/templates/weekly_tasks_manager.html +++ b/app/templates/weekly_tasks_manager.html @@ -1,6 +1,5 @@ {% extends "base.html" %} - {% block content %}
@@ -31,14 +30,16 @@

Weekly Tasks

@@ -73,8 +74,18 @@

Weekly Tasks

-{% endblock %} \ No newline at end of file + +{% endblock %} diff --git a/tests/test_weekly_tasks.py b/tests/test_weekly_tasks.py deleted file mode 100644 index 33d04d89..00000000 --- a/tests/test_weekly_tasks.py +++ /dev/null @@ -1,442 +0,0 @@ -from datetime import datetime - -from app.database.models import Task -from app.routers.weekly_tasks import get_placeholder_user -from app.internal.weekly_tasks import ( - check_inputs, generate_tasks, create_task, remove_weekly_task, - weekly_task_from_input, create_weekly_task, change_weekly_task -) - - -def test_get_placeholder_user(): - user = get_placeholder_user() - assert user.username == 'demo_user' - assert user.email == 'demo@email.po' - assert user.password == 's3jsd183b13' - assert user.full_name == 'The Demo' - - -def test_weekly_tasks_manager(weekly_tasks_test_client): - # Get weekly-tasks page - data = weekly_tasks_test_client.get('/weekly-tasks').content - - # Verify that it is the page and there are no tasks - assert b'Weekly Tasks' in data - assert b'Test Task 1' not in data - - -def test_weekly_tasks_add( - weekly_tasks_test_client, - weekly_task, input_weekly_task -): - # Get add page - data = weekly_tasks_test_client.get('/weekly-tasks/add').content - # Verify that it is the add page - assert b'Add Weekly Tasks' in data - - # set weekly task data for failed attempt - weekly_task_data = { - 'title': weekly_task.title, - 'mode': 'add', - 'weekly_task_id': '0' - } - data = weekly_tasks_test_client.post( - '/weekly-tasks/make-change', data=weekly_task_data).content - # on failed attempt returns to add page - assert b'Add Weekly Tasks' in data - assert b'could not add The Weekly Task' in data - - # sets successful weekly task input - # Sets the input to add mode - input_weekly_task['mode'] = 'add' - input_weekly_task['weekly_task_id'] = '0' - data = weekly_tasks_test_client.post( - '/weekly-tasks/make-change', data=input_weekly_task).content - - # on successful attempt doesn't returns to add page - assert b'Add Weekly Tasks' not in data - - # Get weekly-tasks manager page - data = weekly_tasks_test_client.get('/weekly-tasks').content - # Checks that weekly task details are displayed - assert b'Weekly Tasks' in data - assert weekly_task.title.encode() in data - assert weekly_task.days.encode() in data - assert weekly_task.content.encode() in data - assert weekly_task.the_time.encode() in data - - -def test_weekly_tasks_edit( - weekly_tasks_test_client, weekly_task, - session, - input_weekly_task, - weekly_task_from_db_gen, - weekly_task_id_gen -): - get_weekly_task_id = weekly_task_id_gen( - weekly_task_from_db_gen, - session, - weekly_task.title - ) - - # Get weekly tasks id from db for edit - w_task_id = next(get_weekly_task_id) - - data = weekly_tasks_test_client.post( - '/weekly-tasks/edit', - data={"edit_id": w_task_id}).content - - # Checks that all weekly task details are displayed - assert b'Edit Weekly Tasks' in data - assert weekly_task.title.encode() in data - assert weekly_task.content.encode() in data - assert weekly_task.the_time.encode() in data - - # Sets the input to edit mode - input_weekly_task['mode'] = 'edit' - # Sets the id for edit - input_weekly_task['weekly_task_id'] = w_task_id - - # set weekly task input for failed attempt - input_weekly_task['title'] = "" - data = weekly_tasks_test_client.post( - '/weekly-tasks/make-change', data=input_weekly_task).content - # on failed attempt returns to edit page - assert b'Edit Weekly Tasks' in data - assert b'These changes could not be made to the Weekly Task' in data - assert weekly_task.title.encode() not in data - assert weekly_task.content.encode() in data - - # sets successful weekly task input - input_weekly_task['title'] = "Test Task 2" - input_weekly_task['fri'] = True - input_weekly_task['thu'] = True - input_weekly_task['sun'] = False - - data = weekly_tasks_test_client.post( - '/weekly-tasks/make-change', data=input_weekly_task).content - - # on successful attempt doesn't returns to add page - assert b'Edit Weekly Tasks' not in data - - # Get weekly-tasks manager page - data = weekly_tasks_test_client.get('/weekly-tasks').content - # Checks that all weekly task details are displayed correctly - assert b'Weekly Tasks' in data - assert weekly_task.title.encode() not in data - assert b'Test Task 2' in data - assert weekly_task.days.encode() not in data - assert b'Mon, Thu, Fri, Sat' in data - assert weekly_task.content.encode() in data - assert weekly_task.the_time.encode() in data - - -def test_weekly_tasks_remove( - weekly_tasks_test_client, session, - input_weekly_task, weekly_task, - weekly_task_from_db_gen, - weekly_task_id_gen -): - get_weekly_task_from_db = weekly_task_from_db_gen( - session, title=weekly_task.title) - - get_weekly_task_id = weekly_task_id_gen( - weekly_task_from_db_gen, - session, - weekly_task.title - ) - - # adds weekly_task - input_weekly_task['mode'] = 'add' - input_weekly_task['weekly_task_id'] = '0' - data = weekly_tasks_test_client.post( - '/weekly-tasks/make-change', data=input_weekly_task).content - - # get weekly task id for removal - w_task_id = next(get_weekly_task_id) - - # removes weekly_task - weekly_tasks_test_client.post( - '/weekly-tasks/delete', - data={'remove_id': w_task_id}) - - # Checking if removed successfully - weekly_task_from_db = next(get_weekly_task_from_db) - data = weekly_tasks_test_client.get('/weekly-tasks').content - assert b'Weekly Tasks' in data - assert weekly_task_from_db is None - assert weekly_task.title.encode() not in data - - -def test_internal_weekly_tasks_check_inputs( - weekly_task_time -): - ok = check_inputs( - days="", - the_time=None, - title="the title") - assert not ok - ok = check_inputs( - days="Sun", - the_time=weekly_task_time, - title="the title" - ) - assert ok - - -def test_internal_weekly_tasks_create_task(user, session): - date_time = datetime(2021, 1, 21, 3, 19) - task = Task( - title="task1", - content="my content", - is_done=False, - is_important=True, - date_time=date_time, - owner_id=user.id - ) - made = create_task(task, user, session) - assert made - made = create_task(task, user, session) - assert not made - made_task = user.tasks[0] - assert made_task.date_time == date_time - - -def test_internal_create_weekly_task( - user, - session, - weekly_task -): - # When successful on making the weekly task - weekly_task.owner_id = user.id - made = create_weekly_task( - user, - weekly_task, - session - ) - assert made - # the weekly task should be added to the db - user_w_t = user.weekly_tasks[0] - - assert user_w_t - assert user_w_t.content == weekly_task.content - assert user_w_t.the_time == weekly_task.the_time - - # When trying to add weekly task with the same title - made = create_weekly_task( - user, - weekly_task, - session - ) - assert not made - - # when there is no title - weekly_task.title = None - made = create_weekly_task( - user, - weekly_task, - session - ) - assert not made - - # The db user's weekly tasks should remain in quantity 1 - user_w_tasks = user.weekly_tasks - assert len(user_w_tasks) == 1 - - -def test_internal_change_weekly_task( - user, - session, - weekly_task, - weekly_task2, - weekly_task3 -): - # making w_t for edit testing - weekly_task.owner_id = user.id - made = create_weekly_task( - user, - weekly_task, - session - ) - assert made - - # making another w_t for edit testing - weekly_task2.owner_id = user.id - made = create_weekly_task( - user, - weekly_task2, - session - ) - assert made - user_w_t = user.weekly_tasks - assert len(user_w_t) == 2 - - # get weekly task id for edit - user_w_t = user.weekly_tasks[0] - edit_id = user_w_t.id - - # seting the weekly task for editing - weekly_task.id = edit_id - weekly_task.title = "new title" - weekly_task.content = "new content" - - changed = change_weekly_task( - user, - weekly_task, - session - ) - assert changed - changed_user_w_t = user.weekly_tasks[0] - assert changed_user_w_t.title == weekly_task.title - assert changed_user_w_t.content == weekly_task.content - - # When trying to edit weekly task for an existing title - # weekly_task3.title == weekly_task2.title - weekly_task3.owner_id = user.id - weekly_task3.id = edit_id - changed = change_weekly_task( - user, - weekly_task3, - session - ) - assert not changed - edited_w_t = user.weekly_tasks[0] - assert edited_w_t.title != weekly_task3.title - - -def test_internal_weekly_task_change_permission( - user, - user2, - session, - weekly_task, - weekly_task2 -): - # making the weekly task - weekly_task.owner_id = user.id - made = create_weekly_task( - user, - weekly_task, - session - ) - assert made - user_w_task = user.weekly_tasks[0] - assert user_w_task - - # another user trying to change the weekly task - weekly_task2.id = user_w_task.id - weekly_task2.owner_id = user2.id - changed = change_weekly_task( - user2, - weekly_task, - session - ) - assert not changed - user_w_t = user.weekly_tasks[0] - assert user_w_t.title != weekly_task2.title - assert user_w_t.content != weekly_task2.content - assert user_w_t.is_important != weekly_task2.is_important - - -def test_weekly_task_from_input(user, weekly_task, weekly_task_time): - # when all inputs are ok - w_t = weekly_task_from_input( - user, - weekly_task.title, - weekly_task.days, - weekly_task.content, - weekly_task_time, - weekly_task.is_important, - weekly_task_id=1 - ) - assert w_t - # all the weekly task data should be saved - assert w_t.title == weekly_task.title - assert w_t.days == weekly_task.days - assert w_t.content == weekly_task.content - assert w_t.is_important == weekly_task.is_important - assert w_t.the_time == weekly_task.the_time - - # when not all inputs are ok - w_t = weekly_task_from_input( - user, - "", - weekly_task.days, - weekly_task.content, - weekly_task_time, - weekly_task.is_important - ) - assert w_t - # As much data as possible is saved, except for time and days - assert w_t.content == weekly_task.content - assert w_t.days != weekly_task.days - assert w_t.the_time != weekly_task.the_time - - -def test_internal_remove_weekly_task( - user, session, - weekly_task -): - weekly_task.owner_id = user.id - made = create_weekly_task( - user, - weekly_task, - session - ) - assert made - - # Checks if the weekly task exists in the db - user_w_task = user.weekly_tasks[0] - assert user_w_task - # geting the id of the weekly task for removal - weekly_task_id = user_w_task.id - removed = remove_weekly_task(weekly_task_id, session) - assert removed - # Checks if the weekly task exists in the db after removal - assert not user.weekly_tasks - - # Trying to remove a weekly task that does not exists - removed = remove_weekly_task(weekly_task_id, session) - assert not removed - - -def test_internal_weekly_tasks_generate_tasks( - user, session, - weekly_task -): - weekly_task.owner_id = user.id - made = create_weekly_task( - user, - weekly_task, - session - ) - assert made - - # Activates the generator - task_gen = generate_tasks(user, session) - tasks_added = list(task_gen) - - # the number of days defined in the weekly task is 3 - assert tasks_added.count(True) == 3 - - tasks = user.tasks - # The number of tasks a user has should be - # the number of days defined in the weekly task - assert len(tasks) == 3 - # The Tasks should be defined according to the weekly task - for task in tasks: - assert weekly_task.title == task.title - assert weekly_task.content == task.content - assert weekly_task.is_important == task.is_important - time_string = task.date_time.strftime("%H:%M") - assert weekly_task.the_time == time_string - day = task.date_time.strftime("%a") - assert day in weekly_task.days - - # another activation at the same day - # shouldn't affect the db - # Only after a week new tasks should be added - task_gen = generate_tasks(user, session) - tasks_added = list(task_gen) - assert tasks_added.count(True) == 0 - tasks = user.tasks - assert len(tasks) == 3 diff --git a/tests/test_weekly_tasks_internal.py b/tests/test_weekly_tasks_internal.py new file mode 100644 index 00000000..5982d6e2 --- /dev/null +++ b/tests/test_weekly_tasks_internal.py @@ -0,0 +1,258 @@ +from datetime import datetime + +from app.database.models import Task +from app.internal.weekly_tasks import ( + check_inputs, generate_tasks, create_task, remove_weekly_task, + weekly_task_from_input, create_weekly_task, change_weekly_task +) + + +def test_weekly_tasks_check_inputs( + weekly_task_time +): + ok = check_inputs( + days="", + the_time=None, + title="the title") + assert not ok + ok = check_inputs( + days="Sun", + the_time=weekly_task_time, + title="the title" + ) + assert ok + + +def test_weekly_tasks_create_task(user, session): + date_time = datetime(2021, 1, 21, 3, 19) + task = Task( + title="task1", + content="my content", + is_done=False, + is_important=True, + date_time=date_time, + owner_id=user.id + ) + created = create_task(task, user, session) + assert created + created = create_task(task, user, session) + assert not created + created_task = user.tasks[0] + assert created_task.date_time == date_time + + +def test_create_weekly_task( + user, session, weekly_task +): + # creating the weekly task + weekly_task.owner_id = user.id + created = create_weekly_task( + user, + weekly_task, + session + ) + assert created + # checks if weekly task been added to the db + user_w_t = user.weekly_tasks[0] + assert user_w_t + assert user_w_t.content == weekly_task.content + assert user_w_t.the_time == weekly_task.the_time + + # trying to add weekly task with the same title + created = create_weekly_task( + user, + weekly_task, + session + ) + assert not created + + # adding without a title + weekly_task.title = None + created = create_weekly_task( + user, + weekly_task, + session + ) + assert not created + + # the user's weekly tasks should remain in quantity 1 + user_w_tasks = user.weekly_tasks + assert len(user_w_tasks) == 1 + + +def test_change_weekly_task( + user, session, weekly_task, + weekly_task2, weekly_task3 +): + # creating weekly task for edit testing + weekly_task.owner_id = user.id + created = create_weekly_task( + user, + weekly_task, + session + ) + assert created + + # creating another weekly task for edit testing + weekly_task2.owner_id = user.id + created = create_weekly_task( + user, + weekly_task2, + session + ) + assert created + user_w_t = user.weekly_tasks + assert len(user_w_t) == 2 + + # get weekly task id for edit + user_w_t = user.weekly_tasks[0] + edit_id = user_w_t.id + + # seting the weekly task for editing + weekly_task.id = edit_id + weekly_task.title = "new title" + weekly_task.content = "new content" + + changed = change_weekly_task( + user, weekly_task, session + ) + assert changed + changed_user_w_t = user.weekly_tasks[0] + assert changed_user_w_t.title == weekly_task.title + assert changed_user_w_t.content == weekly_task.content + + # trying to edit weekly task for an existing title + # weekly_task3.title == weekly_task2.title + weekly_task3.owner_id = user.id + weekly_task3.id = edit_id + changed = change_weekly_task( + user, weekly_task3, session + ) + assert not changed + edited_w_t = user.weekly_tasks[0] + assert edited_w_t.title != weekly_task3.title + + +def test_weekly_task_change_permission( + user, user2, session, + weekly_task, weekly_task2 +): + # creating the weekly task + weekly_task.owner_id = user.id + created = create_weekly_task( + user, weekly_task, session + ) + assert created + user_w_task = user.weekly_tasks[0] + assert user_w_task + + # another user trying to change the weekly task + weekly_task2.id = user_w_task.id + weekly_task2.owner_id = user2.id + changed = change_weekly_task( + user2, weekly_task, session + ) + assert not changed + user_w_t = user.weekly_tasks[0] + assert user_w_t.title != weekly_task2.title + assert user_w_t.content != weekly_task2.content + assert user_w_t.is_important != weekly_task2.is_important + + +def test_weekly_task_from_input(user, weekly_task, weekly_task_time): + # all inputs are ok + w_t = weekly_task_from_input( + user, + weekly_task.title, + weekly_task.days, + weekly_task.content, + weekly_task_time, + weekly_task.is_important, + weekly_task_id=1 + ) + assert w_t + # all the weekly task data should be saved + assert w_t.title == weekly_task.title + assert w_t.days == weekly_task.days + assert w_t.content == weekly_task.content + assert w_t.is_important == weekly_task.is_important + assert w_t.the_time == weekly_task.the_time + + # not all inputs are ok + w_t = weekly_task_from_input( + user, + "", + weekly_task.days, + weekly_task.content, + weekly_task_time, + weekly_task.is_important + ) + assert w_t + # As much data as possible is saved, except for time and days + assert w_t.content == weekly_task.content + assert w_t.days != weekly_task.days + assert w_t.the_time != weekly_task.the_time + + +def test_remove_weekly_task( + user, session, weekly_task +): + weekly_task.owner_id = user.id + created = create_weekly_task( + user, weekly_task, session + ) + assert created + + # Checks if the weekly task exists in the db + user_w_task = user.weekly_tasks[0] + assert user_w_task + # geting the id of the weekly task for removal + weekly_task_id = user_w_task.id + removed = remove_weekly_task(weekly_task_id, session) + assert removed + # Checks if the weekly task exists in the db after removal + assert not user.weekly_tasks + + # Trying to remove a weekly task that does not exists + removed = remove_weekly_task(weekly_task_id, session) + assert not removed + + +def test_weekly_tasks_generate_tasks( + user, session, weekly_task +): + weekly_task.owner_id = user.id + created = create_weekly_task( + user, weekly_task, session + ) + assert created + + # Activates the generator + task_gen = generate_tasks(user, session) + tasks_added = list(task_gen) + + # the number of days defined in the weekly task is 3 + assert tasks_added.count(True) == 3 + + tasks = user.tasks + # The number of tasks a user has should be + # the number of days defined in the weekly task + assert len(tasks) == 3 + # The Tasks should be defined according to the weekly task + for task in tasks: + assert weekly_task.title == task.title + assert weekly_task.content == task.content + assert weekly_task.is_important == task.is_important + time_string = task.date_time.strftime("%H:%M") + assert weekly_task.the_time == time_string + day = task.date_time.strftime("%a") + assert day in weekly_task.days + + # another activation at the same day + # shouldn't affect the db + # Only after a week new tasks should be added + task_gen = generate_tasks(user, session) + tasks_added = list(task_gen) + assert tasks_added.count(True) == 0 + tasks = user.tasks + assert len(tasks) == 3 diff --git a/tests/test_weekly_tasks_route.py b/tests/test_weekly_tasks_route.py new file mode 100644 index 00000000..66eade9a --- /dev/null +++ b/tests/test_weekly_tasks_route.py @@ -0,0 +1,149 @@ +from app.database.models import WeeklyTask +from app.routers.weekly_tasks import get_placeholder_user + + +def test_get_placeholder_user(): + user = get_placeholder_user() + assert user.username == 'demo_user' + assert user.email == 'demo@email.po' + assert user.password == 's3jsd183b13' + assert user.full_name == 'The Demo' + + +def test_weekly_tasks_manager(weekly_tasks_test_client): + # Get weekly-tasks page + data = weekly_tasks_test_client.get('/weekly-tasks').content + + # Verify that it is the page and there are no tasks + assert b'Weekly Tasks' in data + assert b'Test Task 1' not in data + + +def test_weekly_tasks_add( + weekly_tasks_test_client, + weekly_task, input_weekly_task +): + # Get add page + data = weekly_tasks_test_client.get('/weekly-tasks/add').content + # Verify that it is the add page + assert b'Add Weekly Tasks' in data + + # set weekly task data for failed attempt + weekly_task_data = { + 'title': weekly_task.title, + 'mode': 'add', + 'weekly_task_id': '0' + } + data = weekly_tasks_test_client.post( + '/weekly-tasks/execute', data=weekly_task_data).content + # on failed attempt returns to add page + assert b'Add Weekly Tasks' in data + assert b'could not add The Weekly Task' in data + + # sets successful weekly task input + # Sets the input to add mode + input_weekly_task['mode'] = 'add' + input_weekly_task['weekly_task_id'] = '0' + data = weekly_tasks_test_client.post( + '/weekly-tasks/execute', data=input_weekly_task).content + + # on successful attempt doesn't returns to add page + assert b'Add Weekly Tasks' not in data + + # Get weekly-tasks manager page + data = weekly_tasks_test_client.get('/weekly-tasks').content + # Checks that weekly task details are displayed + assert b'Weekly Tasks' in data + assert weekly_task.title.encode() in data + assert weekly_task.days.encode() in data + assert weekly_task.content.encode() in data + assert weekly_task.the_time.encode() in data + + +def test_weekly_tasks_edit( + weekly_tasks_test_client, weekly_task, + session, input_weekly_task +): + # Get weekly tasks id from db for edit + w_task_query = session.query(WeeklyTask) + w_task_by_title = w_task_query.filter_by(title=weekly_task.title) + weekly_task_from_db = w_task_by_title.first() + w_task_id = weekly_task_from_db.id + + data = weekly_tasks_test_client.post( + '/weekly-tasks/edit', + data={"edit_id": w_task_id}).content + + # Checks that all weekly task details are displayed + assert b'Edit Weekly Tasks' in data + assert weekly_task.title.encode() in data + assert weekly_task.content.encode() in data + assert weekly_task.the_time.encode() in data + + # Sets the input to edit mode + input_weekly_task['mode'] = 'edit' + # Sets the id for edit + input_weekly_task['weekly_task_id'] = w_task_id + + # set weekly task input for failed attempt + input_weekly_task['title'] = "" + data = weekly_tasks_test_client.post( + '/weekly-tasks/execute', data=input_weekly_task).content + # on failed attempt returns to edit page + assert b'Edit Weekly Tasks' in data + assert b'These changes could not be made to the Weekly Task' in data + assert weekly_task.title.encode() not in data + assert weekly_task.content.encode() in data + + # sets successful weekly task input + input_weekly_task['title'] = "Test Task 2" + input_weekly_task['fri'] = True + input_weekly_task['thu'] = True + input_weekly_task['sun'] = False + + data = weekly_tasks_test_client.post( + '/weekly-tasks/execute', data=input_weekly_task).content + + # on successful attempt doesn't returns to add page + assert b'Edit Weekly Tasks' not in data + + # Get weekly-tasks manager page + data = weekly_tasks_test_client.get('/weekly-tasks').content + # Checks that all weekly task details are displayed correctly + assert b'Weekly Tasks' in data + assert weekly_task.title.encode() not in data + assert b'Test Task 2' in data + assert weekly_task.days.encode() not in data + assert b'Mon, Thu, Fri, Sat' in data + assert weekly_task.content.encode() in data + assert weekly_task.the_time.encode() in data + + +def test_delete_weekly_tasks( + weekly_tasks_test_client, session, + input_weekly_task, weekly_task +): + # adds weekly_task + input_weekly_task['mode'] = 'add' + input_weekly_task['weekly_task_id'] = '0' + data = weekly_tasks_test_client.post( + '/weekly-tasks/execute', data=input_weekly_task).content + + # get weekly task id for removal + w_task_query = session.query(WeeklyTask) + w_task_by_title = w_task_query.filter_by(title=weekly_task.title) + weekly_task_from_db = w_task_by_title.first() + w_task_id = weekly_task_from_db.id + + # removes weekly_task + weekly_tasks_test_client.delete( + f'/weekly-tasks/?remove_id={w_task_id}') + + # Checking if removed successfully + w_task_query = session.query(WeeklyTask) + w_task_by_title = w_task_query.filter_by(title=weekly_task.title) + weekly_task_from_db = w_task_by_title.first() + data = weekly_tasks_test_client.get('/weekly-tasks').content + assert b'Weekly Tasks' in data + assert weekly_task_from_db is None + assert weekly_task.title.encode() not in data diff --git a/tests/user_fixture.py b/tests/user_fixture.py index 964a6893..b71e6b77 100644 --- a/tests/user_fixture.py +++ b/tests/user_fixture.py @@ -1,4 +1,4 @@ -from collections import Generator +from typing import Generator import pytest from sqlalchemy.orm import Session diff --git a/tests/weekly_tasks_fixture.py b/tests/weekly_tasks_fixture.py index 1c5fc623..370aa553 100644 --- a/tests/weekly_tasks_fixture.py +++ b/tests/weekly_tasks_fixture.py @@ -57,40 +57,3 @@ def weekly_task_time(weekly_task): date_time = datetime.strptime(date_time_string, date_time_format) the_time = date_time.time() return the_time - - -def get_from_db(my_session, title=None): - while True: - if title: - w_task_query = my_session.query(WeeklyTask) - w_task_by_title = w_task_query.filter_by(title=title) - weekly_task_from_db = w_task_by_title.first() - yield weekly_task_from_db - else: - yield None - - -@pytest.fixture -def weekly_task_from_db_gen(): - return get_from_db - - -def get_weekly_task_id( - from_db_gen, - my_session, - title -): - while True: - get_title_from_db = from_db_gen( - my_session, title=title) - w_task_from_db = next(get_title_from_db) - if w_task_from_db: - w_task_id = w_task_from_db.id - yield w_task_id - else: - yield None - - -@pytest.fixture -def weekly_task_id_gen(): - return get_weekly_task_id From a6efda99e45fc9580688d160f2b2e7f7f05b3102 Mon Sep 17 00:00:00 2001 From: itzik Date: Mon, 22 Feb 2021 20:25:52 +0200 Subject: [PATCH 23/32] fix: pre-commit hooks --- app/templates/weekly_tasks_manager.html | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/app/templates/weekly_tasks_manager.html b/app/templates/weekly_tasks_manager.html index 2019b051..93f2a15a 100644 --- a/app/templates/weekly_tasks_manager.html +++ b/app/templates/weekly_tasks_manager.html @@ -28,7 +28,7 @@

Weekly Tasks

+
@@ -58,8 +58,11 @@

Weekly Tasks

-

- {{ weekly_task.title }}
{{ content }} +

+ {{ weekly_task.title }} +

+

+ {{ content }}


important: {{ weekly_task.is_important }} @@ -78,14 +81,18 @@

Weekly Tasks

- + {% endblock %} From 07502c0f8346e3d2a985bc042a5efeab185af68e Mon Sep 17 00:00:00 2001 From: itzik Date: Tue, 23 Feb 2021 23:12:50 +0200 Subject: [PATCH 24/32] fix: for change request --- app/database/models.py | 42 +++- app/internal/weekly_tasks.py | 93 ++++---- app/routers/weekly_tasks.py | 277 ++++++++++++++---------- app/templates/add_edit_weekly_task.html | 13 +- app/templates/weekly_tasks_manager.html | 4 +- tests/client_fixture.py | 39 +++- tests/test_weekly_tasks_internal.py | 130 ++++------- tests/test_weekly_tasks_route.py | 193 ++++++++++------- tests/weekly_tasks_fixture.py | 36 +-- 9 files changed, 464 insertions(+), 363 deletions(-) diff --git a/app/database/models.py b/app/database/models.py index dfbbc9a1..1cc254f2 100644 --- a/app/database/models.py +++ b/app/database/models.py @@ -1,5 +1,7 @@ from __future__ import annotations +import calendar + from datetime import datetime from typing import Any, Dict @@ -75,10 +77,12 @@ class User(Base): ) weekly_tasks = relationship( - "WeeklyTask", cascade="all, delete", back_populates="owner") + "WeeklyTask", + cascade="all, delete", + back_populates="owner", + ) - tasks = relationship( - "Task", cascade="all, delete", back_populates="owner") + tasks = relationship("Task", cascade="all, delete", back_populates="owner") def __repr__(self): return f"" @@ -277,13 +281,13 @@ class Task(Base): is_done = Column(Boolean, nullable=False) is_important = Column(Boolean, nullable=False) date_time = Column(DateTime, nullable=False) - owner_id = Column(Integer, ForeignKey("users.id")) - owner = relationship("User", back_populates="tasks") + user_id = Column(Integer, ForeignKey("users.id")) + owner = relationship("User", back_populates=__tablename__) class WeeklyTask(Base): - __tablename__ = "weekly_task" + __tablename__ = "weekly_tasks" id = Column(Integer, primary_key=True, index=True) title = Column(String) @@ -291,9 +295,31 @@ class WeeklyTask(Base): content = Column(String) is_important = Column(Boolean, nullable=False) the_time = Column(String, nullable=False) - owner_id = Column(Integer, ForeignKey("users.id")) - owner = relationship("User", back_populates="weekly_tasks") + user_id = Column(Integer, ForeignKey("users.id")) + owner = relationship("User", back_populates=__tablename__) + + def set_days(self, days: str): + """Gets days represented by names + and sets them in the days field""" + atomic_days = [] + days_list = days.split(", ") + day_abbr = list(calendar.day_abbr) + for day in days_list: + day_num = day_abbr.index(day) + atomic_days.append(str(day_num)) + self.days = "".join(atomic_days) + + def get_days(self) -> str: + """return days represented by names""" + days = [] + atomic_days = self.days + day_abbr = list(calendar.day_abbr) + for day_num in atomic_days: + day_num = int(day_num) + day_name = day_abbr[day_num] + days.append(day_name) + return ", ".join(days) class SalarySettings(Base): diff --git a/app/internal/weekly_tasks.py b/app/internal/weekly_tasks.py index 20497124..eb8901d3 100644 --- a/app/internal/weekly_tasks.py +++ b/app/internal/weekly_tasks.py @@ -1,6 +1,7 @@ from datetime import date, datetime, time -from typing import Iterator +from typing import Iterator, Optional +from app.internal.security.schema import CurrentUser from app.database.models import User, Task, WeeklyTask from sqlalchemy.orm.session import Session @@ -12,10 +13,12 @@ def check_inputs(days: str, the_time: time, title: str) -> bool: def weekly_task_from_input( user: User, - title: str, days: str, - content: str, the_time: time, + title: Optional[str], + days: str, + content: Optional[str], + the_time: Optional[time], is_important: bool, - weekly_task_id: int = 0 + weekly_task_id: int = 0, ) -> WeeklyTask: """This function is being used to make a Weekly Task model from the inputs. @@ -32,11 +35,15 @@ def weekly_task_from_input( Returns: WeeklyTask: the model WeeklyTask which the function managed to make. """ + if isinstance(user, CurrentUser): + user_id = user.user_id + else: + user_id = user.id weekly_task = WeeklyTask( title=title, content=content, is_important=is_important, - owner_id=user.id + user_id=user_id, ) if weekly_task_id != 0: @@ -45,32 +52,32 @@ def weekly_task_from_input( inputs_ok = check_inputs(days, the_time, title) if not inputs_ok: return weekly_task - weekly_task.days = days + weekly_task.set_days(days) weekly_task.the_time = the_time.strftime("%H:%M") return weekly_task def create_weekly_task( - user: User, weekly_task: WeeklyTask, - session: Session + user: User, + weekly_task: WeeklyTask, + session: Session, ) -> bool: """This function is being used to add a Weekly Task to the user. - Args: - user (User): The user who wants to add the Weekly Task. - session (Session): The session to redirect to the database. - weekly_task (WeeklyTask): The Weekly Task that the user will add. + Args: + user (User): The user who wants to add the Weekly Task. + session (Session): The session to redirect to the database. + weekly_task (WeeklyTask): The Weekly Task that the user will add. - Returns: - bool: Shows if the weekly_task has been added to the db. - """ - if weekly_task.days is None or weekly_task.the_time is None: + Returns: + bool: Shows if the weekly_task has been added to the db. + """ + if not weekly_task.days or not weekly_task.the_time: return False - user_titles = ( - user_weekly_task.title - for user_weekly_task in user.weekly_tasks + task_titles = ( + user_weekly_task.title for user_weekly_task in user.weekly_tasks ) - if weekly_task.title in user_titles: + if weekly_task.title in task_titles: return False session.add(weekly_task) session.commit() @@ -80,33 +87,34 @@ def create_weekly_task( def change_weekly_task( user: User, weekly_task: WeeklyTask, - session: Session + session: Session, ) -> bool: """This function is being used to edit a Weekly Task the user have. - Args: - user (User): The user who wants to edit the Weekly Task. - session (Session): The session to redirect to the database. - weekly_task (WeeklyTask): The Weekly Task that the of the user, - with the edited values. + Args: + user (User): The user who wants to edit the Weekly Task. + session (Session): The session to redirect to the database. + weekly_task (WeeklyTask): The Weekly Task that the of the user, + with the edited values. - Returns: - bool: Shows if the weekly_task has been edited in the db. - """ + Returns: + bool: Shows if the weekly_task has been edited in the db. + """ if weekly_task.days is None or weekly_task.the_time is None: return False w_task_query = session.query(WeeklyTask) old_weekly_task = w_task_query.filter_by(id=weekly_task.id).first() user_titles = ( - user_weekly_task.title for user_weekly_task in user.weekly_tasks + user_weekly_task.title + for user_weekly_task in user.weekly_tasks if user_weekly_task.title != old_weekly_task.title ) if weekly_task.title in user_titles: return False - if weekly_task.owner_id != user.id: + if weekly_task.user_id != user.id: return False old_weekly_task.title = weekly_task.title @@ -118,12 +126,9 @@ def change_weekly_task( return True -def create_task( - task: Task, user: User, - session: Session -) -> bool: +def create_task(task: Task, user: User, session: Session) -> bool: """Make a task, used by the generate_tasks function""" - user_tasks_query = session.query(Task).filter_by(owner_id=user.id) + user_tasks_query = session.query(Task).filter_by(user_id=user.id) task_by_time = user_tasks_query.filter_by(date_time=task.date_time) task_by_title_and_time = task_by_time.filter_by(title=task.title) task_exist = task_by_title_and_time.first() @@ -144,15 +149,14 @@ def get_datetime(day: str, the_time: str) -> datetime: return datetime.strptime(date_string, "%a %H:%M %W %Y") -def generate_tasks( - user: User, session: Session -) -> Iterator[bool]: +def generate_tasks(user: User, session: Session) -> Iterator[bool]: """Generates tasks for the week based on all the weekly tasks the user have""" for weekly_task in user.weekly_tasks: the_time = weekly_task.the_time - days = weekly_task.days.split(", ") - for day in days: + days = weekly_task.get_days() + days_list = days.split(", ") + for day in days_list: date_time = get_datetime(day, the_time) task = Task( title=weekly_task.title, @@ -160,15 +164,12 @@ def generate_tasks( is_done=False, is_important=weekly_task.is_important, date_time=date_time, - owner_id=user.id + user_id=user.id, ) yield create_task(task, user, session) -def remove_weekly_task( - weekly_task_id: int, - session: Session -) -> bool: +def remove_weekly_task(weekly_task_id: int, session: Session) -> bool: """Removes a weekly task from the db based on the weekly task id""" weekly_task_query = session.query(WeeklyTask) weekly_task = weekly_task_query.filter_by(id=weekly_task_id).first() diff --git a/app/routers/weekly_tasks.py b/app/routers/weekly_tasks.py index 19aaa921..36744033 100644 --- a/app/routers/weekly_tasks.py +++ b/app/routers/weekly_tasks.py @@ -1,51 +1,36 @@ import calendar import datetime -from typing import List, Tuple -from fastapi import APIRouter, Depends, Request, Form +from typing import List, Tuple, Optional +from fastapi import APIRouter, Cookie, Depends, Request, Response, Form from sqlalchemy.orm.session import Session -from starlette.responses import RedirectResponse +from starlette.responses import RedirectResponse, HTMLResponse from starlette.status import HTTP_302_FOUND, HTTP_303_SEE_OTHER -from app.database.models import User, WeeklyTask +from app.database.models import WeeklyTask from app.dependencies import get_db, templates +from app.internal.security.dependancies import ( + current_user, + schema, + is_logged_in, + current_user_from_db, +) from app.internal.weekly_tasks import ( - remove_weekly_task, weekly_task_from_input, - create_weekly_task, change_weekly_task) + remove_weekly_task, + weekly_task_from_input, + create_weekly_task, + change_weekly_task, +) router = APIRouter( prefix="/weekly-tasks", tags=["weekly-tasks"], responses={404: {"description": "Not found"}}, - dependencies=[Depends(get_db)] + dependencies=[Depends(get_db)], ) -def get_placeholder_user() -> User: - user = User( - username='demo_user', - email='demo@email.po', - password='s3jsd183b13', - full_name='The Demo' - ) - return user - - -def get_user( - demo_user: User, - session: Session = Depends(get_db) -) -> User: - demo_username = demo_user.username - user = session.query(User).filter_by(username=demo_username).first() - if not user: - session.add(demo_user) - session.commit() - user_query = session.query(User) - user = user_query.filter_by(username=demo_username).first() - return user - - def get_checked_days(days: str = "") -> List[Tuple[str, str, str]]: """Produces the input checked_days for the template add_edit_weekly_task""" days_list = days.split(", ") @@ -61,10 +46,13 @@ def get_checked_days(days: str = "") -> List[Tuple[str, str, str]]: def get_days_string( - sun: bool, mon: bool, - tue: bool, wed: bool, - thu: bool, fri: bool, - sat: bool + sun: bool, + mon: bool, + tue: bool, + wed: bool, + thu: bool, + fri: bool, + sat: bool, ) -> str: """Produces a string of all the days that were checked, For use in the model weekly tasks.""" @@ -75,20 +63,18 @@ def get_days_string( "Thu": thu, "Fri": fri, "Sat": sat, - "Sun": sun + "Sun": sun, } days_list = [day for day, is_checked in days_dict.items() if is_checked] days = ", ".join(days_list) return days -@router.get('/') +@router.get("/") async def weekly_tasks_manager( - request: Request, - session=Depends(get_db), - demo_user=Depends(get_placeholder_user)): - - user = get_user(demo_user, session) + request: Request, + user: schema.CurrentUser = Depends(current_user_from_db), +): # TODO: Move the below function to a compatible location # Need to run regularly whenever there are tasks on the week @@ -98,108 +84,173 @@ async def weekly_tasks_manager( # generate_tasks(user, session) # imported from app.internal.weekly_tasks # session.close() - return templates.TemplateResponse("weekly_tasks_manager.html", { - "request": request, - "weekly_tasks": user.weekly_tasks - }) + return templates.TemplateResponse( + "weekly_tasks_manager.html", + {"request": request, "weekly_tasks": user.weekly_tasks}, + ) -@router.get('/add') +@router.get("/add", dependencies=[Depends(is_logged_in)]) def add_weekly_task(request: Request): checked_days = get_checked_days() - return templates.TemplateResponse("add_edit_weekly_task.html", { - "request": request, - "weekly_task": None, - "mode": "add", - "checked_days": checked_days - }) + return templates.TemplateResponse( + "add_edit_weekly_task.html", + { + "request": request, + "weekly_task": None, + "mode": "add", + "checked_days": checked_days, + }, + ) -@router.delete('/') -def delete_weekly_task( - remove_id: int, - session=Depends(get_db)): +@router.delete("/", dependencies=[Depends(is_logged_in)]) +def delete_weekly_task(remove_id: int, session: Session = Depends(get_db)): remove_weekly_task(remove_id, session) - session.close() url = router.url_path_for("weekly_tasks_manager") return RedirectResponse(url=url, status_code=HTTP_303_SEE_OTHER) -@router.post('/edit') -def edit_weekly_task( - request: Request, - session=Depends(get_db), - edit_id: int = Form(...)): +@router.get("/edit", dependencies=[Depends(is_logged_in)]) +def edit_weekly_task(edit_id: int, request: Request, session=Depends(get_db)): weekly_task = session.query(WeeklyTask).filter_by(id=edit_id).first() - checked_days = get_checked_days(weekly_task.days) - return templates.TemplateResponse("add_edit_weekly_task.html", { - "request": request, - "weekly_task": weekly_task, - "mode": "edit", - "checked_days": checked_days - }) + checked_days = get_checked_days(weekly_task.get_days()) + return templates.TemplateResponse( + "add_edit_weekly_task.html", + { + "request": request, + "weekly_task": weekly_task, + "mode": "edit", + "checked_days": checked_days, + }, + ) -@router.post('/execute') +def set_cookies( + response: Response, + id: Optional[int], + title: Optional[str], + content: Optional[str], + days: str, + is_important: bool, +) -> Response: + """Sets the weekly task cookies + for the failed/add and failed/edit routers""" + if not id: + id = 0 + response.set_cookie(key="id", value=id) + response.set_cookie(key="title", value=title) + response.set_cookie(key="content", value=content) + response.set_cookie(key="days", value=days) + response.set_cookie(key="is_important", value=is_important) + return response + + +@router.post("/execute/{mode}") def weekly_task_execute( - request: Request, - session=Depends(get_db), - demo_user=Depends(get_placeholder_user), - title: str = Form(None), - sun: bool = Form(False), - mon: bool = Form(False), - tue: bool = Form(False), - wed: bool = Form(False), - thu: bool = Form(False), - fri: bool = Form(False), - sat: bool = Form(False), - content: str = Form(None), - is_important: bool = Form(False), - the_time: datetime.time = Form(None), - weekly_task_id: int = Form(...), - mode: str = Form(...)): - - user = get_user(demo_user, session) - days = get_days_string( - sun, mon, tue, wed, thu, fri, sat - ) - + request: Request, + mode: str, + session: Session = Depends(get_db), + user: schema.CurrentUser = Depends(current_user_from_db), + title: str = Form(None), + sun: bool = Form(False), + mon: bool = Form(False), + tue: bool = Form(False), + wed: bool = Form(False), + thu: bool = Form(False), + fri: bool = Form(False), + sat: bool = Form(False), + content: str = Form(None), + is_important: bool = Form(False), + the_time: datetime.time = Form(None), + weekly_task_id: int = Form(...), +): + + request.cookies.clear() + + days = get_days_string(sun, mon, tue, wed, thu, fri, sat) weekly_task = weekly_task_from_input( - user, title, days, - content, the_time, + user, + title, + days, + content, + the_time, is_important, - weekly_task_id=weekly_task_id + weekly_task_id=weekly_task_id, ) - fail_massage = None - executed = False if mode == "add": - fail_massage = "could not add The Weekly Task" # creating the weekly task - created = create_weekly_task( - user, weekly_task, session - ) + created = create_weekly_task(user, weekly_task, session) executed = created - else: # mode == "edit" - fail_massage = "These changes could not be made to the Weekly Task" + else: # mode == "edit": # editing the weekly task - edited = change_weekly_task( - user, weekly_task, session - ) + edited = change_weekly_task(user, weekly_task, session) executed = edited if not executed: - checked_days = get_checked_days(days) - return templates.TemplateResponse("add_edit_weekly_task.html", { + url = router.url_path_for("weekly_task_failed", mode=mode) + html_respone = RedirectResponse( + url=url, + status_code=HTTP_303_SEE_OTHER, + ) + response = set_cookies( + html_respone, + weekly_task.id, + title, + content, + days, + weekly_task.is_important, + ) + return response + + url = router.url_path_for("weekly_tasks_manager") + return RedirectResponse(url=url, status_code=HTTP_302_FOUND) + + +@router.get("/failed/{mode}", response_class=HTMLResponse) +def weekly_task_failed( + mode: str, + request: Request, + user: schema.CurrentUser = Depends(current_user), + id: int = Cookie(0), + title: str = Cookie(None), + content: str = Cookie(None), + days: str = Cookie(...), + is_important: bool = Cookie(False), +): + the_time = None + if title == "None": + title = None + if content == "None": + content = None + weekly_task = weekly_task_from_input( + user, + title, + days, + content, + the_time, + is_important, + id, + ) + + if mode == "add": + fail_massage = "could not add The Weekly Task" + else: + fail_massage = "These changes could not be made to the Weekly Task" + checked_days = get_checked_days(days) + + return templates.TemplateResponse( + "add_edit_weekly_task.html", + { "request": request, "massage": fail_massage, "weekly_task": weekly_task, "mode": mode, - "checked_days": checked_days - }) - url = router.url_path_for("weekly_tasks_manager") - return RedirectResponse(url=url, status_code=HTTP_302_FOUND) + "checked_days": checked_days, + }, + ) diff --git a/app/templates/add_edit_weekly_task.html b/app/templates/add_edit_weekly_task.html index ff1e81ef..eda9f74f 100644 --- a/app/templates/add_edit_weekly_task.html +++ b/app/templates/add_edit_weekly_task.html @@ -7,7 +7,7 @@

Edit Weekly Tasks

{% set weekly_task_id = weekly_task.id %} - + {% else %}

Add Weekly Tasks

@@ -35,8 +35,8 @@

Add Weekly Tasks

-
- + +
@@ -73,13 +73,12 @@

Add Weekly Tasks

- + - - +
-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/app/templates/weekly_tasks_manager.html b/app/templates/weekly_tasks_manager.html index 93f2a15a..d8802ab5 100644 --- a/app/templates/weekly_tasks_manager.html +++ b/app/templates/weekly_tasks_manager.html @@ -15,7 +15,7 @@

Weekly Tasks

- Every: {{ weekly_task.days }} + Every: {{ weekly_task.get_days() }} at: {{ weekly_task.the_time }} @@ -30,7 +30,7 @@

Weekly Tasks

@@ -80,6 +82,7 @@ {% block content %}{% endblock %} + @@ -95,5 +98,4 @@ - diff --git a/app/templates/calendar/layout.html b/app/templates/calendar/layout.html new file mode 100644 index 00000000..5f98e980 --- /dev/null +++ b/app/templates/calendar/layout.html @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + Calendar + + + +
+ +
+
FEATURE NAME
+
+
+
+
+
{{day.display()}}
+
Location 0oc 00:00
+
+ +
+
+ {% block main %} {% endblock %} +
+
+
+ + + + + + + + diff --git a/app/templates/invitations.html b/app/templates/invitations.html deleted file mode 100644 index 83d29418..00000000 --- a/app/templates/invitations.html +++ /dev/null @@ -1,24 +0,0 @@ -{% extends "partials/index/index_base.html" %} - - -{% block content %} - -
-

{{ message }}

-
- - {% if invitations %} -
- {% for i in invitations %} -
- {{ i.event.owner.username }} - {{ i.event.title }} ({{ i.event.start }}) ({{ i.status }}) - - -
- {% endfor %} -
- {% else %} - You don't have any invitations. - {% endif %} - -{% endblock %} \ No newline at end of file diff --git a/app/templates/notifications.html b/app/templates/notifications.html new file mode 100644 index 00000000..7b33a17f --- /dev/null +++ b/app/templates/notifications.html @@ -0,0 +1,38 @@ +{% extends "./partials/notification/base.html" %} +{% block page_name %}Notifications{% endblock page_name %} + +{% block description %} +
+
New Notifications
+

+ In this page you can view all of your new notifications.
+ use the + button to mark as read + and the + and + to accept and decline. +

+
+{% endblock description %} + +{% block link %} + +{% endblock link %} + +{% block optional %} +
+ + +
+{% endblock optional %} + +{% block notifications %} + {% include './partials/notification/generate_notifications.html' %} +{% endblock notifications %} + +{% block no_notifications_msg %} + You don't have any new notifications. +{% endblock no_notifications_msg %} diff --git a/app/templates/partials/calendar/navigation.html b/app/templates/partials/calendar/navigation.html index ab65b8eb..ed73747d 100644 --- a/app/templates/partials/calendar/navigation.html +++ b/app/templates/partials/calendar/navigation.html @@ -7,6 +7,11 @@ +
+ + + +
diff --git a/app/templates/partials/index/navigation.html b/app/templates/partials/index/navigation.html index b1fa3b3f..60baf35d 100644 --- a/app/templates/partials/index/navigation.html +++ b/app/templates/partials/index/navigation.html @@ -20,17 +20,14 @@ - + diff --git a/app/templates/partials/notification/base.html b/app/templates/partials/notification/base.html new file mode 100644 index 00000000..0df8fcde --- /dev/null +++ b/app/templates/partials/notification/base.html @@ -0,0 +1,56 @@ +{% extends "partials/base.html" %} +{% block head %} + {{super()}} + + + + + +{% endblock head %} +{% block body %} +
+ {% include 'partials/calendar/navigation.html' %} +
+ {% include 'partials/calendar/feature_settings/example.html' %} +
+
+ {% block content %} +
+ {% block description %} + {% endblock description %} + +
+
+
+ {% block link %} + {% endblock link %} +
+ {% if notifications %} +
+ + {% block optional %} + {% endblock optional %} + +
+ {% block notifications %} + {% endblock notifications %} +
+ + {% else %} + {% block no_notifications_msg %} + {% endblock no_notifications_msg %} +
+ {% endif %} +
+ {% endblock content %} +
+
+ + + + +{% endblock body %} diff --git a/app/templates/partials/notification/generate_archive.html b/app/templates/partials/notification/generate_archive.html new file mode 100644 index 00000000..2d0e0ed3 --- /dev/null +++ b/app/templates/partials/notification/generate_archive.html @@ -0,0 +1,29 @@ +{% for n in notifications %} + {% set type = n.__table__.name %} + +
+ {% if type == "invitations" %} +
+ Invitation from {{ n.event.owner.username }} - + {{ n.event.title }} + (declined) +
+
+
+ + +
+
+ + {% elif type == "messages" %} +
+ {% if n.link %}{{ n.body }} + {% else %}{{ n.body }}{% endif %} +
+ {% endif %} + +
+{% endfor %} diff --git a/app/templates/partials/notification/generate_notifications.html b/app/templates/partials/notification/generate_notifications.html new file mode 100644 index 00000000..b779db22 --- /dev/null +++ b/app/templates/partials/notification/generate_notifications.html @@ -0,0 +1,48 @@ +{% for n in notifications %} + {% set type = n.__table__.name %} + +
+ {% if type == "invitations" %} +
+ Invitation from {{ n.event.owner.username }} - + {{ n.event.title }} + ({{ n.event.start.strftime('%H:%M %m/%d/%Y') }}) +
+
+
+ + +
+
+ + +
+
+ + {% elif type == "messages" %} +
+ {% if n.link %}{{ n.body }} + {% else %}{{ n.body }}{% endif %} +
+
+
+ + +
+
+ {% endif %} + +
+{% endfor %} diff --git a/tests/conftest.py b/tests/conftest.py index 4c2d7f12..ab9d02c6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,20 +9,24 @@ pytest_plugins = [ - 'tests.user_fixture', - 'tests.event_fixture', - 'tests.dayview_fixture', - 'tests.invitation_fixture', - 'tests.association_fixture', - 'tests.client_fixture', - 'tests.asyncio_fixture', - 'tests.logger_fixture', - 'tests.category_fixture', - 'smtpdfix', - 'tests.quotes_fixture', - 'tests.zodiac_fixture', - 'tests.jokes_fixture', - 'tests.comment_fixture', + "tests.fixtures.user_fixture", + "tests.fixtures.event_fixture", + "tests.fixtures.invitation_fixture", + "tests.fixtures.message_fixture", + "tests.fixtures.association_fixture", + "tests.fixtures.client_fixture", + "tests.fixtures.asyncio_fixture", + "tests.fixtures.logger_fixture", + "tests.fixtures.category_fixture", + "tests.fixtures.quotes_fixture", + "tests.fixtures.zodiac_fixture", + "tests.fixtures.dayview_fixture", + "tests.fixtures.comment_fixture", + "tests.fixtures.quotes_fixture", + "tests.fixtures.zodiac_fixture", + "tests.fixtures.jokes_fixture", + "tests.fixtures.comment_fixture", + "smtpdfix", ] # When testing in a PostgreSQL environment please make sure that: @@ -31,21 +35,22 @@ if PSQL_ENVIRONMENT: SQLALCHEMY_TEST_DATABASE_URL = ( - "postgresql://postgres:1234" - "@localhost/postgres" - ) - test_engine = create_engine( - SQLALCHEMY_TEST_DATABASE_URL + "postgresql://postgres:1234" "@localhost/postgres" ) + test_engine = create_engine(SQLALCHEMY_TEST_DATABASE_URL) else: SQLALCHEMY_TEST_DATABASE_URL = "sqlite:///./test.db" test_engine = create_engine( - SQLALCHEMY_TEST_DATABASE_URL, connect_args={"check_same_thread": False} + SQLALCHEMY_TEST_DATABASE_URL, + connect_args={"check_same_thread": False}, ) TestingSessionLocal = sessionmaker( - autocommit=False, autoflush=False, bind=test_engine) + autocommit=False, + autoflush=False, + bind=test_engine, +) def get_test_db(): @@ -66,11 +71,15 @@ def session(): def sqlite_engine(): SQLALCHEMY_TEST_DATABASE_URL = "sqlite:///./test.db" sqlite_test_engine = create_engine( - SQLALCHEMY_TEST_DATABASE_URL, connect_args={"check_same_thread": False} + SQLALCHEMY_TEST_DATABASE_URL, + connect_args={"check_same_thread": False}, ) TestingSession = sessionmaker( - autocommit=False, autoflush=False, bind=sqlite_test_engine) + autocommit=False, + autoflush=False, + bind=sqlite_test_engine, + ) yield sqlite_test_engine session = TestingSession() diff --git a/tests/fixtures/__init__.py b/tests/fixtures/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/association_fixture.py b/tests/fixtures/association_fixture.py similarity index 100% rename from tests/association_fixture.py rename to tests/fixtures/association_fixture.py diff --git a/tests/asyncio_fixture.py b/tests/fixtures/asyncio_fixture.py similarity index 83% rename from tests/asyncio_fixture.py rename to tests/fixtures/asyncio_fixture.py index 2506ab53..7f567b3b 100644 --- a/tests/asyncio_fixture.py +++ b/tests/fixtures/asyncio_fixture.py @@ -7,7 +7,7 @@ from app.main import app from app.routers import telegram from app.routers.event import create_event -from tests.client_fixture import get_test_placeholder_user +from tests.fixtures.client_fixture import get_test_placeholder_user from tests.conftest import get_test_db, test_engine @@ -32,24 +32,24 @@ def fake_user_events(session): session.commit() create_event( db=session, - title='Cool today event', - color='red', + title="Cool today event", + color="red", start=today_date, end=today_date + timedelta(days=2), all_day=False, - content='test event', + content="test event", owner_id=user.id, location="Here", is_google_event=False, ) create_event( db=session, - title='Cool (somewhen in two days) event', - color='blue', + title="Cool (somewhen in two days) event", + color="blue", start=today_date + timedelta(days=1), end=today_date + timedelta(days=3), all_day=False, - content='this week test event', + content="this week test event", owner_id=user.id, location="Here", is_google_event=False, diff --git a/tests/category_fixture.py b/tests/fixtures/category_fixture.py similarity index 100% rename from tests/category_fixture.py rename to tests/fixtures/category_fixture.py diff --git a/tests/client_fixture.py b/tests/fixtures/client_fixture.py similarity index 91% rename from tests/client_fixture.py rename to tests/fixtures/client_fixture.py index 5f5f8971..7a5d1e3c 100644 --- a/tests/client_fixture.py +++ b/tests/fixtures/client_fixture.py @@ -1,11 +1,12 @@ -from typing import Generator, Iterator +from typing import Generator, Iterator, Dict -from fastapi.testclient import TestClient import pytest +from fastapi.testclient import TestClient from sqlalchemy.orm import Session from app import main from app.database.models import Base, User + from app.routers import ( agenda, audio, @@ -13,8 +14,8 @@ event, friendview, google_connect, - invitation, meds, + notification, profile, weight, ) @@ -22,9 +23,15 @@ from tests import security_testing_routes from tests.conftest import get_test_db, test_engine +LOGIN_DATA_TYPE = Dict[str, str] + main.app.include_router(security_testing_routes.router) +def login_client(client: TestClient, data: LOGIN_DATA_TYPE) -> None: + client.post(client.app.url_path_for("login"), data=data) + + def get_test_placeholder_user() -> User: return User( username="fake_user", @@ -57,6 +64,11 @@ def agenda_test_client() -> Generator[TestClient, None, None]: yield from create_test_client(agenda.get_db) +@pytest.fixture(scope="session") +def notification_test_client(): + yield from create_test_client(notification.get_db) + + @pytest.fixture(scope="session") def friendview_test_client() -> Generator[TestClient, None, None]: yield from create_test_client(friendview.get_db) @@ -77,11 +89,6 @@ def home_test_client() -> Generator[TestClient, None, None]: yield from create_test_client(main.get_db) -@pytest.fixture(scope="session") -def invitation_test_client() -> Generator[TestClient, None, None]: - yield from create_test_client(invitation.get_db) - - @pytest.fixture(scope="session") def categories_test_client() -> Generator[TestClient, None, None]: yield from create_test_client(categories.get_db) diff --git a/tests/comment_fixture.py b/tests/fixtures/comment_fixture.py similarity index 100% rename from tests/comment_fixture.py rename to tests/fixtures/comment_fixture.py diff --git a/tests/dayview_fixture.py b/tests/fixtures/dayview_fixture.py similarity index 100% rename from tests/dayview_fixture.py rename to tests/fixtures/dayview_fixture.py diff --git a/tests/event_fixture.py b/tests/fixtures/event_fixture.py similarity index 83% rename from tests/event_fixture.py rename to tests/fixtures/event_fixture.py index 7c3d8a56..17213e6f 100644 --- a/tests/event_fixture.py +++ b/tests/fixtures/event_fixture.py @@ -13,10 +13,10 @@ def event(sender: User, category: Category, session: Session) -> Event: return create_event( db=session, - title='event', + title="event", start=today_date, end=today_date, - content='test event', + content="test event", owner_id=sender.id, location="Some random location", vc_link=None, @@ -28,11 +28,11 @@ def event(sender: User, category: Category, session: Session) -> Event: def today_event(sender: User, session: Session) -> Event: return create_event( db=session, - title='event 1', + title="event 1", start=today_date + timedelta(hours=7), end=today_date + timedelta(hours=9), all_day=False, - content='test event', + content="test event", owner_id=sender.id, ) @@ -41,12 +41,12 @@ def today_event(sender: User, session: Session) -> Event: def today_event_2(sender: User, session: Session) -> Event: return create_event( db=session, - title='event 2', - color='blue', + title="event 2", + color="blue", start=today_date + timedelta(hours=3), end=today_date + timedelta(days=2, hours=3), all_day=False, - content='test event', + content="test event", owner_id=sender.id, ) @@ -55,12 +55,12 @@ def today_event_2(sender: User, session: Session) -> Event: def yesterday_event(sender: User, session: Session) -> Event: return create_event( db=session, - title='event 3', - color='green', + title="event 3", + color="green", start=today_date - timedelta(hours=8), end=today_date, all_day=False, - content='test event', + content="test event", owner_id=sender.id, ) @@ -69,12 +69,12 @@ def yesterday_event(sender: User, session: Session) -> Event: def next_week_event(sender: User, session: Session) -> Event: return create_event( db=session, - title='event 4', - color='blue', + title="event 4", + color="blue", start=today_date + timedelta(days=7, hours=2), end=today_date + timedelta(days=7, hours=4), all_day=False, - content='test event', + content="test event", owner_id=sender.id, ) @@ -83,12 +83,12 @@ def next_week_event(sender: User, session: Session) -> Event: def next_month_event(sender: User, session: Session) -> Event: return create_event( db=session, - title='event 5', + title="event 5", color="green", start=today_date + timedelta(days=20, hours=4), end=today_date + timedelta(days=20, hours=6), all_day=False, - content='test event', + content="test event", owner_id=sender.id, ) @@ -97,12 +97,12 @@ def next_month_event(sender: User, session: Session) -> Event: def old_event(sender: User, session: Session) -> Event: return create_event( db=session, - title='event 6', + title="event 6", color="red", start=today_date - timedelta(days=5), end=today_date - timedelta(days=1), all_day=False, - content='test event', + content="test event", owner_id=sender.id, ) @@ -111,11 +111,11 @@ def old_event(sender: User, session: Session) -> Event: def all_day_event(sender: User, category: Category, session: Session) -> Event: return create_event( db=session, - title='event', + title="event", start=today_date, end=today_date, all_day=True, - content='test event', + content="test event", owner_id=sender.id, location="Some random location", category_id=category.id, diff --git a/tests/invitation_fixture.py b/tests/fixtures/invitation_fixture.py similarity index 100% rename from tests/invitation_fixture.py rename to tests/fixtures/invitation_fixture.py diff --git a/tests/jokes_fixture.py b/tests/fixtures/jokes_fixture.py similarity index 89% rename from tests/jokes_fixture.py rename to tests/fixtures/jokes_fixture.py index d7e3258c..062d5d45 100644 --- a/tests/jokes_fixture.py +++ b/tests/fixtures/jokes_fixture.py @@ -16,5 +16,5 @@ def joke(session: Session) -> Joke: yield from add_joke( session=session, id_joke=1, - text='Chuck Norris can slam a revolving door.', + text="Chuck Norris can slam a revolving door.", ) diff --git a/tests/logger_fixture.py b/tests/fixtures/logger_fixture.py similarity index 100% rename from tests/logger_fixture.py rename to tests/fixtures/logger_fixture.py diff --git a/tests/fixtures/message_fixture.py b/tests/fixtures/message_fixture.py new file mode 100644 index 00000000..839051ba --- /dev/null +++ b/tests/fixtures/message_fixture.py @@ -0,0 +1,29 @@ +import pytest +from sqlalchemy.orm import Session + +from app.database.models import Message, User +from app.internal.utils import create_model, delete_instance + + +@pytest.fixture +def message(user: User, session: Session) -> Message: + invitation = create_model( + session, Message, + body='A test message', + link='#', + recipient_id=user.id, + ) + yield invitation + delete_instance(session, invitation) + + +@pytest.fixture +def sec_message(user: User, session: Session) -> Message: + invitation = create_model( + session, Message, + body='A test message', + link='#', + recipient_id=user.id, + ) + yield invitation + delete_instance(session, invitation) diff --git a/tests/quotes_fixture.py b/tests/fixtures/quotes_fixture.py similarity index 100% rename from tests/quotes_fixture.py rename to tests/fixtures/quotes_fixture.py diff --git a/tests/user_fixture.py b/tests/fixtures/user_fixture.py similarity index 68% rename from tests/user_fixture.py rename to tests/fixtures/user_fixture.py index b50fb900..e2a7ad26 100644 --- a/tests/user_fixture.py +++ b/tests/fixtures/user_fixture.py @@ -4,20 +4,24 @@ from sqlalchemy.orm import Session from app.database.models import User +from app.database.schemas import UserCreate from app.internal.utils import create_model, delete_instance +from app.routers.register import create_user @pytest.fixture -def user(session: Session) -> Generator[User, None, None]: - mock_user = create_model( - session, - User, +async def user(session: Session) -> Generator[User, None, None]: + schema = UserCreate( username="test_username", password="test_password", + confirm_password="test_password", email="test.email@gmail.com", + full_name="test_full_name", + description="test_description", language_id=1, target_weight=60, ) + mock_user = await create_user(session, schema) yield mock_user delete_instance(session, mock_user) diff --git a/tests/zodiac_fixture.py b/tests/fixtures/zodiac_fixture.py similarity index 100% rename from tests/zodiac_fixture.py rename to tests/fixtures/zodiac_fixture.py diff --git a/tests/salary/test_routes.py b/tests/salary/test_routes.py index 13e22e05..830569ff 100644 --- a/tests/salary/test_routes.py +++ b/tests/salary/test_routes.py @@ -199,7 +199,6 @@ def test_invalid_category_redirect( response = salary_test_client.get(path) assert any(temp.status_code == status.HTTP_307_TEMPORARY_REDIRECT for temp in response.history) - print(response.text) assert message in response.text diff --git a/tests/test_a_telegram_asyncio.py b/tests/test_a_telegram_asyncio.py index faf99d98..ff1a7ddf 100644 --- a/tests/test_a_telegram_asyncio.py +++ b/tests/test_a_telegram_asyncio.py @@ -6,141 +6,145 @@ from app.telegram.handlers import MessageHandler, reply_unknown_user from app.telegram.keyboards import DATE_FORMAT from app.telegram.models import Bot, Chat -from tests.asyncio_fixture import today_date -from tests.client_fixture import get_test_placeholder_user +from tests.fixtures.asyncio_fixture import today_date +from tests.fixtures.client_fixture import get_test_placeholder_user def gen_message(text): return { - 'update_id': 10000000, - 'message': { - 'message_id': 2434, - 'from': { - 'id': 666666, - 'is_bot': False, - 'first_name': 'Moshe', - 'username': 'banana', - 'language_code': 'en' + "update_id": 10000000, + "message": { + "message_id": 2434, + "from": { + "id": 666666, + "is_bot": False, + "first_name": "Moshe", + "username": "banana", + "language_code": "en", }, - 'chat': { - 'id': 666666, - 'first_name': 'Moshe', - 'username': 'banana', - 'type': 'private' + "chat": { + "id": 666666, + "first_name": "Moshe", + "username": "banana", + "type": "private", }, - 'date': 1611240725, - 'text': f'{text}' - } + "date": 1611240725, + "text": f"{text}", + }, } def gen_callback(text): return { - 'update_id': 568265, - 'callback_query': { - 'id': '546565356486', - 'from': { - 'id': 666666, - 'is_bot': False, - 'first_name': 'Moshe', - 'username': 'banana', - 'language_code': 'en' - }, 'message': { - 'message_id': 838, - 'from': { - 'id': 2566252, - 'is_bot': True, - 'first_name': 'PyLandar', - 'username': 'pylander_bot' - }, 'chat': { - 'id': 666666, - 'first_name': 'Moshe', - 'username': 'banana', - 'type': 'private' + "update_id": 568265, + "callback_query": { + "id": "546565356486", + "from": { + "id": 666666, + "is_bot": False, + "first_name": "Moshe", + "username": "banana", + "language_code": "en", + }, + "message": { + "message_id": 838, + "from": { + "id": 2566252, + "is_bot": True, + "first_name": "PyLandar", + "username": "pylander_bot", + }, + "chat": { + "id": 666666, + "first_name": "Moshe", + "username": "banana", + "type": "private", }, - 'date': 161156, - 'text': 'Choose events day.', - 'reply_markup': { - 'inline_keyboard': [ + "date": 161156, + "text": "Choose events day.", + "reply_markup": { + "inline_keyboard": [ [ + {"text": "Today", "callback_data": "Today"}, { - 'text': 'Today', - 'callback_data': 'Today' + "text": "This week", + "callback_data": "This week", }, - { - 'text': 'This week', - 'callback_data': 'This week' - } - ] - ] - } + ], + ], + }, }, - 'chat_instance': '-154494', - 'data': f'{text}'}} + "chat_instance": "-154494", + "data": f"{text}", + }, + } class TestChatModel: - @staticmethod def test_private_message(): - chat = Chat(gen_message('Cool message')) - assert chat.message == 'Cool message' + chat = Chat(gen_message("Cool message")) + assert chat.message == "Cool message" assert chat.user_id == 666666 - assert chat.first_name == 'Moshe' + assert chat.first_name == "Moshe" @staticmethod def test_callback_message(): - chat = Chat(gen_callback('Callback Message')) - assert chat.message == 'Callback Message' + chat = Chat(gen_callback("Callback Message")) + assert chat.message == "Callback Message" assert chat.user_id == 666666 - assert chat.first_name == 'Moshe' + assert chat.first_name == "Moshe" @pytest.mark.asyncio async def test_bot_model(): bot = Bot("fake bot id", "https://google.com") - assert bot.base == 'https://api.telegram.org/botfake bot id/' - assert bot.webhook_setter_url == 'https://api.telegram.org/botfake \ -bot id/setWebhook?url=https://google.com/telegram/' + assert bot.base == "https://api.telegram.org/botfake bot id/" + assert ( + bot.webhook_setter_url + == "https://api.telegram.org/botfake \ +bot id/setWebhook?url=https://google.com/telegram/" + ) assert bot.base == bot._set_base_url("fake bot id") assert bot.webhook_setter_url == bot._set_webhook_setter_url( - "https://google.com") + "https://google.com", + ) set_request = await bot.set_webhook() assert set_request.json() == { - 'ok': False, - 'error_code': 404, - 'description': 'Not Found' + "ok": False, + "error_code": 404, + "description": "Not Found", } drop_request = await bot.drop_webhook() assert drop_request.json() == { - 'ok': False, - 'error_code': 404, - 'description': 'Not Found' + "ok": False, + "error_code": 404, + "description": "Not Found", } send_request = await bot.send_message("654654645", "hello") assert send_request.status_code == status.HTTP_404_NOT_FOUND assert send_request.json() == { - 'ok': False, - 'error_code': 404, - 'description': 'Not Found' + "ok": False, + "error_code": 404, + "description": "Not Found", } class TestBotClient: - @staticmethod @pytest.mark.asyncio async def test_user_not_registered(telegram_client): response = await telegram_client.post( - '/telegram/', json=gen_message('/start')) + "/telegram/", + json=gen_message("/start"), + ) assert response.status_code == status.HTTP_200_OK - assert b'Hello, Moshe!' in response.content - assert b'To use PyLendar Bot you have to register' \ - in response.content + assert b"Hello, Moshe!" in response.content + assert b"To use PyLendar Bot you have to register" in response.content @staticmethod @pytest.mark.asyncio @@ -148,9 +152,11 @@ async def test_user_registered(telegram_client, session): session.add(get_test_placeholder_user()) session.commit() response = await telegram_client.post( - '/telegram/', json=gen_message('/start')) + "/telegram/", + json=gen_message("/start"), + ) assert response.status_code == status.HTTP_200_OK - assert b'Welcome to PyLendar telegram client!' in response.content + assert b"Welcome to PyLendar telegram client!" in response.content class TestHandlers: @@ -158,21 +164,27 @@ class TestHandlers: @pytest.mark.asyncio async def test_start_handlers(self): - chat = Chat(gen_message('/start')) + chat = Chat(gen_message("/start")) message = MessageHandler(chat, self.TEST_USER) - assert '/start' in message.handlers - assert await message.process_callback() == '''Hello, Moshe! -Welcome to PyLendar telegram client!''' + assert "/start" in message.handlers + assert ( + await message.process_callback() + == """Hello, Moshe! +Welcome to PyLendar telegram client!""" + ) @pytest.mark.asyncio async def test_default_handlers(self): wrong_start = MessageHandler( - Chat(gen_message('start')), self.TEST_USER) + Chat(gen_message("start")), + self.TEST_USER, + ) wrong_show_events = MessageHandler( - Chat(gen_message('show_events')), self.TEST_USER) - message = MessageHandler( - Chat(gen_message('hello')), self.TEST_USER) + Chat(gen_message("show_events")), + self.TEST_USER, + ) + message = MessageHandler(Chat(gen_message("hello")), self.TEST_USER) assert await wrong_start.process_callback() == "Unknown command." assert await wrong_show_events.process_callback() == "Unknown command." @@ -180,34 +192,34 @@ async def test_default_handlers(self): @pytest.mark.asyncio async def test_show_events_handler(self): - chat = Chat(gen_message('/show_events')) + chat = Chat(gen_message("/show_events")) message = MessageHandler(chat, self.TEST_USER) - assert await message.process_callback() == 'Choose events day.' + assert await message.process_callback() == "Choose events day." @pytest.mark.asyncio async def test_no_today_events_handler(self): - chat = Chat(gen_callback('Today')) + chat = Chat(gen_callback("Today")) message = MessageHandler(chat, self.TEST_USER) assert await message.process_callback() == "There're no events today." @pytest.mark.asyncio async def test_today_handler(self, fake_user_events): - chat = Chat(gen_callback('Today')) + chat = Chat(gen_callback("Today")) message = MessageHandler(chat, fake_user_events) answer = f"{today_date.strftime('%A, %B %d')}:\n" assert await message.process_callback() == answer @pytest.mark.asyncio async def test_this_week_handler(self): - chat = Chat(gen_callback('This week')) + chat = Chat(gen_callback("This week")) message = MessageHandler(chat, self.TEST_USER) - assert await message.process_callback() == 'Choose a day.' + assert await message.process_callback() == "Choose a day." @pytest.mark.asyncio async def test_no_chosen_day_handler(self): - chat = Chat(gen_callback('10 Feb 2021')) + chat = Chat(gen_callback("10 Feb 2021")) message = MessageHandler(chat, self.TEST_USER) - message.handlers['10 Feb 2021'] = message.chosen_day_handler + message.handlers["10 Feb 2021"] = message.chosen_day_handler answer = "There're no events on February 10." assert await message.process_callback() == answer @@ -223,99 +235,101 @@ async def test_chosen_day_handler(self, fake_user_events): @pytest.mark.asyncio async def test_new_event_handler(self): - chat = Chat(gen_message('/new_event')) + chat = Chat(gen_message("/new_event")) message = MessageHandler(chat, self.TEST_USER) - answer = 'Please, give your event a title.' + answer = "Please, give your event a title." assert await message.process_callback() == answer @pytest.mark.asyncio async def test_process_new_event(self): - chat = Chat(gen_message('New Title')) + chat = Chat(gen_message("New Title")) message = MessageHandler(chat, self.TEST_USER) - answer = 'Title:\nNew Title\n\n' - answer += 'Add a description of the event.' + answer = "Title:\nNew Title\n\n" + answer += "Add a description of the event." assert await message.process_callback() == answer - chat = Chat(gen_message('New Content')) + chat = Chat(gen_message("New Content")) message = MessageHandler(chat, self.TEST_USER) - answer = 'Content:\nNew Content\n\n' - answer += 'Where the event will be held?' + answer = "Content:\nNew Content\n\n" + answer += "Where the event will be held?" assert await message.process_callback() == answer - chat = Chat(gen_message('Universe')) + chat = Chat(gen_message("Universe")) message = MessageHandler(chat, self.TEST_USER) - answer = 'Location:\nUniverse\n\n' - answer += 'When does it start?' + answer = "Location:\nUniverse\n\n" + answer += "When does it start?" assert await message.process_callback() == answer - chat = Chat(gen_message('Not valid start datetime input')) + chat = Chat(gen_message("Not valid start datetime input")) message = MessageHandler(chat, self.TEST_USER) - answer = '❗️ Please, enter a valid date/time.' + answer = "❗️ Please, enter a valid date/time." assert await message.process_callback() == answer - chat = Chat(gen_message('today')) + chat = Chat(gen_message("today")) message = MessageHandler(chat, self.TEST_USER) today = datetime.today() answer = f'Starts on:\n{today.strftime("%d %b %Y %H:%M")}\n\n' - answer += 'And when does it end?' + answer += "And when does it end?" assert await message.process_callback() == answer - chat = Chat(gen_message('Not valid end datetime input')) + chat = Chat(gen_message("Not valid end datetime input")) message = MessageHandler(chat, self.TEST_USER) - answer = '❗️ Please, enter a valid date/time.' + answer = "❗️ Please, enter a valid date/time." assert await message.process_callback() == answer - chat = Chat(gen_message('tomorrow')) + chat = Chat(gen_message("tomorrow")) message = MessageHandler(chat, self.TEST_USER) tomorrow = today + timedelta(days=1) - answer = 'Title:\nNew Title\n\n' - answer += 'Content:\nNew Content\n\n' - answer += 'Location:\nUniverse\n\n' + answer = "Title:\nNew Title\n\n" + answer += "Content:\nNew Content\n\n" + answer += "Location:\nUniverse\n\n" answer += f'Starts on:\n{today.strftime("%d %b %Y %H:%M")}\n\n' answer += f'Ends on:\n{tomorrow.strftime("%d %b %Y %H:%M")}' assert await message.process_callback() == answer - chat = Chat(gen_message('create')) + chat = Chat(gen_message("create")) message = MessageHandler(chat, self.TEST_USER) - answer = 'New event was successfully created 🎉' + answer = "New event was successfully created 🎉" assert await message.process_callback() == answer @pytest.mark.asyncio async def test_process_new_event_cancel(self): - chat = Chat(gen_message('/new_event')) + chat = Chat(gen_message("/new_event")) message = MessageHandler(chat, self.TEST_USER) - answer = 'Please, give your event a title.' + answer = "Please, give your event a title." assert await message.process_callback() == answer - chat = Chat(gen_message('cancel')) + chat = Chat(gen_message("cancel")) message = MessageHandler(chat, self.TEST_USER) - answer = '🚫 The process was canceled.' + answer = "🚫 The process was canceled." assert await message.process_callback() == answer @pytest.mark.asyncio async def test_process_new_event_restart(self): - chat = Chat(gen_message('/new_event')) + chat = Chat(gen_message("/new_event")) message = MessageHandler(chat, self.TEST_USER) - answer = 'Please, give your event a title.' + answer = "Please, give your event a title." assert await message.process_callback() == answer - chat = Chat(gen_message('New Title')) + chat = Chat(gen_message("New Title")) message = MessageHandler(chat, self.TEST_USER) - answer = 'Title:\nNew Title\n\n' - answer += 'Add a description of the event.' + answer = "Title:\nNew Title\n\n" + answer += "Add a description of the event." assert await message.process_callback() == answer - chat = Chat(gen_message('restart')) + chat = Chat(gen_message("restart")) message = MessageHandler(chat, self.TEST_USER) - answer = 'Please, give your event a title.' + answer = "Please, give your event a title." assert await message.process_callback() == answer @pytest.mark.asyncio async def test_reply_unknown_user(): - chat = Chat(gen_message('/show_events')) + chat = Chat(gen_message("/show_events")) answer = await reply_unknown_user(chat) - assert answer == ''' + assert ( + answer + == """ Hello, Moshe! To use PyLendar Bot you have to register @@ -325,4 +339,5 @@ async def test_reply_unknown_user(): Keep it secret! https://calendar.pythonic.guru/profile/ -''' +""" + ) diff --git a/tests/test_calendar_privacy.py b/tests/test_calendar_privacy.py index d94dfd56..0fde3d0a 100644 --- a/tests/test_calendar_privacy.py +++ b/tests/test_calendar_privacy.py @@ -1,7 +1,8 @@ from app.internal.calendar_privacy import can_show_calendar + # TODO after user system is merged: -# from app.internal.security.dependencies import CurrentUser -from app.routers.user import create_user +# from app.internal.security.dependancies import CurrentUser +from app.routers.register import _create_user def test_can_show_calendar_public(session, user): @@ -10,32 +11,37 @@ def test_can_show_calendar_public(session, user): # current_user = CurrentUser(**user.__dict__) current_user = user result = can_show_calendar( - requested_user_username='test_username', - db=session, current_user=current_user + requested_user_username="test_username", + db=session, + current_user=current_user, ) assert result is True session.commit() def test_can_show_calendar_private(session, user): - another_user = create_user( + another_user = _create_user( session=session, - username='new_test_username2', - email='new_test.email2@gmail.com', - password='passpar_2', - language_id=1 + username="new_test_username2", + email="new_test.email2@gmail.com", + password="passpar_2", + language_id=1, + full_name="test_full_name", + description="test_description", ) current_user = user # TODO to be replaced after user system is merged: # current_user = CurrentUser(**user.__dict__) result_a = can_show_calendar( - requested_user_username='new_test_username2', - db=session, current_user=current_user + requested_user_username="new_test_username2", + db=session, + current_user=current_user, ) result_b = can_show_calendar( - requested_user_username='test_username', - db=session, current_user=current_user + requested_user_username="test_username", + db=session, + current_user=current_user, ) assert result_a is False assert result_b is True diff --git a/tests/test_google_connect.py b/tests/test_google_connect.py index 02511266..58ac8aa3 100644 --- a/tests/test_google_connect.py +++ b/tests/test_google_connect.py @@ -5,12 +5,13 @@ import app.internal.google_connect as google_connect from app.routers.event import create_event from app.database.models import OAuthCredentials -from app.routers.user import create_user from google.oauth2.credentials import Credentials from googleapiclient.discovery import build from googleapiclient.http import HttpMock +from app.routers.register import _create_user + @pytest.fixture def google_events_mock(): @@ -24,25 +25,13 @@ def google_events_mock(): "created": "2021-01-13T09:10:02.000Z", "updated": "2021-01-13T09:10:02.388Z", "summary": "some title", - "creator": { - "email": "someemail", - "self": True - }, - "organizer": { - "email": "someemail", - "self": True - }, - "start": { - "dateTime": "2021-02-25T13:00:00+02:00" - }, - "end": { - "dateTime": "2021-02-25T14:00:00+02:00" - }, + "creator": {"email": "someemail", "self": True}, + "organizer": {"email": "someemail", "self": True}, + "start": {"dateTime": "2021-02-25T13:00:00+02:00"}, + "end": {"dateTime": "2021-02-25T14:00:00+02:00"}, "iCalUID": "somecode", "sequence": 0, - "reminders": { - "useDefault": True - } + "reminders": {"useDefault": True}, }, { "kind": "calendar#event", @@ -53,27 +42,15 @@ def google_events_mock(): "created": "2021-01-13T09:10:02.000Z", "updated": "2021-01-13T09:10:02.388Z", "summary": "some title to all day event", - "creator": { - "email": "someemail", - "self": True - }, - "organizer": { - "email": "someemail", - "self": True - }, - "start": { - "date": "2021-02-25" - }, - "end": { - "date": "2021-02-25" - }, + "creator": {"email": "someemail", "self": True}, + "organizer": {"email": "someemail", "self": True}, + "start": {"date": "2021-02-25"}, + "end": {"date": "2021-02-25"}, "iCalUID": "somecode", "sequence": 0, - "location": 'somelocation', - "reminders": { - "useDefault": True - } - } + "location": "somelocation", + "reminders": {"useDefault": True}, + }, ] @@ -85,7 +62,7 @@ def credentials(): token_uri="some_uri", client_id="somecode", client_secret="some_secret", - expiry=datetime(2021, 1, 28) + expiry=datetime(2021, 1, 28), ) return cred @@ -100,30 +77,30 @@ def test_push_events_to_db(google_events_mock, user, session): def test_db_cleanup(google_events_mock, user, session): for event in google_events_mock: location = None - title = event['summary'] + title = event["summary"] # support for all day events - if 'dateTime' in event['start'].keys(): + if "dateTime" in event["start"].keys(): # part time event - start = datetime.fromisoformat(event['start']['dateTime']) - end = datetime.fromisoformat(event['end']['dateTime']) + start = datetime.fromisoformat(event["start"]["dateTime"]) + end = datetime.fromisoformat(event["end"]["dateTime"]) else: # all day event - start = event['start']['date'].split('-') + start = event["start"]["date"].split("-") start = datetime( year=int(start[0]), month=int(start[1]), - day=int(start[2]) + day=int(start[2]), ) - end = event['end']['date'].split('-') + end = event["end"]["date"].split("-") end = datetime( year=int(end[0]), month=int(end[1]), - day=int(end[2]) + day=int(end[2]), ) - if 'location' in event.keys(): - location = event['location'] + if "location" in event.keys(): + location = event["location"] create_event( db=session, @@ -132,20 +109,26 @@ def test_db_cleanup(google_events_mock, user, session): end=end, owner_id=user.id, location=location, - is_google_event=True + is_google_event=True, ) assert google_connect.cleanup_user_google_calendar_events( - user, session) + user, + session, + ) @pytest.mark.usefixtures("session") def test_get_credentials_from_db(session): - user = create_user(session=session, - username='new_test_username', - password='new_test_password', - email='new_test.email@gmail.com', - language_id=1) + user = _create_user( + session=session, + username="new_test_username", + password="new_test_password", + email="new_test.email@gmail.com", + language_id=1, + full_name="test_full_name", + description="test_description", + ) credentials = OAuthCredentials( owner=user, @@ -154,7 +137,7 @@ def test_get_credentials_from_db(session): token_uri="some_uri", client_id="somecode", client_secret="some_secret", - expiry=datetime(2021, 2, 22) + expiry=datetime(2021, 2, 22), ) session.add(credentials) session.commit() @@ -166,17 +149,16 @@ def test_get_credentials_from_db(session): @pytest.mark.usefixtures("session", "user", "credentials") def test_refresh_token(mocker, session, user, credentials): - mocker.patch( - 'google.oauth2.credentials.Credentials.refresh', - return_value=logger.debug('refreshed') + "google.oauth2.credentials.Credentials.refresh", + return_value=logger.debug("refreshed"), ) assert google_connect.refresh_token(credentials, user, session) mocker.patch( - 'google.oauth2.credentials.Credentials.expired', - return_value=False + "google.oauth2.credentials.Credentials.expired", + return_value=False, ) assert google_connect.refresh_token(credentials, user, session) @@ -189,76 +171,75 @@ def __init__(self, service): self.service = service def list(self, *args): - request = self.service.events().list(calendarId='primary', - timeMin=datetime( - 2021, 1, 1).isoformat(), - timeMax=datetime( - 2022, 1, 1).isoformat(), - singleEvents=True, - orderBy='startTime' - ) - http = HttpMock( - 'calendar-linux.json', - {'status': '200'} + request = self.service.events().list( + calendarId="primary", + timeMin=datetime(2021, 1, 1).isoformat(), + timeMax=datetime(2022, 1, 1).isoformat(), + singleEvents=True, + orderBy="startTime", ) + http = HttpMock("calendar-linux.json", {"status": "200"}) response = request.execute(http=http) return response - http = HttpMock( - './tests/calendar-discovery.json', - {'status': '200'} - ) + http = HttpMock("./tests/calendar-discovery.json", {"status": "200"}) - service = build('calendar', 'v3', http=http) + service = build("calendar", "v3", http=http) mocker.patch( - 'googleapiclient.discovery.build', + "googleapiclient.discovery.build", return_value=service, - events=service + events=service, ) mocker.patch( - 'googleapiclient.discovery.Resource', - events=mock_events(service) + "googleapiclient.discovery.Resource", + events=mock_events(service), ) assert google_connect.get_current_year_events(credentials, user, session) -@pytest.mark.usefixtures("user", "session", - "google_connect_test_client", "credentials") +@pytest.mark.usefixtures( + "user", + "session", + "google_connect_test_client", + "credentials", +) def test_google_sync(mocker, google_connect_test_client, session, credentials): - create_user(session=session, - username='new_test_username', - password='new_test_password', - email='new_test.email@gmail.com', - language_id=1) + _create_user( + session=session, + username="new_test_username", + password="new_test_password", + email="new_test.email@gmail.com", + language_id=1, + full_name="test_full_name", + description="test_description", + ) mocker.patch( - 'app.routers.google_connect.get_credentials', - return_value=credentials + "app.routers.google_connect.get_credentials", + return_value=credentials, ) mocker.patch( - 'app.routers.google_connect.fetch_save_events', - return_value=None + "app.routers.google_connect.fetch_save_events", + return_value=None, ) connect = google_connect_test_client.get( - 'google/sync', - headers={ - "referer": 'http://testserver/' - }) + "google/sync", + headers={"referer": "http://testserver/"}, + ) assert connect.ok # second case mocker.patch( - 'app.routers.google_connect.get_credentials', - return_value=None + "app.routers.google_connect.get_credentials", + return_value=None, ) connect = google_connect_test_client.get( - 'google/sync', - headers={ - "referer": 'http://testserver/' - }) + "google/sync", + headers={"referer": "http://testserver/"}, + ) assert connect.ok @@ -270,97 +251,125 @@ def test_is_client_secret_none(): @pytest.mark.usefixtures("session") def test_clean_up_old_credentials_from_db(session): google_connect.clean_up_old_credentials_from_db(session) - assert len(session.query(OAuthCredentials) - .filter_by(user_id=None).all()) == 0 + assert ( + len(session.query(OAuthCredentials).filter_by(user_id=None).all()) == 0 + ) -@pytest.mark.usefixtures("session", 'user', 'credentials') -def test_get_credentials_from_consent_screen(mocker, session, - user, credentials): +@pytest.mark.usefixtures("session", "user", "credentials") +def test_get_credentials_from_consent_screen( + mocker, + session, + user, + credentials, +): mocker.patch( - 'google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file', - return_value=mocker.Mock(name='flow', **{ - "credentials": credentials, - "run_local_server": mocker.Mock(name='run_local_server', - return_value=logger.debug( - 'running server')) - }) + "google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file", + return_value=mocker.Mock( + name="flow", + **{ + "credentials": credentials, + "run_local_server": mocker.Mock( + name="run_local_server", + return_value=logger.debug("running server"), + ), + } + ), ) mocker.patch( - 'app.internal.google_connect.is_client_secret_none', - return_value=False + "app.internal.google_connect.is_client_secret_none", + return_value=False, ) - assert google_connect.get_credentials_from_consent_screen( - user, session) == credentials + assert ( + google_connect.get_credentials_from_consent_screen(user, session) + == credentials + ) @pytest.mark.usefixtures("session") def test_create_google_event(session): - user = create_user(session=session, - username='new_test_username', - password='new_test_password', - email='new_test.email@gmail.com', - language_id=1) + user = _create_user( + session=session, + username="new_test_username", + password="new_test_password", + email="new_test.email@gmail.com", + language_id=1, + full_name="test_full_name", + description="test_description", + ) event = google_connect.create_google_event( - 'title', - datetime(2021, 1, 1, 15, 15), - datetime(2021, 1, 1, 15, 30), - user, - 'location', - session - ) + "title", + datetime(2021, 1, 1, 15, 15), + datetime(2021, 1, 1, 15, 30), + user, + "location", + session, + ) - assert event.title == 'title' + assert event.title == "title" -@pytest.mark.usefixtures("session", "user", 'credentials') +@pytest.mark.usefixtures("session", "user", "credentials") def test_get_credentials(mocker, session, user, credentials): - user = create_user( + user = _create_user( session=session, - username='new_test_username', - password='new_test_password', - email='new_test.email@gmail.com', - language_id=1 + username="new_test_username", + password="new_test_password", + email="new_test.email@gmail.com", + language_id=1, + full_name="test_full_name", + description="test_description", ) mocker.patch( - 'app.internal.google_connect.get_credentials_from_consent_screen', - return_value=credentials + "app.internal.google_connect.get_credentials_from_consent_screen", + return_value=credentials, ) - assert google_connect.get_credentials(user=user, - session=session) == credentials + assert ( + google_connect.get_credentials(user=user, session=session) + == credentials + ) mocker.patch( - 'app.internal.google_connect.get_credentials', - return_value=credentials + "app.internal.google_connect.get_credentials", + return_value=credentials, ) mocker.patch( - 'app.internal.google_connect.refresh_token', - return_value=credentials + "app.internal.google_connect.refresh_token", + return_value=credentials, ) - assert google_connect.get_credentials(user=user, - session=session) == credentials - + assert ( + google_connect.get_credentials(user=user, session=session) + == credentials + ) -@pytest.mark.usefixtures("session", "user", - 'credentials', 'google_events_mock') -def test_fetch_save_events(mocker, session, user, credentials, - google_events_mock): +@pytest.mark.usefixtures( + "session", + "user", + "credentials", + "google_events_mock", +) +def test_fetch_save_events( + mocker, + session, + user, + credentials, + google_events_mock, +): mocker.patch( - 'app.internal.google_connect.get_current_year_events', - return_value=google_events_mock + "app.internal.google_connect.get_current_year_events", + return_value=google_events_mock, ) - assert google_connect.fetch_save_events(credentials, - user, session) is None + assert google_connect.fetch_save_events(credentials, user, session) is None -@pytest.mark.usefixtures("session", "user", 'credentials') +@pytest.mark.usefixtures("session", "user", "credentials") def test_push_credentials_to_db(session, user, credentials): assert google_connect.push_credentials_to_db(credentials, user, session) diff --git a/tests/test_invitation.py b/tests/test_invitation.py deleted file mode 100644 index c609a973..00000000 --- a/tests/test_invitation.py +++ /dev/null @@ -1,50 +0,0 @@ -from fastapi import status - -from app.routers.invitation import get_all_invitations, get_invitation_by_id - - -class TestInvitations: - NO_INVITATIONS = b"You don't have any invitations." - URL = "/invitations/" - - @staticmethod - def test_view_no_invitations(invitation_test_client): - response = invitation_test_client.get(TestInvitations.URL) - assert response.ok - assert TestInvitations.NO_INVITATIONS in response.content - - @staticmethod - def test_accept_invitations(user, invitation, invitation_test_client): - invitation = {"invite_id ": invitation.id} - resp = invitation_test_client.post( - TestInvitations.URL, data=invitation) - assert resp.status_code == status.HTTP_302_FOUND - - @staticmethod - def test_get_all_invitations_success(invitation, event, user, session): - invitations = get_all_invitations(event=event, db=session) - assert invitations == [invitation] - invitations = get_all_invitations(recipient=user, db=session) - assert invitations == [invitation] - - @staticmethod - def test_get_all_invitations_failure(user, session): - invitations = get_all_invitations(unknown_parameter=user, db=session) - assert invitations == [] - - invitations = get_all_invitations(recipient=None, db=session) - assert invitations == [] - - @staticmethod - def test_get_invitation_by_id(invitation, session): - get_invitation = get_invitation_by_id(invitation.id, db=session) - assert get_invitation == invitation - - @staticmethod - def test_repr(invitation): - invitation_repr = ( - f'' - ) - assert invitation.__repr__() == invitation_repr diff --git a/tests/test_notification.py b/tests/test_notification.py new file mode 100644 index 00000000..23eacfd2 --- /dev/null +++ b/tests/test_notification.py @@ -0,0 +1,177 @@ +from starlette.status import HTTP_406_NOT_ACCEPTABLE + +from app.database.models import InvitationStatusEnum, MessageStatusEnum +from app.internal.notification import get_all_invitations, get_invitation_by_id +from app.routers.notification import router +from tests.fixtures.client_fixture import login_client + + +class TestNotificationRoutes: + NO_NOTIFICATIONS = b"You don't have any new notifications." + NO_NOTIFICATION_IN_ARCHIVE = b"You don't have any archived notifications." + NEW_NOTIFICATIONS_URL = router.url_path_for("view_notifications") + LOGIN_DATA = {"username": "test_username", "password": "test_password"} + + def test_view_no_notifications( + self, + user, + notification_test_client, + ): + login_client(notification_test_client, self.LOGIN_DATA) + resp = notification_test_client.get(self.NEW_NOTIFICATIONS_URL) + assert resp.ok + assert self.NO_NOTIFICATIONS in resp.content + + def test_accept_invitations( + self, + user, + invitation, + notification_test_client, + ): + login_client(notification_test_client, self.LOGIN_DATA) + assert invitation.status == InvitationStatusEnum.UNREAD + data = { + "invite_id": invitation.id, + "next_url": self.NEW_NOTIFICATIONS_URL, + } + url = router.url_path_for("accept_invitations") + resp = notification_test_client.post(url, data=data) + assert resp.ok + assert InvitationStatusEnum.ACCEPTED + + def test_decline_invitations( + self, + user, + invitation, + notification_test_client, + session, + ): + login_client(notification_test_client, self.LOGIN_DATA) + assert invitation.status == InvitationStatusEnum.UNREAD + data = { + "invite_id": invitation.id, + "next_url": self.NEW_NOTIFICATIONS_URL, + } + url = router.url_path_for("decline_invitations") + resp = notification_test_client.post(url, data=data) + assert resp.ok + session.refresh(invitation) + assert invitation.status == InvitationStatusEnum.DECLINED + + def test_mark_message_as_read( + self, + user, + message, + notification_test_client, + session, + ): + login_client(notification_test_client, self.LOGIN_DATA) + assert message.status == MessageStatusEnum.UNREAD + data = { + "message_id": message.id, + "next_url": self.NEW_NOTIFICATIONS_URL, + } + url = router.url_path_for("mark_message_as_read") + resp = notification_test_client.post(url, data=data) + assert resp.ok + session.refresh(message) + assert message.status == MessageStatusEnum.READ + + def test_mark_all_as_read( + self, + user, + message, + sec_message, + notification_test_client, + session, + ): + login_client(notification_test_client, self.LOGIN_DATA) + url = router.url_path_for("mark_all_as_read") + assert message.status == MessageStatusEnum.UNREAD + assert sec_message.status == MessageStatusEnum.UNREAD + data = {"next_url": self.NEW_NOTIFICATIONS_URL} + resp = notification_test_client.post(url, data=data) + assert resp.ok + session.refresh(message) + session.refresh(sec_message) + assert message.status == MessageStatusEnum.READ + assert sec_message.status == MessageStatusEnum.READ + + def test_archive( + self, + user, + message, + notification_test_client, + session, + ): + login_client(notification_test_client, self.LOGIN_DATA) + archive_url = router.url_path_for("view_archive") + resp = notification_test_client.get(archive_url) + assert resp.ok + assert self.NO_NOTIFICATION_IN_ARCHIVE in resp.content + + # read message + data = { + "message_id": message.id, + "next_url": self.NEW_NOTIFICATIONS_URL, + } + url = router.url_path_for("mark_message_as_read") + notification_test_client.post(url, data=data) + + resp = notification_test_client.get(archive_url) + assert resp.ok + assert self.NO_NOTIFICATION_IN_ARCHIVE not in resp.content + + def test_wrong_id( + self, + user, + notification_test_client, + session, + ): + login_client(notification_test_client, self.LOGIN_DATA) + data = { + "message_id": 1, + "next_url": "/", + } + url = router.url_path_for("mark_message_as_read") + resp = notification_test_client.post(url, data=data) + assert resp.status_code == HTTP_406_NOT_ACCEPTABLE + + +class TestNotification: + def test_get_all_invitations_success( + self, + invitation, + event, + user, + session, + ): + invitations = get_all_invitations(event=event, session=session) + assert invitations == [invitation] + invitations = get_all_invitations(recipient=user, session=session) + assert invitations == [invitation] + + def test_get_all_invitations_failure(self, user, session): + invitations = get_all_invitations( + unknown_parameter=user, + session=session, + ) + assert invitations == [] + + invitations = get_all_invitations(recipient=None, session=session) + assert invitations == [] + + def test_get_invitation_by_id(self, invitation, session): + get_invitation = get_invitation_by_id(invitation.id, session=session) + assert get_invitation == invitation + + def test_invitation_repr(self, invitation): + invitation_repr = ( + f"" + ) + assert invitation.__repr__() == invitation_repr + + def test_message_repr(self, message): + message_repr = f"" + assert message.__repr__() == message_repr diff --git a/tests/test_share_event.py b/tests/test_share_event.py index 67679b2c..e202597a 100644 --- a/tests/test_share_event.py +++ b/tests/test_share_event.py @@ -1,49 +1,68 @@ -from app.routers.invitation import get_all_invitations -from app.routers.share import (accept, send_email_invitation, - send_in_app_invitation, share, sort_emails) +from app.database.models import InvitationStatusEnum +from app.internal.notification import get_all_invitations +from app.routers.share import ( + send_email_invitation, + send_in_app_invitation, + share, + sort_emails, +) class TestShareEvent: - def test_share_success(self, user, event, session): - participants = [user.email] - share(event, participants, session) - invitations = get_all_invitations(db=session, recipient_id=user.id) + share(event, [user.email], session) + invitations = get_all_invitations( + session=session, + recipient_id=user.id, + ) assert invitations != [] def test_share_failure(self, event, session): participants = [event.owner.email] share(event, participants, session) invitations = get_all_invitations( - db=session, recipient_id=event.owner.id) + session=session, + recipient_id=event.owner.id, + ) assert invitations == [] def test_sort_emails(self, user, session): # the user is being imported # so he will be created data = [ - 'test.email@gmail.com', # registered user - 'not_logged_in@gmail.com', # unregistered user + "test.email@gmail.com", # registered user + "not_logged_in@gmail.com", # unregistered user ] sorted_data = sort_emails(data, session=session) assert sorted_data == { - 'registered': ['test.email@gmail.com'], - 'unregistered': ['not_logged_in@gmail.com'] + "registered": ["test.email@gmail.com"], + "unregistered": ["not_logged_in@gmail.com"], } def test_send_in_app_invitation_success( - self, user, sender, event, session + self, + user, + sender, + event, + session, ): assert send_in_app_invitation([user.email], event, session=session) - invitation = get_all_invitations(db=session, recipient=user)[0] + invitation = get_all_invitations(session=session, recipient=user)[0] assert invitation.event.owner == sender assert invitation.recipient == user session.delete(invitation) def test_send_in_app_invitation_failure( - self, user, sender, event, session): - assert (send_in_app_invitation( - [sender.email], event, session=session) is False) + self, + user, + sender, + event, + session, + ): + assert ( + send_in_app_invitation([sender.email], event, session=session) + is False + ) def test_send_email_invitation(self, user, event): send_email_invitation([user.email], event) @@ -51,5 +70,9 @@ def test_send_email_invitation(self, user, event): assert True def test_accept(self, invitation, session): - accept(invitation, session=session) - assert invitation.status == 'accepted' + invitation.accept(session=session) + assert invitation.status == InvitationStatusEnum.ACCEPTED + + def test_decline(self, invitation, session): + invitation.decline(session=session) + assert invitation.status == InvitationStatusEnum.DECLINED diff --git a/tests/test_statistics.py b/tests/test_statistics.py index 7ef52afb..10cc8457 100644 --- a/tests/test_statistics.py +++ b/tests/test_statistics.py @@ -1,40 +1,63 @@ import datetime +from app.internal.notification import get_all_invitations from app.internal.statistics import get_statistics from app.internal.statistics import INVALID_DATE_RANGE, INVALID_USER from app.internal.statistics import SUCCESS_STATUS from app.routers.event import create_event -from app.routers.user import create_user -from app.routers.share import send_in_app_invitation, accept -from app.routers.invitation import get_all_invitations +from app.routers.register import _create_user +from app.routers.share import send_in_app_invitation def create_events_and_user_events(session, start, end, owner, invitations): for _ in range(1, 3): event = create_event( - db=session, title="title" + str(_), start=start, end=end, - owner_id=owner, location="location" + str(_)) + db=session, + title="title" + str(_), + start=start, + end=end, + owner_id=owner, + location="location" + str(_), + ) send_in_app_invitation(invitations, event, session) def create_data(session): - _ = [create_user("user" + str(_), "password" + str(_), - "email" + str(_) + '@' + 'gmail.com', "Hebrew", - session) for _ in range(1, 4)] + _ = [ + _create_user( + username="user" + str(_), + password="password" + str(_), + email="email" + str(_) + "@" + "gmail.com", + language_id="Hebrew", + session=session, + description="", + full_name="", + ) + for _ in range(1, 4) + ] start = datetime.datetime.now() + datetime.timedelta(hours=-1) end = datetime.datetime.now() + datetime.timedelta(hours=1) - create_events_and_user_events(session, start, end, 1, - ["email2@gmail.com", "email3@gmail.com"]) + create_events_and_user_events( + session, + start, + end, + 1, + ["email2@gmail.com", "email3@gmail.com"], + ) start = datetime.datetime.now() + datetime.timedelta(days=-1) end = datetime.datetime.now() + datetime.timedelta(days=-1, hours=2) - create_events_and_user_events(session, start, end, 1, - ["email2@gmail.com", "email3@gmail.com"]) + create_events_and_user_events( + session, + start, + end, + 1, + ["email2@gmail.com", "email3@gmail.com"], + ) start = datetime.datetime.now() + datetime.timedelta(hours=1) end = datetime.datetime.now() + datetime.timedelta(hours=1.5) - create_events_and_user_events(session, start, end, 2, - ["email3@gmail.com"]) + create_events_and_user_events(session, start, end, 2, ["email3@gmail.com"]) for invitation in get_all_invitations(session): - accept(invitation, session) + invitation.accept(session) def test_statistics_invalid_date_range(session): diff --git a/tests/test_user.py b/tests/test_user.py index 213e7589..1a1ed0a7 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -1,9 +1,8 @@ from datetime import datetime import pytest -from app.routers.user import ( - create_user, does_user_exist, get_users -) +from app.routers.register import _create_user +from app.routers.user import does_user_exist, get_users from app.internal.user.availability import disable, enable from app.internal.utils import save from app.database.models import UserEvent, Event @@ -13,12 +12,14 @@ @pytest.fixture def user1(session): # a user made for testing who doesn't own any event. - user = create_user( + user = _create_user( session=session, - username='new_test_username', - password='new_test_password', - email='new2_test.email@gmail.com', - language_id='english' + username="new_test_username", + full_name="test_user", + password="new_test_password", + email="new2_test.email@gmail.com", + language_id="english", + description="", ) return user @@ -27,21 +28,23 @@ def user1(session): @pytest.fixture def user2(session): # a user made for testing who already owns an event. - user = create_user( + user = _create_user( session=session, - username='new_test_username2', - password='new_test_password2', - email='new_test_love231.email@gmail.com', - language_id='english' + username="new_test_username2", + full_name="test_user", + password="new_test_password2", + email="new_test_love231.email@gmail.com", + language_id="english", + description="", ) data = { - 'title': 'user2 event', - 'start': datetime.strptime('2021-05-05 14:59', '%Y-%m-%d %H:%M'), - 'end': datetime.strptime('2021-05-05 15:01', '%Y-%m-%d %H:%M'), - 'location': 'https://us02web.zoom.us/j/875384596', - 'content': 'content', - 'owner_id': user.id, + "title": "user2 event", + "start": datetime.strptime("2021-05-05 14:59", "%Y-%m-%d %H:%M"), + "end": datetime.strptime("2021-05-05 15:01", "%Y-%m-%d %H:%M"), + "location": "https://us02web.zoom.us/j/875384596", + "content": "content", + "owner_id": user.id, } create_event(session, **data) @@ -52,12 +55,12 @@ def user2(session): @pytest.fixture def event1(session, user2): data = { - 'title': 'test event title', - 'start': datetime.strptime('2021-05-05 14:59', '%Y-%m-%d %H:%M'), - 'end': datetime.strptime('2021-05-05 15:01', '%Y-%m-%d %H:%M'), - 'location': 'https://us02web.zoom.us/j/87538459r6', - 'content': 'content', - 'owner_id': user2.id, + "title": "test event title", + "start": datetime.strptime("2021-05-05 14:59", "%Y-%m-%d %H:%M"), + "end": datetime.strptime("2021-05-05 15:01", "%Y-%m-%d %H:%M"), + "location": "https://us02web.zoom.us/j/87538459r6", + "content": "content", + "owner_id": user2.id, } event = create_event(session, **data) @@ -68,41 +71,41 @@ def test_disabling_no_event_user(session, user1): # users without any future event can disable themselves disable(session, user1.id) assert user1.disabled - future_events = list(session.query(Event.id) - .join(UserEvent) - .filter( - UserEvent.user_id == user1.id, - Event.start > datetime - .now())) + future_events = list( + session.query(Event.id) + .join(UserEvent) + .filter(UserEvent.user_id == user1.id, Event.start > datetime.now()), + ) assert not future_events # making sure that after disabling the user he can be easily enabled. enable(session, user1.id) assert not user1.disabled -def test_disabling_user_participating_event( - session, user1, event1): +def test_disabling_user_participating_event(session, user1, event1): """making sure only users who only participate in events can disable and enable themselves.""" - association = UserEvent( - user_id=user1.id, - event_id=event1.id - ) + association = UserEvent(user_id=user1.id, event_id=event1.id) save(session, association) disable(session, user1.id) assert user1.disabled - future_events = list(session.query(Event.id) - .join(UserEvent) - .filter( - UserEvent.user_id == user1.id, - Event.start > datetime.now(), - Event.owner_id == user1.id)) + future_events = list( + session.query(Event.id) + .join(UserEvent) + .filter( + UserEvent.user_id == user1.id, + Event.start > datetime.now(), + Event.owner_id == user1.id, + ), + ) assert not future_events enable(session, user1.id) assert not user1.disabled - deleted_user_event_connection = session.query(UserEvent).filter( - UserEvent.user_id == user1.id, - UserEvent.event_id == event1.id).first() + deleted_user_event_connection = ( + session.query(UserEvent) + .filter(UserEvent.user_id == user1.id, UserEvent.event_id == event1.id) + .first() + ) session.delete(deleted_user_event_connection) @@ -113,18 +116,19 @@ def test_disabling_event_owning_user(session, user2): class TestUser: - def test_create_user(self, session): - user = create_user( + user = _create_user( session=session, - username='new_test_username', - password='new_test_password', - email='new_test.email@gmail.com', - language_id=1 + username="new_test_username", + password="new_test_password", + email="new_test.email@gmail.com", + language_id=1, + description="", + full_name="test_user", ) - assert user.username == 'new_test_username' - assert user.password == 'new_test_password' - assert user.email == 'new_test.email@gmail.com' + assert user.username == "new_test_username" + assert user.password == "new_test_password" + assert user.email == "new_test.email@gmail.com" assert user.language_id == 1 session.delete(user) session.commit() @@ -135,7 +139,7 @@ def test_get_users_success(self, user, session): assert get_users(email=user.email, session=session) == [user] def test_get_users_failure(self, session, user): - assert get_users(username='wrong username', session=session) == [] + assert get_users(username="wrong username", session=session) == [] assert get_users(wrong_param=user.username, session=session) == [] def test_does_user_exist_success(self, user, session): @@ -144,8 +148,8 @@ def test_does_user_exist_success(self, user, session): assert does_user_exist(email=user.email, session=session) def test_does_user_exist_failure(self, session): - assert not does_user_exist(username='wrong username', session=session) + assert not does_user_exist(username="wrong username", session=session) assert not does_user_exist(session=session) def test_repr(self, user): - assert user.__repr__() == f'' + assert user.__repr__() == f"" diff --git a/tests/utils.py b/tests/utils.py deleted file mode 100644 index 58ffdbd0..00000000 --- a/tests/utils.py +++ /dev/null @@ -1,13 +0,0 @@ -from sqlalchemy.orm import Session - - -def create_model(session: Session, model_class, **kw): - instance = model_class(**kw) - session.add(instance) - session.commit() - return instance - - -def delete_instance(session: Session, instance): - session.delete(instance) - session.commit() From a30cbd854f99e7175bac7dbc078b5595be01419d Mon Sep 17 00:00:00 2001 From: itzik Date: Wed, 24 Feb 2021 18:19:51 +0200 Subject: [PATCH 29/32] fix: for Changes requeste --- app/database/models.py | 14 +++--- app/internal/weekly_tasks.py | 63 ++++++++++++------------- app/routers/weekly_tasks.py | 12 ++--- app/templates/add_edit_weekly_task.html | 4 +- app/templates/weekly_tasks_manager.html | 2 +- tests/test_weekly_tasks_internal.py | 54 +++++++++++---------- tests/test_weekly_tasks_route.py | 6 +-- tests/weekly_tasks_fixture.py | 14 +++--- 8 files changed, 85 insertions(+), 84 deletions(-) diff --git a/app/database/models.py b/app/database/models.py index b1fcfbf2..92ef9746 100644 --- a/app/database/models.py +++ b/app/database/models.py @@ -8,6 +8,7 @@ from sqlalchemy import ( Boolean, Column, + Date, DateTime, DDL, event, @@ -277,13 +278,14 @@ class Task(Base): id = Column(Integer, primary_key=True, index=True) title = Column(String) - content = Column(String) - is_done = Column(Boolean, nullable=False) + description = Column(String) + is_done = Column(Boolean, default=False) is_important = Column(Boolean, nullable=False) - date_time = Column(DateTime, nullable=False) + date = Column(Date, nullable=False) + time = Column(Time, nullable=False) + owner_id = Column(Integer, ForeignKey("users.id")) - user_id = Column(Integer, ForeignKey("users.id")) - owner = relationship("User", back_populates=__tablename__) + owner = relationship("User", back_populates="tasks") class WeeklyTask(Base): @@ -294,7 +296,7 @@ class WeeklyTask(Base): days = Column(String, nullable=False) content = Column(String) is_important = Column(Boolean, nullable=False) - the_time = Column(String, nullable=False) + task_time = Column(String, nullable=False) user_id = Column(Integer, ForeignKey("users.id")) owner = relationship("User", back_populates=__tablename__) diff --git a/app/internal/weekly_tasks.py b/app/internal/weekly_tasks.py index eb8901d3..f27fb5d5 100644 --- a/app/internal/weekly_tasks.py +++ b/app/internal/weekly_tasks.py @@ -6,9 +6,9 @@ from sqlalchemy.orm.session import Session -def check_inputs(days: str, the_time: time, title: str) -> bool: +def check_inputs(days: str, task_time: time, title: str) -> bool: """Checks inputs, used by the weekly_task_from_input function""" - return days and the_time and title + return days and task_time and title def weekly_task_from_input( @@ -16,7 +16,7 @@ def weekly_task_from_input( title: Optional[str], days: str, content: Optional[str], - the_time: Optional[time], + task_time: Optional[time], is_important: bool, weekly_task_id: int = 0, ) -> WeeklyTask: @@ -28,7 +28,7 @@ def weekly_task_from_input( title (str): Title of the Weekly Task. days (str): Return days of the Weekly Task. content (str): Content of the Weekly Task. - the_time (time): Return time of the Weekly Task. + task_time (time): Return time of the Weekly Task. is_important (bool): If the task is important. weekly_task_id (int): The id of the weekly task, zero if not mentioned. @@ -49,16 +49,15 @@ def weekly_task_from_input( if weekly_task_id != 0: weekly_task.id = weekly_task_id - inputs_ok = check_inputs(days, the_time, title) + inputs_ok = check_inputs(days, task_time, title) if not inputs_ok: return weekly_task weekly_task.set_days(days) - weekly_task.the_time = the_time.strftime("%H:%M") + weekly_task.task_time = task_time.strftime("%H:%M") return weekly_task def create_weekly_task( - user: User, weekly_task: WeeklyTask, session: Session, ) -> bool: @@ -72,12 +71,12 @@ def create_weekly_task( Returns: bool: Shows if the weekly_task has been added to the db. """ - if not weekly_task.days or not weekly_task.the_time: - return False - task_titles = ( - user_weekly_task.title for user_weekly_task in user.weekly_tasks + inputs_ok = check_inputs( + weekly_task.days, + weekly_task.task_time, + weekly_task.title, ) - if weekly_task.title in task_titles: + if not inputs_ok: return False session.add(weekly_task) session.commit() @@ -100,20 +99,16 @@ def change_weekly_task( Returns: bool: Shows if the weekly_task has been edited in the db. """ - if weekly_task.days is None or weekly_task.the_time is None: + inputs_ok = check_inputs( + weekly_task.days, + weekly_task.task_time, + weekly_task.title, + ) + if not inputs_ok: return False w_task_query = session.query(WeeklyTask) old_weekly_task = w_task_query.filter_by(id=weekly_task.id).first() - user_titles = ( - user_weekly_task.title - for user_weekly_task in user.weekly_tasks - if user_weekly_task.title != old_weekly_task.title - ) - - if weekly_task.title in user_titles: - return False - if weekly_task.user_id != user.id: return False @@ -121,16 +116,17 @@ def change_weekly_task( old_weekly_task.days = weekly_task.days old_weekly_task.content = weekly_task.content old_weekly_task.is_important = weekly_task.is_important - old_weekly_task.the_time = weekly_task.the_time + old_weekly_task.task_time = weekly_task.task_time session.commit() return True def create_task(task: Task, user: User, session: Session) -> bool: """Make a task, used by the generate_tasks function""" - user_tasks_query = session.query(Task).filter_by(user_id=user.id) - task_by_time = user_tasks_query.filter_by(date_time=task.date_time) - task_by_title_and_time = task_by_time.filter_by(title=task.title) + user_tasks_query = session.query(Task).filter_by(owner_id=user.id) + task_by_time = user_tasks_query.filter_by(time=task.time) + task_by_date_time = task_by_time.filter_by(date=task.date) + task_by_title_and_time = task_by_date_time.filter_by(title=task.title) task_exist = task_by_title_and_time.first() if task_exist: return False @@ -139,13 +135,13 @@ def create_task(task: Task, user: User, session: Session) -> bool: return True -def get_datetime(day: str, the_time: str) -> datetime: +def get_datetime(day: str, task_time: str) -> datetime: """Getting the datetime of days in the current week, used by the generate_tasks function""" current_date = date.today() current_week_num = current_date.strftime("%W") current_year = current_date.strftime("%Y") - date_string = f"{day} {the_time} {current_week_num} {current_year}" + date_string = f"{day} {task_time} {current_week_num} {current_year}" return datetime.strptime(date_string, "%a %H:%M %W %Y") @@ -153,18 +149,19 @@ def generate_tasks(user: User, session: Session) -> Iterator[bool]: """Generates tasks for the week based on all the weekly tasks the user have""" for weekly_task in user.weekly_tasks: - the_time = weekly_task.the_time + task_time = weekly_task.task_time days = weekly_task.get_days() days_list = days.split(", ") for day in days_list: - date_time = get_datetime(day, the_time) + date_time = get_datetime(day, task_time) task = Task( title=weekly_task.title, - content=weekly_task.content, + description=weekly_task.content, is_done=False, is_important=weekly_task.is_important, - date_time=date_time, - user_id=user.id, + date=date_time.date(), + time=date_time.time(), + owner_id=user.id, ) yield create_task(task, user, session) diff --git a/app/routers/weekly_tasks.py b/app/routers/weekly_tasks.py index 76b6f6a1..357db43c 100644 --- a/app/routers/weekly_tasks.py +++ b/app/routers/weekly_tasks.py @@ -70,7 +70,7 @@ def get_days_string( return days -@router.get("/") +@router.get("/", include_in_schema=False) async def weekly_tasks_manager( request: Request, user: schema.CurrentUser = Depends(current_user_from_db), @@ -165,7 +165,7 @@ def weekly_task_execute( sat: bool = Form(False), content: str = Form(None), is_important: bool = Form(False), - the_time: datetime.time = Form(None), + task_time: datetime.time = Form(None), weekly_task_id: int = Form(...), ): @@ -177,14 +177,14 @@ def weekly_task_execute( title, days, content, - the_time, + task_time, is_important, weekly_task_id=weekly_task_id, ) if mode == "add": # creating the weekly task - created = create_weekly_task(user, weekly_task, session) + created = create_weekly_task(weekly_task, session) executed = created else: # mode == "edit": @@ -223,7 +223,7 @@ def weekly_task_failed( days: str = Cookie(...), is_important: bool = Cookie(False), ): - the_time = None + task_time = None if title == "None": title = None if content == "None": @@ -233,7 +233,7 @@ def weekly_task_failed( title, days, content, - the_time, + task_time, is_important, id, ) diff --git a/app/templates/add_edit_weekly_task.html b/app/templates/add_edit_weekly_task.html index eda9f74f..f4dbb94f 100644 --- a/app/templates/add_edit_weekly_task.html +++ b/app/templates/add_edit_weekly_task.html @@ -58,8 +58,8 @@

Add Weekly Tasks

- - + +
diff --git a/app/templates/weekly_tasks_manager.html b/app/templates/weekly_tasks_manager.html index d8802ab5..167fed54 100644 --- a/app/templates/weekly_tasks_manager.html +++ b/app/templates/weekly_tasks_manager.html @@ -16,7 +16,7 @@

Weekly Tasks

Every: {{ weekly_task.get_days() }} - at: {{ weekly_task.the_time }} + at: {{ weekly_task.task_time }} diff --git a/tests/test_weekly_tasks_internal.py b/tests/test_weekly_tasks_internal.py index df19de1b..beebe616 100644 --- a/tests/test_weekly_tasks_internal.py +++ b/tests/test_weekly_tasks_internal.py @@ -13,9 +13,13 @@ def test_weekly_tasks_check_inputs(weekly_task_time): - ok = check_inputs(days="", the_time=None, title="the title") + ok = check_inputs(days="", task_time=None, title="the title") assert not ok - ok = check_inputs(days="Sun", the_time=weekly_task_time, title="the title") + ok = check_inputs( + days="Sun", + task_time=weekly_task_time, + title="the title", + ) assert ok @@ -23,38 +27,36 @@ def test_weekly_tasks_create_task(user, session): date_time = datetime(2021, 1, 21, 3, 19) task = Task( title="task1", - content="my content", + description="my description", is_done=False, is_important=True, - date_time=date_time, - user_id=user.id, + date=date_time.date(), + time=date_time.time(), + owner_id=user.id, ) created = create_task(task, user, session) assert created created = create_task(task, user, session) assert not created created_task = user.tasks[0] - assert created_task.date_time == date_time + assert created_task.date == date_time.date() + assert created_task.time == date_time.time() def test_create_weekly_task(user, session, weekly_task): # creating the weekly task weekly_task.user_id = user.id - created = create_weekly_task(user, weekly_task, session) + created = create_weekly_task(weekly_task, session) assert created # checks if weekly task been added to the db user_w_t = user.weekly_tasks[0] assert user_w_t assert user_w_t.content == weekly_task.content - assert user_w_t.the_time == weekly_task.the_time - - # trying to add weekly task with the same title - created = create_weekly_task(user, weekly_task, session) - assert not created + assert user_w_t.task_time == weekly_task.task_time # adding without a title weekly_task.title = None - created = create_weekly_task(user, weekly_task, session) + created = create_weekly_task(weekly_task, session) assert not created # the user's weekly tasks should remain in quantity 1 @@ -71,12 +73,12 @@ def test_change_weekly_task( ): # creating weekly task for edit testing weekly_task.user_id = user.id - created = create_weekly_task(user, weekly_task, session) + created = create_weekly_task(weekly_task, session) assert created # creating another weekly task for edit testing weekly_task2.user_id = user.id - created = create_weekly_task(user, weekly_task2, session) + created = create_weekly_task(weekly_task2, session) assert created user_w_t = user.weekly_tasks assert len(user_w_t) == 2 @@ -96,10 +98,10 @@ def test_change_weekly_task( assert changed_user_w_t.title == weekly_task.title assert changed_user_w_t.content == weekly_task.content - # trying to edit weekly task for an existing title - # weekly_task3.title == weekly_task2.title + # editing without a title weekly_task3.user_id = user.id weekly_task3.id = edit_id + weekly_task3.title = None changed = change_weekly_task(user, weekly_task3, session) assert not changed edited_w_t = user.weekly_tasks[0] @@ -115,7 +117,7 @@ def test_weekly_task_change_permission( ): # creating the weekly task weekly_task.user_id = user.id - created = create_weekly_task(user, weekly_task, session) + created = create_weekly_task(weekly_task, session) assert created user_w_task = user.weekly_tasks[0] assert user_w_task @@ -148,7 +150,7 @@ def test_weekly_task_from_input(user, weekly_task, weekly_task_time): assert w_t.days == weekly_task.days assert w_t.content == weekly_task.content assert w_t.is_important == weekly_task.is_important - assert w_t.the_time == weekly_task.the_time + assert w_t.task_time == weekly_task.task_time # not all inputs are ok w_t = weekly_task_from_input( @@ -163,12 +165,12 @@ def test_weekly_task_from_input(user, weekly_task, weekly_task_time): # As much data as possible is saved, except for time and days assert w_t.content == weekly_task.content assert w_t.days != weekly_task.days - assert w_t.the_time != weekly_task.the_time + assert w_t.task_time != weekly_task.task_time def test_remove_weekly_task(user, session, weekly_task): weekly_task.user_id = user.id - created = create_weekly_task(user, weekly_task, session) + created = create_weekly_task(weekly_task, session) assert created # Checks if the weekly task exists in the db @@ -188,7 +190,7 @@ def test_remove_weekly_task(user, session, weekly_task): def test_weekly_tasks_generate_tasks(user, session, weekly_task): weekly_task.user_id = user.id - created = create_weekly_task(user, weekly_task, session) + created = create_weekly_task(weekly_task, session) assert created # Activates the generator @@ -205,11 +207,11 @@ def test_weekly_tasks_generate_tasks(user, session, weekly_task): # The Tasks should be defined according to the weekly task for task in tasks: assert weekly_task.title == task.title - assert weekly_task.content == task.content + assert weekly_task.content == task.description assert weekly_task.is_important == task.is_important - time_string = task.date_time.strftime("%H:%M") - assert weekly_task.the_time == time_string - day = task.date_time.strftime("%a") + time_string = task.time.strftime("%H:%M") + assert weekly_task.task_time == time_string + day = task.date.strftime("%a") assert day in weekly_task.get_days() # another activation at the same day diff --git a/tests/test_weekly_tasks_route.py b/tests/test_weekly_tasks_route.py index ee566ae8..4854d34f 100644 --- a/tests/test_weekly_tasks_route.py +++ b/tests/test_weekly_tasks_route.py @@ -36,7 +36,7 @@ def test_weekly_tasks_add( assert weekly_task.title.encode() in data assert weekly_task.get_days().encode() in data assert weekly_task.content.encode() in data - assert weekly_task.the_time.encode() in data + assert weekly_task.task_time.encode() in data def test_weekly_tasks_failed_add(weekly_tasks_test_client, weekly_task): @@ -84,7 +84,7 @@ def test_weekly_tasks_edit( assert b"Edit Weekly Tasks" in data assert weekly_task.title.encode() in data assert weekly_task.content.encode() in data - assert weekly_task.the_time.encode() in data + assert weekly_task.task_time.encode() in data # Sets the input to edit mode input_weekly_task["mode"] = "edit" @@ -111,7 +111,7 @@ def test_weekly_tasks_edit( assert weekly_task.get_days().encode() not in data assert b"Mon, Thu, Fri, Sat" in data assert weekly_task.content.encode() in data - assert weekly_task.the_time.encode() in data + assert weekly_task.task_time.encode() in data def test_weekly_tasks_failed_edit( diff --git a/tests/weekly_tasks_fixture.py b/tests/weekly_tasks_fixture.py index ee23c345..66b03405 100644 --- a/tests/weekly_tasks_fixture.py +++ b/tests/weekly_tasks_fixture.py @@ -10,7 +10,7 @@ def weekly_task(): title="Test Task 1", content="my content", is_important=True, - the_time="11:00", + task_time="11:00", ) w_t.set_days("Mon, Sat, Sun") return w_t @@ -22,7 +22,7 @@ def weekly_task2(): title="Test Task 2", content="my content2", is_important=False, - the_time="12:00", + task_time="12:00", ) w_t.set_days("Sat, Sun") return w_t @@ -35,7 +35,7 @@ def weekly_task3(): days="Sat", content="my content3", is_important=False, - the_time="12:00", + task_time="12:00", ) w_t.set_days("Sat") return w_t @@ -50,14 +50,14 @@ def input_weekly_task(): "sat": True, "content": "my content", "is_important": True, - "the_time": "11:00", + "task_time": "11:00", } @pytest.fixture def weekly_task_time(weekly_task): - date_time_string = f"2021-01-28 {weekly_task.the_time}" + date_time_string = f"2021-01-28 {weekly_task.task_time}" date_time_format = "%Y-%m-%d %H:%M" date_time = datetime.strptime(date_time_string, date_time_format) - the_time = date_time.time() - return the_time + task_time = date_time.time() + return task_time From d2104595e2231a3ed6dc74abaa27b4fe46aabae1 Mon Sep 17 00:00:00 2001 From: itzik Date: Wed, 24 Feb 2021 20:19:30 +0200 Subject: [PATCH 30/32] Revert "local merge" This reverts commit 3e2b357e26d73ed55388aa0cfc6e2c14da8892d4, reversing changes made to a30cbd854f99e7175bac7dbc078b5595be01419d. --- .DS_Store | Bin 6148 -> 0 bytes .gitignore | 4 - AUTHORS.md | 1 - app/database/models.py | 72 +--- app/database/schemas.py | 50 +-- app/internal/event.py | 38 +-- app/internal/notification.py | 176 ---------- app/internal/utils.py | 36 +- app/main.py | 4 +- app/routers/event.py | 20 +- app/routers/export.py | 21 +- app/routers/invitation.py | 110 ++++++ app/routers/login.py | 42 +-- app/routers/notification.py | 192 ----------- app/routers/register.py | 17 +- app/routers/share.py | 28 +- app/routers/user.py | 49 ++- app/static/event/eventview.css | 10 +- app/static/notification.css | 70 ---- app/templates/archive.html | 26 -- app/templates/base.html | 72 ++-- app/templates/calendar/layout.html | 83 ----- app/templates/invitations.html | 24 ++ app/templates/notifications.html | 38 --- .../event/view_event_details_tab.html | 53 ++- .../partials/calendar/navigation.html | 5 - app/templates/partials/index/navigation.html | 14 +- app/templates/partials/notification/base.html | 56 --- .../notification/generate_archive.html | 29 -- .../notification/generate_notifications.html | 48 --- requirements.txt | 10 +- tests/{fixtures => }/association_fixture.py | 0 tests/{fixtures => }/asyncio_fixture.py | 12 +- tests/{fixtures => }/category_fixture.py | 0 tests/{fixtures => }/client_fixture.py | 23 +- tests/{fixtures => }/comment_fixture.py | 0 tests/conftest.py | 65 ++-- tests/{fixtures => }/dayview_fixture.py | 0 tests/{fixtures => }/event_fixture.py | 37 +- tests/fixtures/__init__.py | 0 tests/fixtures/message_fixture.py | 29 -- tests/{fixtures => }/invitation_fixture.py | 0 tests/{fixtures => }/jokes_fixture.py | 2 +- tests/{fixtures => }/logger_fixture.py | 0 tests/{fixtures => }/quotes_fixture.py | 0 tests/salary/test_routes.py | 1 + tests/test_a_telegram_asyncio.py | 285 ++++++++-------- tests/test_calendar_privacy.py | 32 +- tests/test_geolocation.py | 105 ------ tests/test_google_connect.py | 323 +++++++++--------- tests/test_invitation.py | 50 +++ tests/test_notification.py | 177 ---------- tests/test_share_event.py | 61 ++-- tests/test_statistics.py | 53 +-- tests/test_user.py | 120 ++++--- tests/{fixtures => }/user_fixture.py | 21 +- tests/utils.py | 13 + tests/{fixtures => }/weekly_tasks_fixture.py | 0 tests/{fixtures => }/zodiac_fixture.py | 0 59 files changed, 858 insertions(+), 1949 deletions(-) delete mode 100644 .DS_Store delete mode 100644 app/internal/notification.py create mode 100644 app/routers/invitation.py delete mode 100644 app/routers/notification.py delete mode 100644 app/static/notification.css delete mode 100644 app/templates/archive.html delete mode 100644 app/templates/calendar/layout.html create mode 100644 app/templates/invitations.html delete mode 100644 app/templates/notifications.html delete mode 100644 app/templates/partials/notification/base.html delete mode 100644 app/templates/partials/notification/generate_archive.html delete mode 100644 app/templates/partials/notification/generate_notifications.html rename tests/{fixtures => }/association_fixture.py (100%) rename tests/{fixtures => }/asyncio_fixture.py (83%) rename tests/{fixtures => }/category_fixture.py (100%) rename tests/{fixtures => }/client_fixture.py (93%) rename tests/{fixtures => }/comment_fixture.py (100%) rename tests/{fixtures => }/dayview_fixture.py (100%) rename tests/{fixtures => }/event_fixture.py (82%) delete mode 100644 tests/fixtures/__init__.py delete mode 100644 tests/fixtures/message_fixture.py rename tests/{fixtures => }/invitation_fixture.py (100%) rename tests/{fixtures => }/jokes_fixture.py (89%) rename tests/{fixtures => }/logger_fixture.py (100%) rename tests/{fixtures => }/quotes_fixture.py (100%) delete mode 100644 tests/test_geolocation.py create mode 100644 tests/test_invitation.py delete mode 100644 tests/test_notification.py rename tests/{fixtures => }/user_fixture.py (68%) create mode 100644 tests/utils.py rename tests/{fixtures => }/weekly_tasks_fixture.py (100%) rename tests/{fixtures => }/zodiac_fixture.py (100%) diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 None: - """declines the invitation.""" - self.status = InvitationStatusEnum.DECLINED - session.merge(self) - session.commit() - - def accept(self, session: Session) -> None: - """Accepts the invitation by creating an - UserEvent association that represents - participantship at the event.""" - - association = UserEvent( - user_id=self.recipient.id, - event_id=self.event.id, - ) - self.status = InvitationStatusEnum.ACCEPTED - session.merge(self) - session.add(association) - session.commit() - - def __repr__(self): - return f"" - - -class Message(Base): - __tablename__ = "messages" - - id = Column(Integer, primary_key=True, index=True) - body = Column(String, nullable=False) - link = Column(String) - creation = Column(DateTime, default=datetime.now, nullable=False) - status = Column( - Enum(MessageStatusEnum), - default=MessageStatusEnum.UNREAD, - nullable=False, - ) + creation = Column(DateTime, default=datetime.now) - recipient_id = Column(Integer, ForeignKey("users.id")) recipient = relationship("User") - - def mark_as_read(self, session): - self.status = MessageStatusEnum.READ - session.merge(self) - session.commit() + event = relationship("Event") def __repr__(self): - return f"" + return f"" class UserSettings(Base): diff --git a/app/database/schemas.py b/app/database/schemas.py index 29748b6f..61d31a33 100644 --- a/app/database/schemas.py +++ b/app/database/schemas.py @@ -2,7 +2,7 @@ from pydantic import BaseModel, validator, EmailStr, EmailError -EMPTY_FIELD_STRING = "field is required" +EMPTY_FIELD_STRING = 'field is required' MIN_FIELD_LENGTH = 3 MAX_FIELD_LENGTH = 20 @@ -19,14 +19,10 @@ class UserBase(BaseModel): Validating fields types Returns a User object without sensitive information """ - username: str email: str full_name: str - - language_id: Optional[int] = 1 description: Optional[str] = None - target_weight: Optional[Union[int, float]] = None class Config: orm_mode = True @@ -34,7 +30,6 @@ class Config: class UserCreate(UserBase): """Validating fields types""" - password: str confirm_password: str @@ -42,49 +37,41 @@ class UserCreate(UserBase): Calling to field_not_empty validaion function, for each required field. """ - _fields_not_empty_username = validator("username", allow_reuse=True)( - fields_not_empty, - ) - _fields_not_empty_full_name = validator("full_name", allow_reuse=True)( - fields_not_empty, - ) - _fields_not_empty_password = validator("password", allow_reuse=True)( - fields_not_empty, - ) + _fields_not_empty_username = validator( + 'username', allow_reuse=True)(fields_not_empty) + _fields_not_empty_full_name = validator( + 'full_name', allow_reuse=True)(fields_not_empty) + _fields_not_empty_password = validator( + 'password', allow_reuse=True)(fields_not_empty) _fields_not_empty_confirm_password = validator( - "confirm_password", - allow_reuse=True, - )(fields_not_empty) - _fields_not_empty_email = validator("email", allow_reuse=True)( - fields_not_empty, - ) - - @validator("confirm_password") + 'confirm_password', allow_reuse=True)(fields_not_empty) + _fields_not_empty_email = validator( + 'email', allow_reuse=True)(fields_not_empty) + + @validator('confirm_password') def passwords_match( - cls, - confirm_password: str, - values: UserBase, - ) -> Union[ValueError, str]: + cls, confirm_password: str, + values: UserBase) -> Union[ValueError, str]: """Validating passwords fields identical.""" - if "password" in values and confirm_password != values["password"]: + if 'password' in values and confirm_password != values['password']: raise ValueError("doesn't match to password") return confirm_password - @validator("username") + @validator('username') def username_length(cls, username: str) -> Union[ValueError, str]: """Validating username length is legal""" if not (MIN_FIELD_LENGTH < len(username) < MAX_FIELD_LENGTH): raise ValueError("must contain between 3 to 20 charactars") return username - @validator("password") + @validator('password') def password_length(cls, password: str) -> Union[ValueError, str]: """Validating username length is legal""" if not (MIN_FIELD_LENGTH < len(password) < MAX_FIELD_LENGTH): raise ValueError("must contain between 3 to 20 charactars") return password - @validator("email") + @validator('email') def confirm_mail(cls, email: str) -> Union[ValueError, str]: """Validating email is valid mail address.""" try: @@ -99,6 +86,5 @@ class User(UserBase): Validating fields types Returns a User object without sensitive information """ - id: int is_active: bool diff --git a/app/internal/event.py b/app/internal/event.py index a771149c..57b29d27 100644 --- a/app/internal/event.py +++ b/app/internal/event.py @@ -1,29 +1,17 @@ import logging import re -from typing import List, NamedTuple, Set, Union +from typing import List, Set from email_validator import EmailSyntaxError, validate_email from fastapi import HTTPException -from geopy.adapters import AioHTTPAdapter -from geopy.exc import GeocoderTimedOut, GeocoderUnavailable -from geopy.geocoders import Nominatim -from loguru import logger from sqlalchemy.orm import Session from starlette.status import HTTP_400_BAD_REQUEST from app.database.models import Event - ZOOM_REGEX = re.compile(r"https://.*?\.zoom.us/[a-z]/.[^.,\b\s]+") -class Location(NamedTuple): - # Location type hint class. - latitude: str - longitude: str - name: str - - def raise_if_zoom_link_invalid(vc_link): if ZOOM_REGEX.search(vc_link) is None: raise HTTPException( @@ -113,27 +101,3 @@ def get_messages( f"Want to create another one {weeks_diff} after too?", ) return messages - - -async def get_location_coordinates( - address: str, -) -> Union[Location, str]: - """Return location coordinates and accurate - address of the specified location.""" - try: - async with Nominatim( - user_agent="Pylendar", - adapter_factory=AioHTTPAdapter, - ) as geolocator: - geolocation = await geolocator.geocode(address) - except (GeocoderTimedOut, GeocoderUnavailable) as e: - logger.exception(str(e)) - else: - if geolocation is not None: - location = Location( - latitude=geolocation.latitude, - longitude=geolocation.longitude, - name=geolocation.raw["display_name"], - ) - return location - return address diff --git a/app/internal/notification.py b/app/internal/notification.py deleted file mode 100644 index af86c9bb..00000000 --- a/app/internal/notification.py +++ /dev/null @@ -1,176 +0,0 @@ -from operator import attrgetter -from typing import Iterator, List, Union, Callable - -from fastapi import HTTPException -from sqlalchemy.exc import SQLAlchemyError -from sqlalchemy.orm import Session -from starlette.status import HTTP_401_UNAUTHORIZED, HTTP_406_NOT_ACCEPTABLE - -from app.database.models import ( - Invitation, - Message, - InvitationStatusEnum, - MessageStatusEnum, -) -from app.internal.utils import create_model - - -WRONG_NOTIFICATION_ID = ( - "The notification id you have entered is wrong\n." - "If you did not enter the notification id manually, report this exception." -) - -NOTIFICATION_TYPE = Union[Invitation, Message] - -UNREAD_STATUS = { - InvitationStatusEnum.UNREAD, - MessageStatusEnum.UNREAD, -} - -ARCHIVED = { - InvitationStatusEnum.DECLINED, - MessageStatusEnum.READ, -} - - -async def get_message_by_id( - message_id: int, - session: Session, -) -> Union[Message, None]: - """Returns an invitation by an id. - if id does not exist, returns None. - """ - return session.query(Message).filter_by(id=message_id).first() - - -def _is_unread(notification: NOTIFICATION_TYPE) -> bool: - """Returns True if notification is unread, False otherwise.""" - return notification.status in UNREAD_STATUS - - -def _is_archived(notification: NOTIFICATION_TYPE) -> bool: - """Returns True if notification should be - in archived page, False otherwise. - """ - return notification.status in ARCHIVED - - -def is_owner(user, notification: NOTIFICATION_TYPE) -> bool: - """Checks if user is owner of the notification. - - Args: - notification: a NOTIFICATION_TYPE object. - user: user schema object. - - Returns: - True or raises HTTPException. - """ - if notification.recipient_id == user.user_id: - return True - - msg = "The notification you are trying to access is not yours." - raise HTTPException( - status_code=HTTP_401_UNAUTHORIZED, - detail=msg, - ) - - -def raise_wrong_id_error() -> None: - """Raises HTTPException. - - Returns: - None - """ - raise HTTPException( - status_code=HTTP_406_NOT_ACCEPTABLE, - detail=WRONG_NOTIFICATION_ID, - ) - - -def filter_notifications( - session: Session, - user_id: int, - func: Callable[[NOTIFICATION_TYPE], bool], -) -> Iterator[NOTIFICATION_TYPE]: - """Filters notifications by "func".""" - yield from filter(func, get_all_notifications(session, user_id)) - - -def get_unread_notifications( - session: Session, - user_id: int, -) -> Iterator[NOTIFICATION_TYPE]: - """Returns all unread notifications.""" - yield from filter_notifications(session, user_id, _is_unread) - - -def get_archived_notifications( - session: Session, - user_id: int, -) -> List[NOTIFICATION_TYPE]: - """Returns all archived notifications.""" - yield from filter_notifications(session, user_id, _is_archived) - - -def get_all_notifications( - session: Session, - user_id: int, -) -> List[NOTIFICATION_TYPE]: - """Returns all notifications.""" - invitations: List[Invitation] = get_all_invitations( - session, - recipient_id=user_id, - ) - messages: List[Message] = get_all_messages(session, user_id) - - notifications = invitations + messages - return sort_notifications(notifications) - - -def sort_notifications( - notification: List[NOTIFICATION_TYPE], -) -> List[NOTIFICATION_TYPE]: - """Sorts the notifications by the creation date.""" - return sorted(notification, key=attrgetter("creation"), reverse=True) - - -def create_message( - session: Session, - msg: str, - recipient_id: int, - link=None, -) -> Message: - """Creates a new message.""" - return create_model( - session, - Message, - body=msg, - recipient_id=recipient_id, - link=link, - ) - - -def get_all_messages(session: Session, recipient_id: int) -> List[Message]: - """Returns all messages.""" - condition = Message.recipient_id == recipient_id - return session.query(Message).filter(condition).all() - - -def get_all_invitations(session: Session, **param) -> List[Invitation]: - """Returns all invitations filter by param.""" - try: - invitations = session.query(Invitation).filter_by(**param).all() - except SQLAlchemyError: - return [] - else: - return invitations - - -def get_invitation_by_id( - invitation_id: int, - session: Session, -) -> Union[Invitation, None]: - """Returns an invitation by an id. - if id does not exist, returns None. - """ - return session.query(Invitation).filter_by(id=invitation_id).first() diff --git a/app/internal/utils.py b/app/internal/utils.py index a7e208f5..2f669212 100644 --- a/app/internal/utils.py +++ b/app/internal/utils.py @@ -2,8 +2,6 @@ from typing import Any, List, Optional, Union from sqlalchemy.orm import Session -from starlette.responses import RedirectResponse -from starlette.status import HTTP_302_FOUND from app.database.models import Base, User @@ -21,7 +19,6 @@ def save(session: Session, instance: Base) -> bool: def create_model(session: Session, model_class: Base, **kwargs: Any) -> Base: """Creates and saves a db model.""" instance = model_class(**kwargs) - save(session, instance) return instance @@ -72,7 +69,7 @@ def get_time_from_string(string: str) -> Optional[Union[date, time]]: datetime.time | datetime.date | None: Date or Time object if valid, None otherwise. """ - formats = {"%Y-%m-%d": "date", "%H:%M": "time", "%H:%M:%S": "time"} + formats = {'%Y-%m-%d': 'date', '%H:%M': 'time', '%H:%M:%S': 'time'} for time_format, method in formats.items(): try: time_obj = getattr(datetime.strptime(string, time_format), method) @@ -92,31 +89,10 @@ def get_placeholder_user() -> User: A User object. """ return User( - username="new_user", - email="my@email.po", - password="1a2s3d4f5g6", - full_name="My Name", + username='new_user', + email='my@email.po', + password='1a2s3d4f5g6', + full_name='My Name', language_id=1, - telegram_id="", + telegram_id='', ) - - -def safe_redirect_response( - url: str, - default: str = "/", - status_code: int = HTTP_302_FOUND, -): - """Returns a safe redirect response. - - Args: - url: the url to redirect to. - default: where to redirect if url isn't safe. - status_code: the response status code. - - Returns: - The Notifications HTML page. - """ - if not url.startswith("/"): - url = default - - return RedirectResponse(url=url, status_code=status_code) diff --git a/app/main.py b/app/main.py index 79866510..9a0ee412 100644 --- a/app/main.py +++ b/app/main.py @@ -63,11 +63,11 @@ def create_tables(engine, psql_environment): four_o_four, friendview, google_connect, + invitation, joke, login, logout, meds, - notification, profile, register, search, @@ -114,11 +114,11 @@ async def swagger_ui_redirect(): four_o_four.router, friendview.router, google_connect.router, + invitation.router, joke.router, login.router, logout.router, meds.router, - notification.router, profile.router, register.router, salary.router, diff --git a/app/routers/event.py b/app/routers/event.py index 7858ebba..d87e206e 100644 --- a/app/routers/event.py +++ b/app/routers/event.py @@ -16,24 +16,21 @@ from app.database.models import Comment, Event, User, UserEvent from app.dependencies import get_db, logger, templates -from app.internal import comment as cmt -from app.internal.emotion import get_emotion from app.internal.event import ( get_invited_emails, - get_location_coordinates, get_messages, get_uninvited_regular_emails, raise_if_zoom_link_invalid, ) +from app.internal import comment as cmt +from app.internal.emotion import get_emotion from app.internal.privacy import PrivacyKinds from app.internal.utils import create_model, get_current_user from app.routers.categories import get_user_categories - EVENT_DATA = Tuple[Event, List[Dict[str, str]], str] TIME_FORMAT = "%Y-%m-%d %H:%M" START_FORMAT = "%A, %d/%m/%Y %H:%M" - UPDATE_EVENTS_FIELDS = { "title": str, "start": dt, @@ -135,16 +132,9 @@ async def create_new_event( title, invited_emails, ) - latitude, longitude = None, None if vc_link: raise_if_zoom_link_invalid(vc_link) - else: - location_details = await get_location_coordinates(location) - if not isinstance(location_details, str): - location = location_details.name - latitude = location_details.latitude - longitude = location_details.longitude event = create_event( db=session, @@ -155,8 +145,6 @@ async def create_new_event( owner_id=owner_id, content=content, location=location, - latitude=latitude, - longitude=longitude, vc_link=vc_link, invitees=invited_emails, category_id=category_id, @@ -423,8 +411,6 @@ def create_event( content: Optional[str] = None, location: Optional[str] = None, vc_link: str = None, - latitude: Optional[str] = None, - longitude: Optional[str] = None, color: Optional[str] = None, invitees: List[str] = None, category_id: Optional[int] = None, @@ -446,8 +432,6 @@ def create_event( content=content, owner_id=owner_id, location=location, - latitude=latitude, - longitude=longitude, vc_link=vc_link, color=color, emotion=get_emotion(title, content), diff --git a/app/routers/export.py b/app/routers/export.py index 0fa5b279..a5fd4229 100644 --- a/app/routers/export.py +++ b/app/routers/export.py @@ -9,8 +9,7 @@ from app.dependencies import get_db from app.internal.agenda_events import get_events_in_time_frame from app.internal.export import get_icalendar_with_multiple_events -from app.internal.security.schema import CurrentUser -from tests.security_testing_routes import current_user +from app.internal.utils import get_current_user router = APIRouter( prefix="/export", @@ -21,10 +20,9 @@ @router.get("/") def export( - start_date: Union[date, str], - end_date: Union[date, str], - db: Session = Depends(get_db), - user: CurrentUser = Depends(current_user), + start_date: Union[date, str], + end_date: Union[date, str], + db: Session = Depends(get_db), ) -> StreamingResponse: """Returns the Export page route. @@ -32,18 +30,19 @@ def export( start_date: A date or an empty string. end_date: A date or an empty string. db: Optional; The database connection. - user: user schema object. Returns: - A StreamingResponse that contains an .ics file. + # TODO add description """ - events = get_events_in_time_frame(start_date, end_date, user.user_id, db) + # TODO: connect to real user + user = get_current_user(db) + events = get_events_in_time_frame(start_date, end_date, user.id, db) file = BytesIO(get_icalendar_with_multiple_events(db, list(events))) return StreamingResponse( content=file, media_type="text/calendar", headers={ - # Change filename to "PyLendar.ics". - "Content-Disposition": "attachment;filename=PyLendar.ics", + # Change filename to "pylandar.ics". + "Content-Disposition": "attachment;filename=pylandar.ics", }, ) diff --git a/app/routers/invitation.py b/app/routers/invitation.py new file mode 100644 index 00000000..da2ba209 --- /dev/null +++ b/app/routers/invitation.py @@ -0,0 +1,110 @@ +from typing import Any, List, Optional + +from fastapi import APIRouter, Depends, Request, status +from fastapi.responses import RedirectResponse, Response +from sqlalchemy.exc import SQLAlchemyError +from sqlalchemy.orm import Session + +from app.database.models import Invitation +from app.dependencies import get_db, templates +from app.routers.share import accept + +router = APIRouter( + prefix="/invitations", + tags=["invitation"], + dependencies=[Depends(get_db)], +) + + +@router.get("/", include_in_schema=False) +def view_invitations( + request: Request, db: Session = Depends(get_db) +) -> Response: + """Returns the Invitations page route. + + Args: + request: The HTTP request. + db: Optional; The database connection. + + Returns: + The Invitations HTML page. + """ + return templates.TemplateResponse("invitations.html", { + "request": request, + # TODO: Connect to current user. + # recipient_id should be the current user + # but because we don't have one yet, + # "get_all_invitations" returns all invitations + "invitations": get_all_invitations(db), + }) + + +@router.post("/", include_in_schema=False) +async def accept_invitations( + request: Request, db: Session = Depends(get_db) +) -> RedirectResponse: + """Creates a new connection between the User and the Event in the database. + + See Also: + share.accept for more information. + + Args: + request: The HTTP request. + db: Optional; The database connection. + + Returns: + An updated Invitations HTML page. + """ + data = await request.form() + invite_id = list(data.values())[0] + + invitation = get_invitation_by_id(invite_id, db) + if invitation: + accept(invitation, db) + + url = router.url_path_for("view_invitations") + return RedirectResponse(url=url, status_code=status.HTTP_302_FOUND) + + +# TODO: should be a get request with the path of: +# @router.get("/all") +@router.get("/get_all_invitations") +def get_all_invitations( + db: Session = Depends(get_db), **param: Any +) -> List[Invitation]: + """Returns all Invitations filtered by the requested parameters. + + Args: + db: Optional; The database connection. + **param: A list of parameters to filter by. + + Returns: + A list of all Invitations. + """ + try: + invitations = list(db.query(Invitation).filter_by(**param)) + except SQLAlchemyError: + return [] + else: + return invitations + + +# TODO: should be a get request with the path of: +# @router.get("/{id}") +@router.post("/get_invitation_by_id") +def get_invitation_by_id( + invitation_id: int, db: Session = Depends(get_db) +) -> Optional[Invitation]: + """Returns an Invitation by an ID. + + Args: + invitation_id: The Invitation ID. + db: Optional; The database connection. + + Returns: + An Invitation object if found, otherwise returns None. + """ + return (db.query(Invitation) + .filter_by(id=invitation_id) + .first() + ) diff --git a/app/routers/login.py b/app/routers/login.py index 59645520..99fd5b5c 100644 --- a/app/routers/login.py +++ b/app/routers/login.py @@ -3,11 +3,13 @@ from fastapi import APIRouter, Depends, Request from sqlalchemy.orm import Session from starlette.responses import RedirectResponse +from starlette.status import HTTP_302_FOUND from app.dependencies import get_db, templates -from app.internal.security.ouath2 import authenticate_user, create_jwt_token +from app.internal.security.ouath2 import ( + authenticate_user, create_jwt_token) from app.internal.security import schema -from app.internal.utils import safe_redirect_response + router = APIRouter( prefix="", @@ -18,23 +20,21 @@ @router.get("/login") async def login_user_form( - request: Request, - message: Optional[str] = "", -) -> templates: + request: Request, message: Optional[str] = "") -> templates: """rendering login route get method""" - return templates.TemplateResponse( - "login.html", - {"request": request, "message": message, "current_user": "logged in"}, - ) + return templates.TemplateResponse("login.html", { + "request": request, + "message": message, + 'current_user': "logged in" + }) -@router.post("/login") +@router.post('/login') async def login( - request: Request, - next: Optional[str] = "/", - db: Session = Depends(get_db), - existing_jwt: Union[str, bool] = False, -) -> RedirectResponse: + request: Request, + next: Optional[str] = "/", + db: Session = Depends(get_db), + existing_jwt: Union[str, bool] = False) -> RedirectResponse: """rendering login route post method.""" form = await request.form() form_dict = dict(form) @@ -49,17 +49,19 @@ async def login( if user: user = await authenticate_user(db, user) if not user: - return templates.TemplateResponse( - "login.html", - {"request": request, "message": "Please check your credentials"}, - ) + return templates.TemplateResponse("login.html", { + "request": request, + "message": 'Please check your credentials' + }) # creating HTTPONLY cookie with jwt-token out of user unique data # for testing if not existing_jwt: jwt_token = create_jwt_token(user) else: jwt_token = existing_jwt - response = safe_redirect_response(next) + if not next.startswith("/"): + next = "/" + response = RedirectResponse(next, status_code=HTTP_302_FOUND) response.set_cookie( "Authorization", value=jwt_token, diff --git a/app/routers/notification.py b/app/routers/notification.py deleted file mode 100644 index 74b51102..00000000 --- a/app/routers/notification.py +++ /dev/null @@ -1,192 +0,0 @@ -from fastapi import APIRouter, Depends, Form, Request -from sqlalchemy.orm import Session - -from app.database.models import MessageStatusEnum -from app.dependencies import get_db, templates -from app.internal.notification import ( - get_all_messages, - get_archived_notifications, - get_invitation_by_id, - get_message_by_id, - get_unread_notifications, - is_owner, - raise_wrong_id_error, -) -from app.internal.security.dependencies import current_user, is_logged_in - -from app.internal.security.schema import CurrentUser -from app.internal.utils import safe_redirect_response - -router = APIRouter( - prefix="/notification", - tags=["notification"], - dependencies=[ - Depends(get_db), - Depends(is_logged_in), - ], -) - - -@router.get("/", include_in_schema=False) -async def view_notifications( - request: Request, - user: CurrentUser = Depends(current_user), - db: Session = Depends(get_db), -): - """Returns the Notifications page. - - Args: - request: The HTTP request. - db: Optional; The database connection. - user: user schema object. - - Returns: - The Notifications HTML page. - """ - return templates.TemplateResponse( - "notifications.html", - { - "request": request, - "new_messages": bool(get_all_messages), - "notifications": list( - get_unread_notifications( - session=db, - user_id=user.user_id, - ), - ), - }, - ) - - -@router.get("/archive", include_in_schema=False) -async def view_archive( - request: Request, - user: CurrentUser = Depends(current_user), - db: Session = Depends(get_db), -): - """Returns the Archived Notifications page. - - Args: - request: The HTTP request. - db: Optional; The database connection. - user: user schema object. - - Returns: - The Archived Notifications HTML page. - """ - return templates.TemplateResponse( - "archive.html", - { - "request": request, - "notifications": list( - get_archived_notifications( - session=db, - user_id=user.user_id, - ), - ), - }, - ) - - -@router.post("/invitation/accept") -async def accept_invitations( - invite_id: int = Form(...), - next_url: str = Form(...), - db: Session = Depends(get_db), - user: CurrentUser = Depends(current_user), -): - """Creates a new connection between the User and the Event in the database. - - See Also: - models.Invitation.accept for more information. - - Args: - invite_id: the id of the invitation. - next_url: url to redirect to. - db: Optional; The database connection. - user: user schema object. - - Returns: - A redirect to where the user called the route from. - """ - invitation = get_invitation_by_id(invite_id, session=db) - if invitation and is_owner(user, invitation): - invitation.accept(db) - return safe_redirect_response(next_url) - - raise_wrong_id_error() - - -@router.post("/invitation/decline") -async def decline_invitations( - invite_id: int = Form(...), - next_url: str = Form(...), - db: Session = Depends(get_db), - user: CurrentUser = Depends(current_user), -): - """Declines an invitations. - - Args: - invite_id: the id of the invitation. - db: Optional; The database connection. - next_url: url to redirect to. - user: user schema object. - - Returns: - A redirect to where the user called the route from. - """ - invitation = get_invitation_by_id(invite_id, session=db) - if invitation and is_owner(user, invitation): - invitation.decline(db) - return safe_redirect_response(next_url) - - raise_wrong_id_error() - - -@router.post("/message/read") -async def mark_message_as_read( - message_id: int = Form(...), - next_url: str = Form(...), - db: Session = Depends(get_db), - user: CurrentUser = Depends(current_user), -): - """Marks a message as read. - - Args: - message_id: the id of the message. - db: Optional; The database connection. - next_url: url to redirect to. - user: user schema object. - - Returns: - A redirect to where the user called the route from. - """ - message = await get_message_by_id(message_id, session=db) - if message and is_owner(user, message): - message.mark_as_read(db) - return safe_redirect_response(next_url) - - raise_wrong_id_error() - - -@router.post("/message/read/all") -async def mark_all_as_read( - next_url: str = Form(...), - db: Session = Depends(get_db), - user: CurrentUser = Depends(current_user), -): - """Marks all messages as read. - - Args: - next_url: url to redirect to. - user: user schema object. - db: Optional; The database connection. - - Returns: - A redirect to where the user called the route from. - """ - for message in get_all_messages(db, user.user_id): - if message.status == MessageStatusEnum.UNREAD: - message.mark_as_read(db) - - return safe_redirect_response(next_url) diff --git a/app/routers/register.py b/app/routers/register.py index 2bd8c4bf..57f77165 100644 --- a/app/routers/register.py +++ b/app/routers/register.py @@ -11,7 +11,7 @@ from app.database import schemas from app.database import models from app.dependencies import get_db, templates -from app.internal.utils import save + router = APIRouter( prefix="", @@ -20,13 +20,6 @@ ) -def _create_user(session, **kw) -> models.User: - """Creates and saves a new user.""" - user = models.User(**kw) - save(session, user) - return user - - async def create_user(db: Session, user: schemas.UserCreate) -> models.User: """ creating a new User object in the database, with hashed password @@ -39,10 +32,12 @@ async def create_user(db: Session, user: schemas.UserCreate) -> models.User: "email": user.email, "password": hashed_password, "description": user.description, - "language_id": user.language_id, - "target_weight": user.target_weight, } - return _create_user(**user_details, session=db) + db_user = models.User(**user_details) + db.add(db_user) + db.commit() + db.refresh(db_user) + return db_user async def check_unique_fields( diff --git a/app/routers/share.py b/app/routers/share.py index fe5d449e..a33f44fd 100644 --- a/app/routers/share.py +++ b/app/routers/share.py @@ -2,7 +2,8 @@ from sqlalchemy.orm import Session -from app.database.models import Event, Invitation +from app.database.models import Event, Invitation, UserEvent +from app.internal.utils import save from app.internal.export import get_icalendar from app.routers.user import does_user_exist, get_users @@ -31,11 +32,11 @@ def send_email_invitation( event: Event, ) -> bool: """Sends an email with an invitation.""" - if participants: - ical_invitation = get_icalendar(event, participants) # noqa: F841 - for _ in participants: - # TODO: send email - pass + + ical_invitation = get_icalendar(event, participants) # noqa: F841 + for _ in participants: + # TODO: send email + pass return True @@ -49,6 +50,7 @@ def send_in_app_invitation( for participant in participants: # email is unique recipient = get_users(email=participant, session=session)[0] + if recipient.id != event.owner.id: session.add(Invitation(recipient=recipient, event=event)) @@ -60,6 +62,20 @@ def send_in_app_invitation( return True +def accept(invitation: Invitation, session: Session) -> None: + """Accepts an invitation by creating an + UserEvent association that represents + participantship at the event.""" + + association = UserEvent( + user_id=invitation.recipient.id, + event_id=invitation.event.id + ) + invitation.status = 'accepted' + save(session, invitation) + save(session, association) + + def share(event: Event, participants: List[str], session: Session) -> bool: """Sends invitations to all event participants.""" diff --git a/app/routers/user.py b/app/routers/user.py index 8b8a0403..05206c8f 100644 --- a/app/routers/user.py +++ b/app/routers/user.py @@ -10,7 +10,8 @@ from app.database.models import Event, User, UserEvent from app.dependencies import get_db from app.internal.user.availability import disable, enable -from app.internal.utils import get_current_user +from app.internal.utils import get_current_user, save + router = APIRouter( prefix="/user", @@ -22,7 +23,7 @@ class UserModel(BaseModel): username: str password: str - email: str = Field(regex="^\\S+@\\S+\\.\\S+$") + email: str = Field(regex='^\\S+@\\S+\\.\\S+$') language: str language_id: int @@ -37,8 +38,32 @@ async def get_user(id: int, session=Depends(get_db)): return session.query(User).filter_by(id=id).first() +@router.post("/") +def manually_create_user(user: UserModel, session=Depends(get_db)): + create_user(**user.dict(), session=session) + return f'User {user.username} successfully created' + + +def create_user(username: str, + password: str, + email: str, + language_id: int, + session: Session) -> User: + """Creates and saves a new user.""" + + user = User( + username=username, + password=password, + email=email, + language_id=language_id + ) + save(session, user) + return user + + def get_users(session: Session, **param): """Returns all users filtered by param.""" + try: users = list(session.query(User).filter_by(**param)) except SQLAlchemyError: @@ -48,10 +73,13 @@ def get_users(session: Session, **param): def does_user_exist( - session: Session, *, user_id=None, username=None, email=None + session: Session, + *, user_id=None, + username=None, email=None ): """Returns True if user exists, False otherwise. - function can receive one of the there parameters""" + function can receive one of the there parameters""" + if user_id: return len(get_users(session=session, id=user_id)) == 1 if username: @@ -63,16 +91,16 @@ def does_user_exist( def get_all_user_events(session: Session, user_id: int) -> List[Event]: """Returns all events that the user participants in.""" + return ( - session.query(Event) - .join(UserEvent) - .filter(UserEvent.user_id == user_id) - .all() + session.query(Event).join(UserEvent) + .filter(UserEvent.user_id == user_id).all() ) @router.post("/disable") -def disable_logged_user(request: Request, session: Session = Depends(get_db)): +def disable_logged_user( + request: Request, session: Session = Depends(get_db)): """route that sends request to disable the user. after successful disable it will be directed to main page. if the disable fails user will stay at settings page @@ -85,7 +113,8 @@ def disable_logged_user(request: Request, session: Session = Depends(get_db)): @router.post("/enable") -def enable_logged_user(request: Request, session: Session = Depends(get_db)): +def enable_logged_user( + request: Request, session: Session = Depends(get_db)): """router that sends a request to enable the user. if enable successful it will be directed to main page. if it fails user will stay at settings page diff --git a/app/static/event/eventview.css b/app/static/event/eventview.css index 0b768405..3a420e0e 100644 --- a/app/static/event/eventview.css +++ b/app/static/event/eventview.css @@ -50,6 +50,10 @@ div.event_info_row, margin-block-end: 0.2em; } +.title { + border-bottom: 4px solid blue; +} + .title h1 { white-space: nowrap; margin-block-start: 0.2em; @@ -68,8 +72,4 @@ div.event_info_row, button { height: 100%; -} - -.google_maps_object { - width: 100%; -} +} \ No newline at end of file diff --git a/app/static/notification.css b/app/static/notification.css deleted file mode 100644 index 7dbe0a7d..00000000 --- a/app/static/notification.css +++ /dev/null @@ -1,70 +0,0 @@ -/* general */ -#main { - width: 90%; - margin: 0 25% 0 5%; -} - -#link { - font-size: 1.5rem; -} - - -/* notifications */ -#notifications-box { - margin-top: 1rem; - -} - -.notification { - padding: 0.5rem 1rem; - display: flex; - justify-content: space-between; -} - -.notification:hover { - background-color: var(--surface-variant); - border-radius: 0.2rem; -} - -.action, .description { - display: inline-block; -} - -.action { - width: 4rem; -} - - -/* buttons */ -.notification-btn { - background-color: transparent; - border: none; -} - -.notification-btn:focus { - outline: 0; -} - -.btn-accept { - color: green; -} - -.btn-decline { - color: red; -} - -#mark-all-as-read { - margin: 1rem; -} - - -/* form */ -.notification-form { - display: inline-block; -} - - -/* icons */ -.icon { - font-size: 1.5rem; -} diff --git a/app/templates/archive.html b/app/templates/archive.html deleted file mode 100644 index a74da791..00000000 --- a/app/templates/archive.html +++ /dev/null @@ -1,26 +0,0 @@ -{% extends "./partials/notification/base.html" %} -{% block page_name %}Archive{% endblock page_name %} - -{% block description %} -
-
Archived Notifications
-

- In this page you can view all of your archived notifications.
- Any notification you have marked as read or declined, you will see here.
- You can use the - button to accept an invitation that you already declined. -

-
-{% endblock description %} - -{% block link %} - -{% endblock link %} - -{% block notifications %} - {% include './partials/notification/generate_archive.html' %} -{% endblock notifications %} - -{% block no_notifications_msg %} - You don't have any archived notifications. -{% endblock no_notifications_msg %} diff --git a/app/templates/base.html b/app/templates/base.html index d6039fb4..5d211ad5 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -39,42 +39,40 @@ - - - - - - - - Create Categories - - - - - + + + + + + + + + Create Categories + + + +
@@ -82,7 +80,6 @@ {% block content %}{% endblock %} - @@ -98,4 +95,5 @@ + diff --git a/app/templates/calendar/layout.html b/app/templates/calendar/layout.html deleted file mode 100644 index 5f98e980..00000000 --- a/app/templates/calendar/layout.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - Calendar - - - -
- -
-
FEATURE NAME
-
-
-
-
-
{{day.display()}}
-
Location 0oc 00:00
-
- -
-
- {% block main %} {% endblock %} -
-
-
- - - - - - - - diff --git a/app/templates/invitations.html b/app/templates/invitations.html new file mode 100644 index 00000000..83d29418 --- /dev/null +++ b/app/templates/invitations.html @@ -0,0 +1,24 @@ +{% extends "partials/index/index_base.html" %} + + +{% block content %} + +
+

{{ message }}

+
+ + {% if invitations %} +
+ {% for i in invitations %} +
+ {{ i.event.owner.username }} - {{ i.event.title }} ({{ i.event.start }}) ({{ i.status }}) + + +
+ {% endfor %} +
+ {% else %} + You don't have any invitations. + {% endif %} + +{% endblock %} \ No newline at end of file diff --git a/app/templates/notifications.html b/app/templates/notifications.html deleted file mode 100644 index 7b33a17f..00000000 --- a/app/templates/notifications.html +++ /dev/null @@ -1,38 +0,0 @@ -{% extends "./partials/notification/base.html" %} -{% block page_name %}Notifications{% endblock page_name %} - -{% block description %} -
-
New Notifications
-

- In this page you can view all of your new notifications.
- use the - button to mark as read - and the - and - to accept and decline. -

-
-{% endblock description %} - -{% block link %} - -{% endblock link %} - -{% block optional %} -
- - -
-{% endblock optional %} - -{% block notifications %} - {% include './partials/notification/generate_notifications.html' %} -{% endblock notifications %} - -{% block no_notifications_msg %} - You don't have any new notifications. -{% endblock no_notifications_msg %} diff --git a/app/templates/partials/calendar/event/view_event_details_tab.html b/app/templates/partials/calendar/event/view_event_details_tab.html index 36b96d04..d2c235ed 100644 --- a/app/templates/partials/calendar/event/view_event_details_tab.html +++ b/app/templates/partials/calendar/event/view_event_details_tab.html @@ -1,11 +1,11 @@
-
-

{{ event.title }}

-
-
- - -
+
+

{{ event.title }}

+
+
+ + +
ICON @@ -35,39 +35,24 @@

{{ event.title }}

VC linkVC URL
{% endif %} - -{% if event.latitude is not none and event.longitude is not none %} -
- -
-{% endif %} - {% if event.invitees %}
-
- - - +
+ + +
{% endif %}

- {{event.owner.username}} + {{event.owner.username}}

- - - + + +
diff --git a/app/templates/partials/calendar/navigation.html b/app/templates/partials/calendar/navigation.html index ed73747d..ab65b8eb 100644 --- a/app/templates/partials/calendar/navigation.html +++ b/app/templates/partials/calendar/navigation.html @@ -7,11 +7,6 @@ -
- - - -
diff --git a/app/templates/partials/index/navigation.html b/app/templates/partials/index/navigation.html index 60baf35d..b1fa3b3f 100644 --- a/app/templates/partials/index/navigation.html +++ b/app/templates/partials/index/navigation.html @@ -20,14 +20,17 @@ + - diff --git a/app/templates/partials/notification/base.html b/app/templates/partials/notification/base.html deleted file mode 100644 index 0df8fcde..00000000 --- a/app/templates/partials/notification/base.html +++ /dev/null @@ -1,56 +0,0 @@ -{% extends "partials/base.html" %} -{% block head %} - {{super()}} - - - - - -{% endblock head %} -{% block body %} -
- {% include 'partials/calendar/navigation.html' %} -
- {% include 'partials/calendar/feature_settings/example.html' %} -
-
- {% block content %} -
- {% block description %} - {% endblock description %} - -
-
-
- {% block link %} - {% endblock link %} -
- {% if notifications %} -
- - {% block optional %} - {% endblock optional %} - -
- {% block notifications %} - {% endblock notifications %} -
- - {% else %} - {% block no_notifications_msg %} - {% endblock no_notifications_msg %} -
- {% endif %} -
- {% endblock content %} -
-
- - - - -{% endblock body %} diff --git a/app/templates/partials/notification/generate_archive.html b/app/templates/partials/notification/generate_archive.html deleted file mode 100644 index 2d0e0ed3..00000000 --- a/app/templates/partials/notification/generate_archive.html +++ /dev/null @@ -1,29 +0,0 @@ -{% for n in notifications %} - {% set type = n.__table__.name %} - -
- {% if type == "invitations" %} -
- Invitation from {{ n.event.owner.username }} - - {{ n.event.title }} - (declined) -
-
-
- - -
-
- - {% elif type == "messages" %} -
- {% if n.link %}{{ n.body }} - {% else %}{{ n.body }}{% endif %} -
- {% endif %} - -
-{% endfor %} diff --git a/app/templates/partials/notification/generate_notifications.html b/app/templates/partials/notification/generate_notifications.html deleted file mode 100644 index b779db22..00000000 --- a/app/templates/partials/notification/generate_notifications.html +++ /dev/null @@ -1,48 +0,0 @@ -{% for n in notifications %} - {% set type = n.__table__.name %} - -
- {% if type == "invitations" %} -
- Invitation from {{ n.event.owner.username }} - - {{ n.event.title }} - ({{ n.event.start.strftime('%H:%M %m/%d/%Y') }}) -
-
-
- - -
-
- - -
-
- - {% elif type == "messages" %} -
- {% if n.link %}{{ n.body }} - {% else %}{{ n.body }}{% endif %} -
-
-
- - -
-
- {% endif %} - -
-{% endfor %} diff --git a/requirements.txt b/requirements.txt index 5d07acea..5bbdca17 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ aiofiles==0.6.0 -aiohttp==3.7.3 aioredis==1.3.1 aiosmtpd==1.2.2 aiosmtplib==1.1.4 @@ -25,7 +24,7 @@ cachetools==4.2.0 certifi==2020.12.5 cffi==1.14.4 cfgv==3.2.0 -chardet==3.0.4 +chardet==4.0.0 click==7.1.2 colorama==0.4.4 coverage==5.3.1 @@ -45,8 +44,6 @@ fastapi-mail==0.3.3.1 filelock==3.0.12 flake8==3.8.4 frozendict==1.2 -geographiclib==1.50 -geopy==2.1.0 google-api-core==1.25.0 google-api-python-client==1.12.8 google-auth==1.24.0 @@ -80,7 +77,6 @@ mocker==1.1.1 multidict==5.1.0 mypy==0.790 mypy-extensions==0.4.3 -nest-asyncio==1.5.1 nltk==3.5 nodeenv==1.5.0 oauth2client==4.1.3 @@ -88,7 +84,6 @@ oauthlib==3.1.0 outcome==1.1.0 packaging==20.8 passlib==1.7.4 -pathspec==0.8.1 Pillow==8.1.0 pluggy==0.13.1 pre-commit==2.10.0 @@ -153,5 +148,4 @@ win32-setctime==1.0.3 word-forms==2.1.0 wsproto==1.0.0 yapf==0.30.0 -yarl==1.6.3 -zipp==3.4.0 +zipp==3.4.0 \ No newline at end of file diff --git a/tests/fixtures/association_fixture.py b/tests/association_fixture.py similarity index 100% rename from tests/fixtures/association_fixture.py rename to tests/association_fixture.py diff --git a/tests/fixtures/asyncio_fixture.py b/tests/asyncio_fixture.py similarity index 83% rename from tests/fixtures/asyncio_fixture.py rename to tests/asyncio_fixture.py index 7f567b3b..db6645c5 100644 --- a/tests/fixtures/asyncio_fixture.py +++ b/tests/asyncio_fixture.py @@ -7,7 +7,7 @@ from app.main import app from app.routers import telegram from app.routers.event import create_event -from tests.fixtures.client_fixture import get_test_placeholder_user +from tests.client_fixture import get_test_placeholder_user from tests.conftest import get_test_db, test_engine @@ -32,24 +32,22 @@ def fake_user_events(session): session.commit() create_event( db=session, - title="Cool today event", - color="red", + title='Cool today event', start=today_date, end=today_date + timedelta(days=2), all_day=False, - content="test event", + content='test event', owner_id=user.id, location="Here", is_google_event=False, ) create_event( db=session, - title="Cool (somewhen in two days) event", - color="blue", + title='Cool (somewhen in two days) event', start=today_date + timedelta(days=1), end=today_date + timedelta(days=3), all_day=False, - content="this week test event", + content='this week test event', owner_id=user.id, location="Here", is_google_event=False, diff --git a/tests/fixtures/category_fixture.py b/tests/category_fixture.py similarity index 100% rename from tests/fixtures/category_fixture.py rename to tests/category_fixture.py diff --git a/tests/fixtures/client_fixture.py b/tests/client_fixture.py similarity index 93% rename from tests/fixtures/client_fixture.py rename to tests/client_fixture.py index d905c19f..7627e34a 100644 --- a/tests/fixtures/client_fixture.py +++ b/tests/client_fixture.py @@ -1,12 +1,11 @@ -from typing import Generator, Iterator, Dict +from typing import Generator, Iterator -import pytest from fastapi.testclient import TestClient +import pytest from sqlalchemy.orm import Session from app import main from app.database.models import Base, User - from app.routers import ( agenda, audio, @@ -14,8 +13,8 @@ event, friendview, google_connect, + invitation, meds, - notification, profile, weekview, weekly_tasks, @@ -25,8 +24,6 @@ from tests import security_testing_routes from tests.conftest import get_test_db, test_engine -LOGIN_DATA_TYPE = Dict[str, str] - main.app.include_router(security_testing_routes.router) REGISTER_DETAIL = { @@ -41,10 +38,6 @@ LOGIN_DATA = {"username": "correct_user", "password": "correct_password"} -def login_client(client: TestClient, data: LOGIN_DATA_TYPE) -> None: - client.post(client.app.url_path_for("login"), data=data) - - def get_test_placeholder_user() -> User: return User( username="fake_user", @@ -97,11 +90,6 @@ def agenda_test_client() -> Generator[TestClient, None, None]: yield from create_test_client(agenda.get_db) -@pytest.fixture(scope="session") -def notification_test_client(): - yield from create_test_client(notification.get_db) - - @pytest.fixture(scope="session") def friendview_test_client() -> Generator[TestClient, None, None]: yield from create_test_client(friendview.get_db) @@ -122,6 +110,11 @@ def home_test_client() -> Generator[TestClient, None, None]: yield from create_test_client(main.get_db) +@pytest.fixture(scope="session") +def invitation_test_client() -> Generator[TestClient, None, None]: + yield from create_test_client(invitation.get_db) + + @pytest.fixture(scope="session") def categories_test_client() -> Generator[TestClient, None, None]: yield from create_test_client(categories.get_db) diff --git a/tests/fixtures/comment_fixture.py b/tests/comment_fixture.py similarity index 100% rename from tests/fixtures/comment_fixture.py rename to tests/comment_fixture.py diff --git a/tests/conftest.py b/tests/conftest.py index 42cee5dc..500ede4a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,33 +1,28 @@ import calendar -import nest_asyncio import pytest -from app.config import PSQL_ENVIRONMENT -from app.database.models import Base from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker +from app.config import PSQL_ENVIRONMENT +from app.database.models import Base pytest_plugins = [ - "tests.fixtures.user_fixture", - "tests.fixtures.event_fixture", - "tests.fixtures.invitation_fixture", - "tests.fixtures.message_fixture", - "tests.fixtures.association_fixture", - "tests.fixtures.client_fixture", - "tests.fixtures.weekly_tasks_fixture", - "tests.fixtures.asyncio_fixture", - "tests.fixtures.logger_fixture", - "tests.fixtures.category_fixture", - "tests.fixtures.quotes_fixture", - "tests.fixtures.zodiac_fixture", - "tests.fixtures.dayview_fixture", - "tests.fixtures.comment_fixture", - "tests.fixtures.quotes_fixture", - "tests.fixtures.zodiac_fixture", - "tests.fixtures.jokes_fixture", - "tests.fixtures.comment_fixture", - "smtpdfix", + 'tests.user_fixture', + 'tests.event_fixture', + 'tests.dayview_fixture', + 'tests.invitation_fixture', + 'tests.association_fixture', + 'tests.client_fixture', + 'tests.weekly_tasks_fixture', + 'tests.asyncio_fixture', + 'tests.logger_fixture', + 'tests.category_fixture', + 'smtpdfix', + 'tests.quotes_fixture', + 'tests.zodiac_fixture', + 'tests.jokes_fixture', + 'tests.comment_fixture', ] # When testing in a PostgreSQL environment please make sure that: @@ -36,22 +31,21 @@ if PSQL_ENVIRONMENT: SQLALCHEMY_TEST_DATABASE_URL = ( - "postgresql://postgres:1234" "@localhost/postgres" + "postgresql://postgres:1234" + "@localhost/postgres" + ) + test_engine = create_engine( + SQLALCHEMY_TEST_DATABASE_URL ) - test_engine = create_engine(SQLALCHEMY_TEST_DATABASE_URL) else: SQLALCHEMY_TEST_DATABASE_URL = "sqlite:///./test.db" test_engine = create_engine( - SQLALCHEMY_TEST_DATABASE_URL, - connect_args={"check_same_thread": False}, + SQLALCHEMY_TEST_DATABASE_URL, connect_args={"check_same_thread": False} ) TestingSessionLocal = sessionmaker( - autocommit=False, - autoflush=False, - bind=test_engine, -) + autocommit=False, autoflush=False, bind=test_engine) def get_test_db(): @@ -72,15 +66,11 @@ def session(): def sqlite_engine(): SQLALCHEMY_TEST_DATABASE_URL = "sqlite:///./test.db" sqlite_test_engine = create_engine( - SQLALCHEMY_TEST_DATABASE_URL, - connect_args={"check_same_thread": False}, + SQLALCHEMY_TEST_DATABASE_URL, connect_args={"check_same_thread": False} ) TestingSession = sessionmaker( - autocommit=False, - autoflush=False, - bind=sqlite_test_engine, - ) + autocommit=False, autoflush=False, bind=sqlite_test_engine) yield sqlite_test_engine session = TestingSession() @@ -91,6 +81,3 @@ def sqlite_engine(): @pytest.fixture def Calendar(): return calendar.Calendar(0) - - -nest_asyncio.apply() diff --git a/tests/fixtures/dayview_fixture.py b/tests/dayview_fixture.py similarity index 100% rename from tests/fixtures/dayview_fixture.py rename to tests/dayview_fixture.py diff --git a/tests/fixtures/event_fixture.py b/tests/event_fixture.py similarity index 82% rename from tests/fixtures/event_fixture.py rename to tests/event_fixture.py index 17213e6f..989c41fb 100644 --- a/tests/fixtures/event_fixture.py +++ b/tests/event_fixture.py @@ -13,10 +13,10 @@ def event(sender: User, category: Category, session: Session) -> Event: return create_event( db=session, - title="event", + title='event', start=today_date, end=today_date, - content="test event", + content='test event', owner_id=sender.id, location="Some random location", vc_link=None, @@ -28,11 +28,11 @@ def event(sender: User, category: Category, session: Session) -> Event: def today_event(sender: User, session: Session) -> Event: return create_event( db=session, - title="event 1", + title='event 1', start=today_date + timedelta(hours=7), end=today_date + timedelta(hours=9), all_day=False, - content="test event", + content='test event', owner_id=sender.id, ) @@ -41,12 +41,11 @@ def today_event(sender: User, session: Session) -> Event: def today_event_2(sender: User, session: Session) -> Event: return create_event( db=session, - title="event 2", - color="blue", + title='event 2', start=today_date + timedelta(hours=3), end=today_date + timedelta(days=2, hours=3), all_day=False, - content="test event", + content='test event', owner_id=sender.id, ) @@ -55,12 +54,11 @@ def today_event_2(sender: User, session: Session) -> Event: def yesterday_event(sender: User, session: Session) -> Event: return create_event( db=session, - title="event 3", - color="green", + title='event 3', start=today_date - timedelta(hours=8), end=today_date, all_day=False, - content="test event", + content='test event', owner_id=sender.id, ) @@ -69,12 +67,11 @@ def yesterday_event(sender: User, session: Session) -> Event: def next_week_event(sender: User, session: Session) -> Event: return create_event( db=session, - title="event 4", - color="blue", + title='event 4', start=today_date + timedelta(days=7, hours=2), end=today_date + timedelta(days=7, hours=4), all_day=False, - content="test event", + content='test event', owner_id=sender.id, ) @@ -83,12 +80,11 @@ def next_week_event(sender: User, session: Session) -> Event: def next_month_event(sender: User, session: Session) -> Event: return create_event( db=session, - title="event 5", - color="green", + title='event 5', start=today_date + timedelta(days=20, hours=4), end=today_date + timedelta(days=20, hours=6), all_day=False, - content="test event", + content='test event', owner_id=sender.id, ) @@ -97,12 +93,11 @@ def next_month_event(sender: User, session: Session) -> Event: def old_event(sender: User, session: Session) -> Event: return create_event( db=session, - title="event 6", - color="red", + title='event 6', start=today_date - timedelta(days=5), end=today_date - timedelta(days=1), all_day=False, - content="test event", + content='test event', owner_id=sender.id, ) @@ -111,11 +106,11 @@ def old_event(sender: User, session: Session) -> Event: def all_day_event(sender: User, category: Category, session: Session) -> Event: return create_event( db=session, - title="event", + title='event', start=today_date, end=today_date, all_day=True, - content="test event", + content='test event', owner_id=sender.id, location="Some random location", category_id=category.id, diff --git a/tests/fixtures/__init__.py b/tests/fixtures/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/fixtures/message_fixture.py b/tests/fixtures/message_fixture.py deleted file mode 100644 index 839051ba..00000000 --- a/tests/fixtures/message_fixture.py +++ /dev/null @@ -1,29 +0,0 @@ -import pytest -from sqlalchemy.orm import Session - -from app.database.models import Message, User -from app.internal.utils import create_model, delete_instance - - -@pytest.fixture -def message(user: User, session: Session) -> Message: - invitation = create_model( - session, Message, - body='A test message', - link='#', - recipient_id=user.id, - ) - yield invitation - delete_instance(session, invitation) - - -@pytest.fixture -def sec_message(user: User, session: Session) -> Message: - invitation = create_model( - session, Message, - body='A test message', - link='#', - recipient_id=user.id, - ) - yield invitation - delete_instance(session, invitation) diff --git a/tests/fixtures/invitation_fixture.py b/tests/invitation_fixture.py similarity index 100% rename from tests/fixtures/invitation_fixture.py rename to tests/invitation_fixture.py diff --git a/tests/fixtures/jokes_fixture.py b/tests/jokes_fixture.py similarity index 89% rename from tests/fixtures/jokes_fixture.py rename to tests/jokes_fixture.py index 062d5d45..d7e3258c 100644 --- a/tests/fixtures/jokes_fixture.py +++ b/tests/jokes_fixture.py @@ -16,5 +16,5 @@ def joke(session: Session) -> Joke: yield from add_joke( session=session, id_joke=1, - text="Chuck Norris can slam a revolving door.", + text='Chuck Norris can slam a revolving door.', ) diff --git a/tests/fixtures/logger_fixture.py b/tests/logger_fixture.py similarity index 100% rename from tests/fixtures/logger_fixture.py rename to tests/logger_fixture.py diff --git a/tests/fixtures/quotes_fixture.py b/tests/quotes_fixture.py similarity index 100% rename from tests/fixtures/quotes_fixture.py rename to tests/quotes_fixture.py diff --git a/tests/salary/test_routes.py b/tests/salary/test_routes.py index 830569ff..13e22e05 100644 --- a/tests/salary/test_routes.py +++ b/tests/salary/test_routes.py @@ -199,6 +199,7 @@ def test_invalid_category_redirect( response = salary_test_client.get(path) assert any(temp.status_code == status.HTTP_307_TEMPORARY_REDIRECT for temp in response.history) + print(response.text) assert message in response.text diff --git a/tests/test_a_telegram_asyncio.py b/tests/test_a_telegram_asyncio.py index ff1a7ddf..faf99d98 100644 --- a/tests/test_a_telegram_asyncio.py +++ b/tests/test_a_telegram_asyncio.py @@ -6,145 +6,141 @@ from app.telegram.handlers import MessageHandler, reply_unknown_user from app.telegram.keyboards import DATE_FORMAT from app.telegram.models import Bot, Chat -from tests.fixtures.asyncio_fixture import today_date -from tests.fixtures.client_fixture import get_test_placeholder_user +from tests.asyncio_fixture import today_date +from tests.client_fixture import get_test_placeholder_user def gen_message(text): return { - "update_id": 10000000, - "message": { - "message_id": 2434, - "from": { - "id": 666666, - "is_bot": False, - "first_name": "Moshe", - "username": "banana", - "language_code": "en", + 'update_id': 10000000, + 'message': { + 'message_id': 2434, + 'from': { + 'id': 666666, + 'is_bot': False, + 'first_name': 'Moshe', + 'username': 'banana', + 'language_code': 'en' }, - "chat": { - "id": 666666, - "first_name": "Moshe", - "username": "banana", - "type": "private", + 'chat': { + 'id': 666666, + 'first_name': 'Moshe', + 'username': 'banana', + 'type': 'private' }, - "date": 1611240725, - "text": f"{text}", - }, + 'date': 1611240725, + 'text': f'{text}' + } } def gen_callback(text): return { - "update_id": 568265, - "callback_query": { - "id": "546565356486", - "from": { - "id": 666666, - "is_bot": False, - "first_name": "Moshe", - "username": "banana", - "language_code": "en", - }, - "message": { - "message_id": 838, - "from": { - "id": 2566252, - "is_bot": True, - "first_name": "PyLandar", - "username": "pylander_bot", - }, - "chat": { - "id": 666666, - "first_name": "Moshe", - "username": "banana", - "type": "private", + 'update_id': 568265, + 'callback_query': { + 'id': '546565356486', + 'from': { + 'id': 666666, + 'is_bot': False, + 'first_name': 'Moshe', + 'username': 'banana', + 'language_code': 'en' + }, 'message': { + 'message_id': 838, + 'from': { + 'id': 2566252, + 'is_bot': True, + 'first_name': 'PyLandar', + 'username': 'pylander_bot' + }, 'chat': { + 'id': 666666, + 'first_name': 'Moshe', + 'username': 'banana', + 'type': 'private' }, - "date": 161156, - "text": "Choose events day.", - "reply_markup": { - "inline_keyboard": [ + 'date': 161156, + 'text': 'Choose events day.', + 'reply_markup': { + 'inline_keyboard': [ [ - {"text": "Today", "callback_data": "Today"}, { - "text": "This week", - "callback_data": "This week", + 'text': 'Today', + 'callback_data': 'Today' }, - ], - ], - }, + { + 'text': 'This week', + 'callback_data': 'This week' + } + ] + ] + } }, - "chat_instance": "-154494", - "data": f"{text}", - }, - } + 'chat_instance': '-154494', + 'data': f'{text}'}} class TestChatModel: + @staticmethod def test_private_message(): - chat = Chat(gen_message("Cool message")) - assert chat.message == "Cool message" + chat = Chat(gen_message('Cool message')) + assert chat.message == 'Cool message' assert chat.user_id == 666666 - assert chat.first_name == "Moshe" + assert chat.first_name == 'Moshe' @staticmethod def test_callback_message(): - chat = Chat(gen_callback("Callback Message")) - assert chat.message == "Callback Message" + chat = Chat(gen_callback('Callback Message')) + assert chat.message == 'Callback Message' assert chat.user_id == 666666 - assert chat.first_name == "Moshe" + assert chat.first_name == 'Moshe' @pytest.mark.asyncio async def test_bot_model(): bot = Bot("fake bot id", "https://google.com") - assert bot.base == "https://api.telegram.org/botfake bot id/" - assert ( - bot.webhook_setter_url - == "https://api.telegram.org/botfake \ -bot id/setWebhook?url=https://google.com/telegram/" - ) + assert bot.base == 'https://api.telegram.org/botfake bot id/' + assert bot.webhook_setter_url == 'https://api.telegram.org/botfake \ +bot id/setWebhook?url=https://google.com/telegram/' assert bot.base == bot._set_base_url("fake bot id") assert bot.webhook_setter_url == bot._set_webhook_setter_url( - "https://google.com", - ) + "https://google.com") set_request = await bot.set_webhook() assert set_request.json() == { - "ok": False, - "error_code": 404, - "description": "Not Found", + 'ok': False, + 'error_code': 404, + 'description': 'Not Found' } drop_request = await bot.drop_webhook() assert drop_request.json() == { - "ok": False, - "error_code": 404, - "description": "Not Found", + 'ok': False, + 'error_code': 404, + 'description': 'Not Found' } send_request = await bot.send_message("654654645", "hello") assert send_request.status_code == status.HTTP_404_NOT_FOUND assert send_request.json() == { - "ok": False, - "error_code": 404, - "description": "Not Found", + 'ok': False, + 'error_code': 404, + 'description': 'Not Found' } class TestBotClient: + @staticmethod @pytest.mark.asyncio async def test_user_not_registered(telegram_client): response = await telegram_client.post( - "/telegram/", - json=gen_message("/start"), - ) + '/telegram/', json=gen_message('/start')) assert response.status_code == status.HTTP_200_OK - assert b"Hello, Moshe!" in response.content - assert b"To use PyLendar Bot you have to register" in response.content + assert b'Hello, Moshe!' in response.content + assert b'To use PyLendar Bot you have to register' \ + in response.content @staticmethod @pytest.mark.asyncio @@ -152,11 +148,9 @@ async def test_user_registered(telegram_client, session): session.add(get_test_placeholder_user()) session.commit() response = await telegram_client.post( - "/telegram/", - json=gen_message("/start"), - ) + '/telegram/', json=gen_message('/start')) assert response.status_code == status.HTTP_200_OK - assert b"Welcome to PyLendar telegram client!" in response.content + assert b'Welcome to PyLendar telegram client!' in response.content class TestHandlers: @@ -164,27 +158,21 @@ class TestHandlers: @pytest.mark.asyncio async def test_start_handlers(self): - chat = Chat(gen_message("/start")) + chat = Chat(gen_message('/start')) message = MessageHandler(chat, self.TEST_USER) - assert "/start" in message.handlers - assert ( - await message.process_callback() - == """Hello, Moshe! -Welcome to PyLendar telegram client!""" - ) + assert '/start' in message.handlers + assert await message.process_callback() == '''Hello, Moshe! +Welcome to PyLendar telegram client!''' @pytest.mark.asyncio async def test_default_handlers(self): wrong_start = MessageHandler( - Chat(gen_message("start")), - self.TEST_USER, - ) + Chat(gen_message('start')), self.TEST_USER) wrong_show_events = MessageHandler( - Chat(gen_message("show_events")), - self.TEST_USER, - ) - message = MessageHandler(Chat(gen_message("hello")), self.TEST_USER) + Chat(gen_message('show_events')), self.TEST_USER) + message = MessageHandler( + Chat(gen_message('hello')), self.TEST_USER) assert await wrong_start.process_callback() == "Unknown command." assert await wrong_show_events.process_callback() == "Unknown command." @@ -192,34 +180,34 @@ async def test_default_handlers(self): @pytest.mark.asyncio async def test_show_events_handler(self): - chat = Chat(gen_message("/show_events")) + chat = Chat(gen_message('/show_events')) message = MessageHandler(chat, self.TEST_USER) - assert await message.process_callback() == "Choose events day." + assert await message.process_callback() == 'Choose events day.' @pytest.mark.asyncio async def test_no_today_events_handler(self): - chat = Chat(gen_callback("Today")) + chat = Chat(gen_callback('Today')) message = MessageHandler(chat, self.TEST_USER) assert await message.process_callback() == "There're no events today." @pytest.mark.asyncio async def test_today_handler(self, fake_user_events): - chat = Chat(gen_callback("Today")) + chat = Chat(gen_callback('Today')) message = MessageHandler(chat, fake_user_events) answer = f"{today_date.strftime('%A, %B %d')}:\n" assert await message.process_callback() == answer @pytest.mark.asyncio async def test_this_week_handler(self): - chat = Chat(gen_callback("This week")) + chat = Chat(gen_callback('This week')) message = MessageHandler(chat, self.TEST_USER) - assert await message.process_callback() == "Choose a day." + assert await message.process_callback() == 'Choose a day.' @pytest.mark.asyncio async def test_no_chosen_day_handler(self): - chat = Chat(gen_callback("10 Feb 2021")) + chat = Chat(gen_callback('10 Feb 2021')) message = MessageHandler(chat, self.TEST_USER) - message.handlers["10 Feb 2021"] = message.chosen_day_handler + message.handlers['10 Feb 2021'] = message.chosen_day_handler answer = "There're no events on February 10." assert await message.process_callback() == answer @@ -235,101 +223,99 @@ async def test_chosen_day_handler(self, fake_user_events): @pytest.mark.asyncio async def test_new_event_handler(self): - chat = Chat(gen_message("/new_event")) + chat = Chat(gen_message('/new_event')) message = MessageHandler(chat, self.TEST_USER) - answer = "Please, give your event a title." + answer = 'Please, give your event a title.' assert await message.process_callback() == answer @pytest.mark.asyncio async def test_process_new_event(self): - chat = Chat(gen_message("New Title")) + chat = Chat(gen_message('New Title')) message = MessageHandler(chat, self.TEST_USER) - answer = "Title:\nNew Title\n\n" - answer += "Add a description of the event." + answer = 'Title:\nNew Title\n\n' + answer += 'Add a description of the event.' assert await message.process_callback() == answer - chat = Chat(gen_message("New Content")) + chat = Chat(gen_message('New Content')) message = MessageHandler(chat, self.TEST_USER) - answer = "Content:\nNew Content\n\n" - answer += "Where the event will be held?" + answer = 'Content:\nNew Content\n\n' + answer += 'Where the event will be held?' assert await message.process_callback() == answer - chat = Chat(gen_message("Universe")) + chat = Chat(gen_message('Universe')) message = MessageHandler(chat, self.TEST_USER) - answer = "Location:\nUniverse\n\n" - answer += "When does it start?" + answer = 'Location:\nUniverse\n\n' + answer += 'When does it start?' assert await message.process_callback() == answer - chat = Chat(gen_message("Not valid start datetime input")) + chat = Chat(gen_message('Not valid start datetime input')) message = MessageHandler(chat, self.TEST_USER) - answer = "❗️ Please, enter a valid date/time." + answer = '❗️ Please, enter a valid date/time.' assert await message.process_callback() == answer - chat = Chat(gen_message("today")) + chat = Chat(gen_message('today')) message = MessageHandler(chat, self.TEST_USER) today = datetime.today() answer = f'Starts on:\n{today.strftime("%d %b %Y %H:%M")}\n\n' - answer += "And when does it end?" + answer += 'And when does it end?' assert await message.process_callback() == answer - chat = Chat(gen_message("Not valid end datetime input")) + chat = Chat(gen_message('Not valid end datetime input')) message = MessageHandler(chat, self.TEST_USER) - answer = "❗️ Please, enter a valid date/time." + answer = '❗️ Please, enter a valid date/time.' assert await message.process_callback() == answer - chat = Chat(gen_message("tomorrow")) + chat = Chat(gen_message('tomorrow')) message = MessageHandler(chat, self.TEST_USER) tomorrow = today + timedelta(days=1) - answer = "Title:\nNew Title\n\n" - answer += "Content:\nNew Content\n\n" - answer += "Location:\nUniverse\n\n" + answer = 'Title:\nNew Title\n\n' + answer += 'Content:\nNew Content\n\n' + answer += 'Location:\nUniverse\n\n' answer += f'Starts on:\n{today.strftime("%d %b %Y %H:%M")}\n\n' answer += f'Ends on:\n{tomorrow.strftime("%d %b %Y %H:%M")}' assert await message.process_callback() == answer - chat = Chat(gen_message("create")) + chat = Chat(gen_message('create')) message = MessageHandler(chat, self.TEST_USER) - answer = "New event was successfully created 🎉" + answer = 'New event was successfully created 🎉' assert await message.process_callback() == answer @pytest.mark.asyncio async def test_process_new_event_cancel(self): - chat = Chat(gen_message("/new_event")) + chat = Chat(gen_message('/new_event')) message = MessageHandler(chat, self.TEST_USER) - answer = "Please, give your event a title." + answer = 'Please, give your event a title.' assert await message.process_callback() == answer - chat = Chat(gen_message("cancel")) + chat = Chat(gen_message('cancel')) message = MessageHandler(chat, self.TEST_USER) - answer = "🚫 The process was canceled." + answer = '🚫 The process was canceled.' assert await message.process_callback() == answer @pytest.mark.asyncio async def test_process_new_event_restart(self): - chat = Chat(gen_message("/new_event")) + chat = Chat(gen_message('/new_event')) message = MessageHandler(chat, self.TEST_USER) - answer = "Please, give your event a title." + answer = 'Please, give your event a title.' assert await message.process_callback() == answer - chat = Chat(gen_message("New Title")) + chat = Chat(gen_message('New Title')) message = MessageHandler(chat, self.TEST_USER) - answer = "Title:\nNew Title\n\n" - answer += "Add a description of the event." + answer = 'Title:\nNew Title\n\n' + answer += 'Add a description of the event.' assert await message.process_callback() == answer - chat = Chat(gen_message("restart")) + chat = Chat(gen_message('restart')) message = MessageHandler(chat, self.TEST_USER) - answer = "Please, give your event a title." + answer = 'Please, give your event a title.' assert await message.process_callback() == answer @pytest.mark.asyncio async def test_reply_unknown_user(): - chat = Chat(gen_message("/show_events")) + chat = Chat(gen_message('/show_events')) answer = await reply_unknown_user(chat) - assert ( - answer - == """ + assert answer == ''' Hello, Moshe! To use PyLendar Bot you have to register @@ -339,5 +325,4 @@ async def test_reply_unknown_user(): Keep it secret! https://calendar.pythonic.guru/profile/ -""" - ) +''' diff --git a/tests/test_calendar_privacy.py b/tests/test_calendar_privacy.py index 0fde3d0a..d94dfd56 100644 --- a/tests/test_calendar_privacy.py +++ b/tests/test_calendar_privacy.py @@ -1,8 +1,7 @@ from app.internal.calendar_privacy import can_show_calendar - # TODO after user system is merged: -# from app.internal.security.dependancies import CurrentUser -from app.routers.register import _create_user +# from app.internal.security.dependencies import CurrentUser +from app.routers.user import create_user def test_can_show_calendar_public(session, user): @@ -11,37 +10,32 @@ def test_can_show_calendar_public(session, user): # current_user = CurrentUser(**user.__dict__) current_user = user result = can_show_calendar( - requested_user_username="test_username", - db=session, - current_user=current_user, + requested_user_username='test_username', + db=session, current_user=current_user ) assert result is True session.commit() def test_can_show_calendar_private(session, user): - another_user = _create_user( + another_user = create_user( session=session, - username="new_test_username2", - email="new_test.email2@gmail.com", - password="passpar_2", - language_id=1, - full_name="test_full_name", - description="test_description", + username='new_test_username2', + email='new_test.email2@gmail.com', + password='passpar_2', + language_id=1 ) current_user = user # TODO to be replaced after user system is merged: # current_user = CurrentUser(**user.__dict__) result_a = can_show_calendar( - requested_user_username="new_test_username2", - db=session, - current_user=current_user, + requested_user_username='new_test_username2', + db=session, current_user=current_user ) result_b = can_show_calendar( - requested_user_username="test_username", - db=session, - current_user=current_user, + requested_user_username='test_username', + db=session, current_user=current_user ) assert result_a is False assert result_b is True diff --git a/tests/test_geolocation.py b/tests/test_geolocation.py deleted file mode 100644 index 9a9503fd..00000000 --- a/tests/test_geolocation.py +++ /dev/null @@ -1,105 +0,0 @@ -import pytest - -from app.internal.event import get_location_coordinates -from app.database.models import Event -from sqlalchemy.sql import func - - -class TestGeolocation: - CORRECT_LOCATION_EVENT = { - "title": "test title", - "start_date": "2021-02-18", - "start_time": "18:00", - "end_date": "2021-02-18", - "end_time": "20:00", - "location_type": "address", - "location": "אדר 11, אשדוד", - "event_type": "on", - "description": "test1", - "color": "red", - "invited": "a@gmail.com", - "availability": "busy", - "privacy": "public", - } - - WRONG_LOCATION_EVENT = { - "title": "test title", - "start_date": "2021-02-18", - "start_time": "18:00", - "end_date": "2021-02-18", - "end_time": "20:00", - "location_type": "address", - "location": "not a real location with coords", - "event_type": "on", - "description": "test1", - "invited": "a@gmail.com", - "color": "red", - "availability": "busy", - "privacy": "public", - } - - CORRECT_LOCATIONS = [ - "Tamuz 13, Ashdod", - "Menachem Begin 21, Tel Aviv", - "רמב״ן 25, ירושלים", - ] - - WRONG_LOCATIONS = [ - "not a real location with coords", - "מיקום לא תקין", - "https://us02web.zoom.us/j/376584566", - ] - - @staticmethod - @pytest.mark.asyncio - @pytest.mark.parametrize("location", CORRECT_LOCATIONS) - async def test_get_location_coordinates_correct(location): - # Test geolocation search using valid locations. - location = await get_location_coordinates(location) - assert all(location) - - @staticmethod - @pytest.mark.asyncio - @pytest.mark.parametrize("location", WRONG_LOCATIONS) - async def test_get_location_coordinates_wrong(location): - # Test geolocation search using invalid locations. - location = await get_location_coordinates(location) - assert location == location - - @staticmethod - @pytest.mark.asyncio - async def test_event_location_correct(event_test_client, session): - # Test handling with location available on geopy servers. - response = event_test_client.post( - "event/edit", - data=TestGeolocation.CORRECT_LOCATION_EVENT, - ) - assert response.ok - event_id = session.query(func.count(Event.id)).scalar() - url = event_test_client.app.url_path_for( - "eventview", - event_id=event_id, - ) - response = event_test_client.get(url) - location = await get_location_coordinates( - TestGeolocation.CORRECT_LOCATION_EVENT["location"], - ) - address = location.name.split(" ")[0] - assert bytes(address, "utf-8") in response.content - - @staticmethod - def test_event_location_wrong(event_test_client, session): - # Test handling with location not available on geopy servers. - address = TestGeolocation.WRONG_LOCATION_EVENT["location"] - response = event_test_client.post( - "event/edit", - data=TestGeolocation.WRONG_LOCATION_EVENT, - ) - assert response.ok - event_id = session.query(func.count(Event.id)).scalar() - url = event_test_client.app.url_path_for( - "eventview", - event_id=event_id, - ) - response = event_test_client.get(url) - assert bytes(address, "utf-8") in response.content diff --git a/tests/test_google_connect.py b/tests/test_google_connect.py index 58ac8aa3..02511266 100644 --- a/tests/test_google_connect.py +++ b/tests/test_google_connect.py @@ -5,13 +5,12 @@ import app.internal.google_connect as google_connect from app.routers.event import create_event from app.database.models import OAuthCredentials +from app.routers.user import create_user from google.oauth2.credentials import Credentials from googleapiclient.discovery import build from googleapiclient.http import HttpMock -from app.routers.register import _create_user - @pytest.fixture def google_events_mock(): @@ -25,13 +24,25 @@ def google_events_mock(): "created": "2021-01-13T09:10:02.000Z", "updated": "2021-01-13T09:10:02.388Z", "summary": "some title", - "creator": {"email": "someemail", "self": True}, - "organizer": {"email": "someemail", "self": True}, - "start": {"dateTime": "2021-02-25T13:00:00+02:00"}, - "end": {"dateTime": "2021-02-25T14:00:00+02:00"}, + "creator": { + "email": "someemail", + "self": True + }, + "organizer": { + "email": "someemail", + "self": True + }, + "start": { + "dateTime": "2021-02-25T13:00:00+02:00" + }, + "end": { + "dateTime": "2021-02-25T14:00:00+02:00" + }, "iCalUID": "somecode", "sequence": 0, - "reminders": {"useDefault": True}, + "reminders": { + "useDefault": True + } }, { "kind": "calendar#event", @@ -42,15 +53,27 @@ def google_events_mock(): "created": "2021-01-13T09:10:02.000Z", "updated": "2021-01-13T09:10:02.388Z", "summary": "some title to all day event", - "creator": {"email": "someemail", "self": True}, - "organizer": {"email": "someemail", "self": True}, - "start": {"date": "2021-02-25"}, - "end": {"date": "2021-02-25"}, + "creator": { + "email": "someemail", + "self": True + }, + "organizer": { + "email": "someemail", + "self": True + }, + "start": { + "date": "2021-02-25" + }, + "end": { + "date": "2021-02-25" + }, "iCalUID": "somecode", "sequence": 0, - "location": "somelocation", - "reminders": {"useDefault": True}, - }, + "location": 'somelocation', + "reminders": { + "useDefault": True + } + } ] @@ -62,7 +85,7 @@ def credentials(): token_uri="some_uri", client_id="somecode", client_secret="some_secret", - expiry=datetime(2021, 1, 28), + expiry=datetime(2021, 1, 28) ) return cred @@ -77,30 +100,30 @@ def test_push_events_to_db(google_events_mock, user, session): def test_db_cleanup(google_events_mock, user, session): for event in google_events_mock: location = None - title = event["summary"] + title = event['summary'] # support for all day events - if "dateTime" in event["start"].keys(): + if 'dateTime' in event['start'].keys(): # part time event - start = datetime.fromisoformat(event["start"]["dateTime"]) - end = datetime.fromisoformat(event["end"]["dateTime"]) + start = datetime.fromisoformat(event['start']['dateTime']) + end = datetime.fromisoformat(event['end']['dateTime']) else: # all day event - start = event["start"]["date"].split("-") + start = event['start']['date'].split('-') start = datetime( year=int(start[0]), month=int(start[1]), - day=int(start[2]), + day=int(start[2]) ) - end = event["end"]["date"].split("-") + end = event['end']['date'].split('-') end = datetime( year=int(end[0]), month=int(end[1]), - day=int(end[2]), + day=int(end[2]) ) - if "location" in event.keys(): - location = event["location"] + if 'location' in event.keys(): + location = event['location'] create_event( db=session, @@ -109,26 +132,20 @@ def test_db_cleanup(google_events_mock, user, session): end=end, owner_id=user.id, location=location, - is_google_event=True, + is_google_event=True ) assert google_connect.cleanup_user_google_calendar_events( - user, - session, - ) + user, session) @pytest.mark.usefixtures("session") def test_get_credentials_from_db(session): - user = _create_user( - session=session, - username="new_test_username", - password="new_test_password", - email="new_test.email@gmail.com", - language_id=1, - full_name="test_full_name", - description="test_description", - ) + user = create_user(session=session, + username='new_test_username', + password='new_test_password', + email='new_test.email@gmail.com', + language_id=1) credentials = OAuthCredentials( owner=user, @@ -137,7 +154,7 @@ def test_get_credentials_from_db(session): token_uri="some_uri", client_id="somecode", client_secret="some_secret", - expiry=datetime(2021, 2, 22), + expiry=datetime(2021, 2, 22) ) session.add(credentials) session.commit() @@ -149,16 +166,17 @@ def test_get_credentials_from_db(session): @pytest.mark.usefixtures("session", "user", "credentials") def test_refresh_token(mocker, session, user, credentials): + mocker.patch( - "google.oauth2.credentials.Credentials.refresh", - return_value=logger.debug("refreshed"), + 'google.oauth2.credentials.Credentials.refresh', + return_value=logger.debug('refreshed') ) assert google_connect.refresh_token(credentials, user, session) mocker.patch( - "google.oauth2.credentials.Credentials.expired", - return_value=False, + 'google.oauth2.credentials.Credentials.expired', + return_value=False ) assert google_connect.refresh_token(credentials, user, session) @@ -171,75 +189,76 @@ def __init__(self, service): self.service = service def list(self, *args): - request = self.service.events().list( - calendarId="primary", - timeMin=datetime(2021, 1, 1).isoformat(), - timeMax=datetime(2022, 1, 1).isoformat(), - singleEvents=True, - orderBy="startTime", + request = self.service.events().list(calendarId='primary', + timeMin=datetime( + 2021, 1, 1).isoformat(), + timeMax=datetime( + 2022, 1, 1).isoformat(), + singleEvents=True, + orderBy='startTime' + ) + http = HttpMock( + 'calendar-linux.json', + {'status': '200'} ) - http = HttpMock("calendar-linux.json", {"status": "200"}) response = request.execute(http=http) return response - http = HttpMock("./tests/calendar-discovery.json", {"status": "200"}) + http = HttpMock( + './tests/calendar-discovery.json', + {'status': '200'} + ) - service = build("calendar", "v3", http=http) + service = build('calendar', 'v3', http=http) mocker.patch( - "googleapiclient.discovery.build", + 'googleapiclient.discovery.build', return_value=service, - events=service, + events=service ) mocker.patch( - "googleapiclient.discovery.Resource", - events=mock_events(service), + 'googleapiclient.discovery.Resource', + events=mock_events(service) ) assert google_connect.get_current_year_events(credentials, user, session) -@pytest.mark.usefixtures( - "user", - "session", - "google_connect_test_client", - "credentials", -) +@pytest.mark.usefixtures("user", "session", + "google_connect_test_client", "credentials") def test_google_sync(mocker, google_connect_test_client, session, credentials): - _create_user( - session=session, - username="new_test_username", - password="new_test_password", - email="new_test.email@gmail.com", - language_id=1, - full_name="test_full_name", - description="test_description", - ) + create_user(session=session, + username='new_test_username', + password='new_test_password', + email='new_test.email@gmail.com', + language_id=1) mocker.patch( - "app.routers.google_connect.get_credentials", - return_value=credentials, + 'app.routers.google_connect.get_credentials', + return_value=credentials ) mocker.patch( - "app.routers.google_connect.fetch_save_events", - return_value=None, + 'app.routers.google_connect.fetch_save_events', + return_value=None ) connect = google_connect_test_client.get( - "google/sync", - headers={"referer": "http://testserver/"}, - ) + 'google/sync', + headers={ + "referer": 'http://testserver/' + }) assert connect.ok # second case mocker.patch( - "app.routers.google_connect.get_credentials", - return_value=None, + 'app.routers.google_connect.get_credentials', + return_value=None ) connect = google_connect_test_client.get( - "google/sync", - headers={"referer": "http://testserver/"}, - ) + 'google/sync', + headers={ + "referer": 'http://testserver/' + }) assert connect.ok @@ -251,125 +270,97 @@ def test_is_client_secret_none(): @pytest.mark.usefixtures("session") def test_clean_up_old_credentials_from_db(session): google_connect.clean_up_old_credentials_from_db(session) - assert ( - len(session.query(OAuthCredentials).filter_by(user_id=None).all()) == 0 - ) + assert len(session.query(OAuthCredentials) + .filter_by(user_id=None).all()) == 0 -@pytest.mark.usefixtures("session", "user", "credentials") -def test_get_credentials_from_consent_screen( - mocker, - session, - user, - credentials, -): +@pytest.mark.usefixtures("session", 'user', 'credentials') +def test_get_credentials_from_consent_screen(mocker, session, + user, credentials): mocker.patch( - "google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file", - return_value=mocker.Mock( - name="flow", - **{ - "credentials": credentials, - "run_local_server": mocker.Mock( - name="run_local_server", - return_value=logger.debug("running server"), - ), - } - ), + 'google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file', + return_value=mocker.Mock(name='flow', **{ + "credentials": credentials, + "run_local_server": mocker.Mock(name='run_local_server', + return_value=logger.debug( + 'running server')) + }) ) mocker.patch( - "app.internal.google_connect.is_client_secret_none", - return_value=False, + 'app.internal.google_connect.is_client_secret_none', + return_value=False ) - assert ( - google_connect.get_credentials_from_consent_screen(user, session) - == credentials - ) + assert google_connect.get_credentials_from_consent_screen( + user, session) == credentials @pytest.mark.usefixtures("session") def test_create_google_event(session): - user = _create_user( - session=session, - username="new_test_username", - password="new_test_password", - email="new_test.email@gmail.com", - language_id=1, - full_name="test_full_name", - description="test_description", - ) + user = create_user(session=session, + username='new_test_username', + password='new_test_password', + email='new_test.email@gmail.com', + language_id=1) event = google_connect.create_google_event( - "title", - datetime(2021, 1, 1, 15, 15), - datetime(2021, 1, 1, 15, 30), - user, - "location", - session, - ) + 'title', + datetime(2021, 1, 1, 15, 15), + datetime(2021, 1, 1, 15, 30), + user, + 'location', + session + ) - assert event.title == "title" + assert event.title == 'title' -@pytest.mark.usefixtures("session", "user", "credentials") +@pytest.mark.usefixtures("session", "user", 'credentials') def test_get_credentials(mocker, session, user, credentials): - user = _create_user( + user = create_user( session=session, - username="new_test_username", - password="new_test_password", - email="new_test.email@gmail.com", - language_id=1, - full_name="test_full_name", - description="test_description", + username='new_test_username', + password='new_test_password', + email='new_test.email@gmail.com', + language_id=1 ) mocker.patch( - "app.internal.google_connect.get_credentials_from_consent_screen", - return_value=credentials, + 'app.internal.google_connect.get_credentials_from_consent_screen', + return_value=credentials ) - assert ( - google_connect.get_credentials(user=user, session=session) - == credentials - ) + assert google_connect.get_credentials(user=user, + session=session) == credentials mocker.patch( - "app.internal.google_connect.get_credentials", - return_value=credentials, + 'app.internal.google_connect.get_credentials', + return_value=credentials ) mocker.patch( - "app.internal.google_connect.refresh_token", - return_value=credentials, + 'app.internal.google_connect.refresh_token', + return_value=credentials ) - assert ( - google_connect.get_credentials(user=user, session=session) - == credentials - ) + assert google_connect.get_credentials(user=user, + session=session) == credentials + +@pytest.mark.usefixtures("session", "user", + 'credentials', 'google_events_mock') +def test_fetch_save_events(mocker, session, user, credentials, + google_events_mock): -@pytest.mark.usefixtures( - "session", - "user", - "credentials", - "google_events_mock", -) -def test_fetch_save_events( - mocker, - session, - user, - credentials, - google_events_mock, -): mocker.patch( - "app.internal.google_connect.get_current_year_events", - return_value=google_events_mock, + 'app.internal.google_connect.get_current_year_events', + return_value=google_events_mock ) - assert google_connect.fetch_save_events(credentials, user, session) is None + assert google_connect.fetch_save_events(credentials, + user, session) is None -@pytest.mark.usefixtures("session", "user", "credentials") +@pytest.mark.usefixtures("session", "user", 'credentials') def test_push_credentials_to_db(session, user, credentials): assert google_connect.push_credentials_to_db(credentials, user, session) diff --git a/tests/test_invitation.py b/tests/test_invitation.py new file mode 100644 index 00000000..c609a973 --- /dev/null +++ b/tests/test_invitation.py @@ -0,0 +1,50 @@ +from fastapi import status + +from app.routers.invitation import get_all_invitations, get_invitation_by_id + + +class TestInvitations: + NO_INVITATIONS = b"You don't have any invitations." + URL = "/invitations/" + + @staticmethod + def test_view_no_invitations(invitation_test_client): + response = invitation_test_client.get(TestInvitations.URL) + assert response.ok + assert TestInvitations.NO_INVITATIONS in response.content + + @staticmethod + def test_accept_invitations(user, invitation, invitation_test_client): + invitation = {"invite_id ": invitation.id} + resp = invitation_test_client.post( + TestInvitations.URL, data=invitation) + assert resp.status_code == status.HTTP_302_FOUND + + @staticmethod + def test_get_all_invitations_success(invitation, event, user, session): + invitations = get_all_invitations(event=event, db=session) + assert invitations == [invitation] + invitations = get_all_invitations(recipient=user, db=session) + assert invitations == [invitation] + + @staticmethod + def test_get_all_invitations_failure(user, session): + invitations = get_all_invitations(unknown_parameter=user, db=session) + assert invitations == [] + + invitations = get_all_invitations(recipient=None, db=session) + assert invitations == [] + + @staticmethod + def test_get_invitation_by_id(invitation, session): + get_invitation = get_invitation_by_id(invitation.id, db=session) + assert get_invitation == invitation + + @staticmethod + def test_repr(invitation): + invitation_repr = ( + f'' + ) + assert invitation.__repr__() == invitation_repr diff --git a/tests/test_notification.py b/tests/test_notification.py deleted file mode 100644 index 23eacfd2..00000000 --- a/tests/test_notification.py +++ /dev/null @@ -1,177 +0,0 @@ -from starlette.status import HTTP_406_NOT_ACCEPTABLE - -from app.database.models import InvitationStatusEnum, MessageStatusEnum -from app.internal.notification import get_all_invitations, get_invitation_by_id -from app.routers.notification import router -from tests.fixtures.client_fixture import login_client - - -class TestNotificationRoutes: - NO_NOTIFICATIONS = b"You don't have any new notifications." - NO_NOTIFICATION_IN_ARCHIVE = b"You don't have any archived notifications." - NEW_NOTIFICATIONS_URL = router.url_path_for("view_notifications") - LOGIN_DATA = {"username": "test_username", "password": "test_password"} - - def test_view_no_notifications( - self, - user, - notification_test_client, - ): - login_client(notification_test_client, self.LOGIN_DATA) - resp = notification_test_client.get(self.NEW_NOTIFICATIONS_URL) - assert resp.ok - assert self.NO_NOTIFICATIONS in resp.content - - def test_accept_invitations( - self, - user, - invitation, - notification_test_client, - ): - login_client(notification_test_client, self.LOGIN_DATA) - assert invitation.status == InvitationStatusEnum.UNREAD - data = { - "invite_id": invitation.id, - "next_url": self.NEW_NOTIFICATIONS_URL, - } - url = router.url_path_for("accept_invitations") - resp = notification_test_client.post(url, data=data) - assert resp.ok - assert InvitationStatusEnum.ACCEPTED - - def test_decline_invitations( - self, - user, - invitation, - notification_test_client, - session, - ): - login_client(notification_test_client, self.LOGIN_DATA) - assert invitation.status == InvitationStatusEnum.UNREAD - data = { - "invite_id": invitation.id, - "next_url": self.NEW_NOTIFICATIONS_URL, - } - url = router.url_path_for("decline_invitations") - resp = notification_test_client.post(url, data=data) - assert resp.ok - session.refresh(invitation) - assert invitation.status == InvitationStatusEnum.DECLINED - - def test_mark_message_as_read( - self, - user, - message, - notification_test_client, - session, - ): - login_client(notification_test_client, self.LOGIN_DATA) - assert message.status == MessageStatusEnum.UNREAD - data = { - "message_id": message.id, - "next_url": self.NEW_NOTIFICATIONS_URL, - } - url = router.url_path_for("mark_message_as_read") - resp = notification_test_client.post(url, data=data) - assert resp.ok - session.refresh(message) - assert message.status == MessageStatusEnum.READ - - def test_mark_all_as_read( - self, - user, - message, - sec_message, - notification_test_client, - session, - ): - login_client(notification_test_client, self.LOGIN_DATA) - url = router.url_path_for("mark_all_as_read") - assert message.status == MessageStatusEnum.UNREAD - assert sec_message.status == MessageStatusEnum.UNREAD - data = {"next_url": self.NEW_NOTIFICATIONS_URL} - resp = notification_test_client.post(url, data=data) - assert resp.ok - session.refresh(message) - session.refresh(sec_message) - assert message.status == MessageStatusEnum.READ - assert sec_message.status == MessageStatusEnum.READ - - def test_archive( - self, - user, - message, - notification_test_client, - session, - ): - login_client(notification_test_client, self.LOGIN_DATA) - archive_url = router.url_path_for("view_archive") - resp = notification_test_client.get(archive_url) - assert resp.ok - assert self.NO_NOTIFICATION_IN_ARCHIVE in resp.content - - # read message - data = { - "message_id": message.id, - "next_url": self.NEW_NOTIFICATIONS_URL, - } - url = router.url_path_for("mark_message_as_read") - notification_test_client.post(url, data=data) - - resp = notification_test_client.get(archive_url) - assert resp.ok - assert self.NO_NOTIFICATION_IN_ARCHIVE not in resp.content - - def test_wrong_id( - self, - user, - notification_test_client, - session, - ): - login_client(notification_test_client, self.LOGIN_DATA) - data = { - "message_id": 1, - "next_url": "/", - } - url = router.url_path_for("mark_message_as_read") - resp = notification_test_client.post(url, data=data) - assert resp.status_code == HTTP_406_NOT_ACCEPTABLE - - -class TestNotification: - def test_get_all_invitations_success( - self, - invitation, - event, - user, - session, - ): - invitations = get_all_invitations(event=event, session=session) - assert invitations == [invitation] - invitations = get_all_invitations(recipient=user, session=session) - assert invitations == [invitation] - - def test_get_all_invitations_failure(self, user, session): - invitations = get_all_invitations( - unknown_parameter=user, - session=session, - ) - assert invitations == [] - - invitations = get_all_invitations(recipient=None, session=session) - assert invitations == [] - - def test_get_invitation_by_id(self, invitation, session): - get_invitation = get_invitation_by_id(invitation.id, session=session) - assert get_invitation == invitation - - def test_invitation_repr(self, invitation): - invitation_repr = ( - f"" - ) - assert invitation.__repr__() == invitation_repr - - def test_message_repr(self, message): - message_repr = f"" - assert message.__repr__() == message_repr diff --git a/tests/test_share_event.py b/tests/test_share_event.py index e202597a..67679b2c 100644 --- a/tests/test_share_event.py +++ b/tests/test_share_event.py @@ -1,68 +1,49 @@ -from app.database.models import InvitationStatusEnum -from app.internal.notification import get_all_invitations -from app.routers.share import ( - send_email_invitation, - send_in_app_invitation, - share, - sort_emails, -) +from app.routers.invitation import get_all_invitations +from app.routers.share import (accept, send_email_invitation, + send_in_app_invitation, share, sort_emails) class TestShareEvent: + def test_share_success(self, user, event, session): - share(event, [user.email], session) - invitations = get_all_invitations( - session=session, - recipient_id=user.id, - ) + participants = [user.email] + share(event, participants, session) + invitations = get_all_invitations(db=session, recipient_id=user.id) assert invitations != [] def test_share_failure(self, event, session): participants = [event.owner.email] share(event, participants, session) invitations = get_all_invitations( - session=session, - recipient_id=event.owner.id, - ) + db=session, recipient_id=event.owner.id) assert invitations == [] def test_sort_emails(self, user, session): # the user is being imported # so he will be created data = [ - "test.email@gmail.com", # registered user - "not_logged_in@gmail.com", # unregistered user + 'test.email@gmail.com', # registered user + 'not_logged_in@gmail.com', # unregistered user ] sorted_data = sort_emails(data, session=session) assert sorted_data == { - "registered": ["test.email@gmail.com"], - "unregistered": ["not_logged_in@gmail.com"], + 'registered': ['test.email@gmail.com'], + 'unregistered': ['not_logged_in@gmail.com'] } def test_send_in_app_invitation_success( - self, - user, - sender, - event, - session, + self, user, sender, event, session ): assert send_in_app_invitation([user.email], event, session=session) - invitation = get_all_invitations(session=session, recipient=user)[0] + invitation = get_all_invitations(db=session, recipient=user)[0] assert invitation.event.owner == sender assert invitation.recipient == user session.delete(invitation) def test_send_in_app_invitation_failure( - self, - user, - sender, - event, - session, - ): - assert ( - send_in_app_invitation([sender.email], event, session=session) - is False - ) + self, user, sender, event, session): + assert (send_in_app_invitation( + [sender.email], event, session=session) is False) def test_send_email_invitation(self, user, event): send_email_invitation([user.email], event) @@ -70,9 +51,5 @@ def test_send_email_invitation(self, user, event): assert True def test_accept(self, invitation, session): - invitation.accept(session=session) - assert invitation.status == InvitationStatusEnum.ACCEPTED - - def test_decline(self, invitation, session): - invitation.decline(session=session) - assert invitation.status == InvitationStatusEnum.DECLINED + accept(invitation, session=session) + assert invitation.status == 'accepted' diff --git a/tests/test_statistics.py b/tests/test_statistics.py index 10cc8457..7ef52afb 100644 --- a/tests/test_statistics.py +++ b/tests/test_statistics.py @@ -1,63 +1,40 @@ import datetime -from app.internal.notification import get_all_invitations from app.internal.statistics import get_statistics from app.internal.statistics import INVALID_DATE_RANGE, INVALID_USER from app.internal.statistics import SUCCESS_STATUS from app.routers.event import create_event -from app.routers.register import _create_user -from app.routers.share import send_in_app_invitation +from app.routers.user import create_user +from app.routers.share import send_in_app_invitation, accept +from app.routers.invitation import get_all_invitations def create_events_and_user_events(session, start, end, owner, invitations): for _ in range(1, 3): event = create_event( - db=session, - title="title" + str(_), - start=start, - end=end, - owner_id=owner, - location="location" + str(_), - ) + db=session, title="title" + str(_), start=start, end=end, + owner_id=owner, location="location" + str(_)) send_in_app_invitation(invitations, event, session) def create_data(session): - _ = [ - _create_user( - username="user" + str(_), - password="password" + str(_), - email="email" + str(_) + "@" + "gmail.com", - language_id="Hebrew", - session=session, - description="", - full_name="", - ) - for _ in range(1, 4) - ] + _ = [create_user("user" + str(_), "password" + str(_), + "email" + str(_) + '@' + 'gmail.com', "Hebrew", + session) for _ in range(1, 4)] start = datetime.datetime.now() + datetime.timedelta(hours=-1) end = datetime.datetime.now() + datetime.timedelta(hours=1) - create_events_and_user_events( - session, - start, - end, - 1, - ["email2@gmail.com", "email3@gmail.com"], - ) + create_events_and_user_events(session, start, end, 1, + ["email2@gmail.com", "email3@gmail.com"]) start = datetime.datetime.now() + datetime.timedelta(days=-1) end = datetime.datetime.now() + datetime.timedelta(days=-1, hours=2) - create_events_and_user_events( - session, - start, - end, - 1, - ["email2@gmail.com", "email3@gmail.com"], - ) + create_events_and_user_events(session, start, end, 1, + ["email2@gmail.com", "email3@gmail.com"]) start = datetime.datetime.now() + datetime.timedelta(hours=1) end = datetime.datetime.now() + datetime.timedelta(hours=1.5) - create_events_and_user_events(session, start, end, 2, ["email3@gmail.com"]) + create_events_and_user_events(session, start, end, 2, + ["email3@gmail.com"]) for invitation in get_all_invitations(session): - invitation.accept(session) + accept(invitation, session) def test_statistics_invalid_date_range(session): diff --git a/tests/test_user.py b/tests/test_user.py index 1a1ed0a7..213e7589 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -1,8 +1,9 @@ from datetime import datetime import pytest -from app.routers.register import _create_user -from app.routers.user import does_user_exist, get_users +from app.routers.user import ( + create_user, does_user_exist, get_users +) from app.internal.user.availability import disable, enable from app.internal.utils import save from app.database.models import UserEvent, Event @@ -12,14 +13,12 @@ @pytest.fixture def user1(session): # a user made for testing who doesn't own any event. - user = _create_user( + user = create_user( session=session, - username="new_test_username", - full_name="test_user", - password="new_test_password", - email="new2_test.email@gmail.com", - language_id="english", - description="", + username='new_test_username', + password='new_test_password', + email='new2_test.email@gmail.com', + language_id='english' ) return user @@ -28,23 +27,21 @@ def user1(session): @pytest.fixture def user2(session): # a user made for testing who already owns an event. - user = _create_user( + user = create_user( session=session, - username="new_test_username2", - full_name="test_user", - password="new_test_password2", - email="new_test_love231.email@gmail.com", - language_id="english", - description="", + username='new_test_username2', + password='new_test_password2', + email='new_test_love231.email@gmail.com', + language_id='english' ) data = { - "title": "user2 event", - "start": datetime.strptime("2021-05-05 14:59", "%Y-%m-%d %H:%M"), - "end": datetime.strptime("2021-05-05 15:01", "%Y-%m-%d %H:%M"), - "location": "https://us02web.zoom.us/j/875384596", - "content": "content", - "owner_id": user.id, + 'title': 'user2 event', + 'start': datetime.strptime('2021-05-05 14:59', '%Y-%m-%d %H:%M'), + 'end': datetime.strptime('2021-05-05 15:01', '%Y-%m-%d %H:%M'), + 'location': 'https://us02web.zoom.us/j/875384596', + 'content': 'content', + 'owner_id': user.id, } create_event(session, **data) @@ -55,12 +52,12 @@ def user2(session): @pytest.fixture def event1(session, user2): data = { - "title": "test event title", - "start": datetime.strptime("2021-05-05 14:59", "%Y-%m-%d %H:%M"), - "end": datetime.strptime("2021-05-05 15:01", "%Y-%m-%d %H:%M"), - "location": "https://us02web.zoom.us/j/87538459r6", - "content": "content", - "owner_id": user2.id, + 'title': 'test event title', + 'start': datetime.strptime('2021-05-05 14:59', '%Y-%m-%d %H:%M'), + 'end': datetime.strptime('2021-05-05 15:01', '%Y-%m-%d %H:%M'), + 'location': 'https://us02web.zoom.us/j/87538459r6', + 'content': 'content', + 'owner_id': user2.id, } event = create_event(session, **data) @@ -71,41 +68,41 @@ def test_disabling_no_event_user(session, user1): # users without any future event can disable themselves disable(session, user1.id) assert user1.disabled - future_events = list( - session.query(Event.id) - .join(UserEvent) - .filter(UserEvent.user_id == user1.id, Event.start > datetime.now()), - ) + future_events = list(session.query(Event.id) + .join(UserEvent) + .filter( + UserEvent.user_id == user1.id, + Event.start > datetime + .now())) assert not future_events # making sure that after disabling the user he can be easily enabled. enable(session, user1.id) assert not user1.disabled -def test_disabling_user_participating_event(session, user1, event1): +def test_disabling_user_participating_event( + session, user1, event1): """making sure only users who only participate in events can disable and enable themselves.""" - association = UserEvent(user_id=user1.id, event_id=event1.id) + association = UserEvent( + user_id=user1.id, + event_id=event1.id + ) save(session, association) disable(session, user1.id) assert user1.disabled - future_events = list( - session.query(Event.id) - .join(UserEvent) - .filter( - UserEvent.user_id == user1.id, - Event.start > datetime.now(), - Event.owner_id == user1.id, - ), - ) + future_events = list(session.query(Event.id) + .join(UserEvent) + .filter( + UserEvent.user_id == user1.id, + Event.start > datetime.now(), + Event.owner_id == user1.id)) assert not future_events enable(session, user1.id) assert not user1.disabled - deleted_user_event_connection = ( - session.query(UserEvent) - .filter(UserEvent.user_id == user1.id, UserEvent.event_id == event1.id) - .first() - ) + deleted_user_event_connection = session.query(UserEvent).filter( + UserEvent.user_id == user1.id, + UserEvent.event_id == event1.id).first() session.delete(deleted_user_event_connection) @@ -116,19 +113,18 @@ def test_disabling_event_owning_user(session, user2): class TestUser: + def test_create_user(self, session): - user = _create_user( + user = create_user( session=session, - username="new_test_username", - password="new_test_password", - email="new_test.email@gmail.com", - language_id=1, - description="", - full_name="test_user", + username='new_test_username', + password='new_test_password', + email='new_test.email@gmail.com', + language_id=1 ) - assert user.username == "new_test_username" - assert user.password == "new_test_password" - assert user.email == "new_test.email@gmail.com" + assert user.username == 'new_test_username' + assert user.password == 'new_test_password' + assert user.email == 'new_test.email@gmail.com' assert user.language_id == 1 session.delete(user) session.commit() @@ -139,7 +135,7 @@ def test_get_users_success(self, user, session): assert get_users(email=user.email, session=session) == [user] def test_get_users_failure(self, session, user): - assert get_users(username="wrong username", session=session) == [] + assert get_users(username='wrong username', session=session) == [] assert get_users(wrong_param=user.username, session=session) == [] def test_does_user_exist_success(self, user, session): @@ -148,8 +144,8 @@ def test_does_user_exist_success(self, user, session): assert does_user_exist(email=user.email, session=session) def test_does_user_exist_failure(self, session): - assert not does_user_exist(username="wrong username", session=session) + assert not does_user_exist(username='wrong username', session=session) assert not does_user_exist(session=session) def test_repr(self, user): - assert user.__repr__() == f"" + assert user.__repr__() == f'' diff --git a/tests/fixtures/user_fixture.py b/tests/user_fixture.py similarity index 68% rename from tests/fixtures/user_fixture.py rename to tests/user_fixture.py index 84aa17d3..a8b30056 100644 --- a/tests/fixtures/user_fixture.py +++ b/tests/user_fixture.py @@ -4,24 +4,20 @@ from sqlalchemy.orm import Session from app.database.models import User -from app.database.schemas import UserCreate from app.internal.utils import create_model, delete_instance -from app.routers.register import create_user @pytest.fixture -async def user(session: Session) -> Generator[User, None, None]: - schema = UserCreate( +def user(session: Session) -> Generator[User, None, None]: + mock_user = create_model( + session, + User, username="test_username", password="test_password", - confirm_password="test_password", email="test.email@gmail.com", - full_name="test_full_name", - description="test_description", language_id=1, target_weight=60, ) - mock_user = await create_user(session, schema) yield mock_user delete_instance(session, mock_user) @@ -29,11 +25,10 @@ async def user(session: Session) -> Generator[User, None, None]: @pytest.fixture def user2(session: Session) -> Generator[User, None, None]: mock_user = create_model( - session, - User, - username="test_username2", - password="test_password2", - email="test2.email@gmail.com", + session, User, + username='test_username2', + password='test_password2', + email='test2.email@gmail.com', language_id=1, ) yield mock_user diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 00000000..58ffdbd0 --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,13 @@ +from sqlalchemy.orm import Session + + +def create_model(session: Session, model_class, **kw): + instance = model_class(**kw) + session.add(instance) + session.commit() + return instance + + +def delete_instance(session: Session, instance): + session.delete(instance) + session.commit() diff --git a/tests/fixtures/weekly_tasks_fixture.py b/tests/weekly_tasks_fixture.py similarity index 100% rename from tests/fixtures/weekly_tasks_fixture.py rename to tests/weekly_tasks_fixture.py diff --git a/tests/fixtures/zodiac_fixture.py b/tests/zodiac_fixture.py similarity index 100% rename from tests/fixtures/zodiac_fixture.py rename to tests/zodiac_fixture.py From dab05ee0b9dbb5c452679da68bfb08140d53534f Mon Sep 17 00:00:00 2001 From: itzik Date: Wed, 24 Feb 2021 21:30:23 +0200 Subject: [PATCH 31/32] Arranging files --- tests/conftest.py | 53 +++++++------- tests/{ => fixtures}/association_fixture.py | 3 +- tests/{ => fixtures}/asyncio_fixture.py | 8 +-- tests/{ => fixtures}/category_fixture.py | 8 ++- tests/{ => fixtures}/client_fixture.py | 0 tests/{ => fixtures}/comment_fixture.py | 8 +-- tests/{ => fixtures}/dayview_fixture.py | 75 +++++++++++++++----- tests/{ => fixtures}/event_fixture.py | 32 ++++----- tests/{ => fixtures}/invitation_fixture.py | 7 +- tests/{ => fixtures}/jokes_fixture.py | 2 +- tests/{ => fixtures}/logger_fixture.py | 16 +++-- tests/{ => fixtures}/quotes_fixture.py | 13 ++-- tests/{ => fixtures}/user_fixture.py | 9 +-- tests/{ => fixtures}/weekly_tasks_fixture.py | 0 tests/{ => fixtures}/zodiac_fixture.py | 3 +- 15 files changed, 149 insertions(+), 88 deletions(-) rename tests/{ => fixtures}/association_fixture.py (71%) rename tests/{ => fixtures}/asyncio_fixture.py (90%) rename tests/{ => fixtures}/category_fixture.py (64%) rename tests/{ => fixtures}/client_fixture.py (100%) rename tests/{ => fixtures}/comment_fixture.py (79%) rename tests/{ => fixtures}/dayview_fixture.py (54%) rename tests/{ => fixtures}/event_fixture.py (85%) rename tests/{ => fixtures}/invitation_fixture.py (89%) rename tests/{ => fixtures}/jokes_fixture.py (89%) rename tests/{ => fixtures}/logger_fixture.py (56%) rename tests/{ => fixtures}/quotes_fixture.py (74%) rename tests/{ => fixtures}/user_fixture.py (88%) rename tests/{ => fixtures}/weekly_tasks_fixture.py (100%) rename tests/{ => fixtures}/zodiac_fixture.py (92%) diff --git a/tests/conftest.py b/tests/conftest.py index 500ede4a..f5243885 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,21 +8,21 @@ from app.database.models import Base pytest_plugins = [ - 'tests.user_fixture', - 'tests.event_fixture', - 'tests.dayview_fixture', - 'tests.invitation_fixture', - 'tests.association_fixture', - 'tests.client_fixture', - 'tests.weekly_tasks_fixture', - 'tests.asyncio_fixture', - 'tests.logger_fixture', - 'tests.category_fixture', - 'smtpdfix', - 'tests.quotes_fixture', - 'tests.zodiac_fixture', - 'tests.jokes_fixture', - 'tests.comment_fixture', + "fixtures.tests.user_fixture", + "fixtures.tests.event_fixture", + "fixtures.tests.dayview_fixture", + "fixtures.tests.invitation_fixture", + "fixtures.tests.association_fixture", + "fixtures.tests.client_fixture", + "fixtures.tests.weekly_tasks_fixture", + "fixtures.tests.asyncio_fixture", + "fixtures.tests.logger_fixture", + "fixtures.tests.category_fixture", + "fixtures.tests.quotes_fixture", + "fixtures.tests.zodiac_fixture", + "fixtures.tests.jokes_fixture", + "fixtures.tests.comment_fixture", + "smtpdfix", ] # When testing in a PostgreSQL environment please make sure that: @@ -31,21 +31,22 @@ if PSQL_ENVIRONMENT: SQLALCHEMY_TEST_DATABASE_URL = ( - "postgresql://postgres:1234" - "@localhost/postgres" - ) - test_engine = create_engine( - SQLALCHEMY_TEST_DATABASE_URL + "postgresql://postgres:1234" "@localhost/postgres" ) + test_engine = create_engine(SQLALCHEMY_TEST_DATABASE_URL) else: SQLALCHEMY_TEST_DATABASE_URL = "sqlite:///./test.db" test_engine = create_engine( - SQLALCHEMY_TEST_DATABASE_URL, connect_args={"check_same_thread": False} + SQLALCHEMY_TEST_DATABASE_URL, + connect_args={"check_same_thread": False}, ) TestingSessionLocal = sessionmaker( - autocommit=False, autoflush=False, bind=test_engine) + autocommit=False, + autoflush=False, + bind=test_engine, +) def get_test_db(): @@ -66,11 +67,15 @@ def session(): def sqlite_engine(): SQLALCHEMY_TEST_DATABASE_URL = "sqlite:///./test.db" sqlite_test_engine = create_engine( - SQLALCHEMY_TEST_DATABASE_URL, connect_args={"check_same_thread": False} + SQLALCHEMY_TEST_DATABASE_URL, + connect_args={"check_same_thread": False}, ) TestingSession = sessionmaker( - autocommit=False, autoflush=False, bind=sqlite_test_engine) + autocommit=False, + autoflush=False, + bind=sqlite_test_engine, + ) yield sqlite_test_engine session = TestingSession() diff --git a/tests/association_fixture.py b/tests/fixtures/association_fixture.py similarity index 71% rename from tests/association_fixture.py rename to tests/fixtures/association_fixture.py index 92c845c2..f56d3e57 100644 --- a/tests/association_fixture.py +++ b/tests/fixtures/association_fixture.py @@ -7,6 +7,5 @@ @pytest.fixture def association(event: Event, session: Session) -> UserEvent: return ( - session.query(UserEvent) - .filter(UserEvent.event_id == event.id) + session.query(UserEvent).filter(UserEvent.event_id == event.id) ).first() diff --git a/tests/asyncio_fixture.py b/tests/fixtures/asyncio_fixture.py similarity index 90% rename from tests/asyncio_fixture.py rename to tests/fixtures/asyncio_fixture.py index db6645c5..6493f879 100644 --- a/tests/asyncio_fixture.py +++ b/tests/fixtures/asyncio_fixture.py @@ -32,22 +32,22 @@ def fake_user_events(session): session.commit() create_event( db=session, - title='Cool today event', + title="Cool today event", start=today_date, end=today_date + timedelta(days=2), all_day=False, - content='test event', + content="test event", owner_id=user.id, location="Here", is_google_event=False, ) create_event( db=session, - title='Cool (somewhen in two days) event', + title="Cool (somewhen in two days) event", start=today_date + timedelta(days=1), end=today_date + timedelta(days=3), all_day=False, - content='this week test event', + content="this week test event", owner_id=user.id, location="Here", is_google_event=False, diff --git a/tests/category_fixture.py b/tests/fixtures/category_fixture.py similarity index 64% rename from tests/category_fixture.py rename to tests/fixtures/category_fixture.py index 469b3593..fcca9680 100644 --- a/tests/category_fixture.py +++ b/tests/fixtures/category_fixture.py @@ -6,8 +6,12 @@ @pytest.fixture def category(session: Session, sender: User) -> Category: - category = Category.create(session, name="Guitar Lesson", color="121212", - user_id=sender.id) + category = Category.create( + session, + name="Guitar Lesson", + color="121212", + user_id=sender.id, + ) yield category session.delete(category) session.commit() diff --git a/tests/client_fixture.py b/tests/fixtures/client_fixture.py similarity index 100% rename from tests/client_fixture.py rename to tests/fixtures/client_fixture.py diff --git a/tests/comment_fixture.py b/tests/fixtures/comment_fixture.py similarity index 79% rename from tests/comment_fixture.py rename to tests/fixtures/comment_fixture.py index 5c0a3671..651f01f9 100644 --- a/tests/comment_fixture.py +++ b/tests/fixtures/comment_fixture.py @@ -11,10 +11,10 @@ @pytest.fixture def comment(session: Session, event: Event, user: User) -> Iterator[Comment]: data = { - 'user': user, - 'event': event, - 'content': 'test comment', - 'time': datetime(2021, 1, 1, 0, 1), + "user": user, + "event": event, + "content": "test comment", + "time": datetime(2021, 1, 1, 0, 1), } create_model(session, Comment, **data) comment = session.query(Comment).first() diff --git a/tests/dayview_fixture.py b/tests/fixtures/dayview_fixture.py similarity index 54% rename from tests/dayview_fixture.py rename to tests/fixtures/dayview_fixture.py index 769651a3..10087e9c 100644 --- a/tests/dayview_fixture.py +++ b/tests/fixtures/dayview_fixture.py @@ -9,63 +9,106 @@ def event1(): start = datetime(year=2021, month=2, day=1, hour=7, minute=5) end = datetime(year=2021, month=2, day=1, hour=9, minute=15) - return Event(title='test1', content='test', - start=start, end=end, owner_id=1) + return Event( + title="test1", + content="test", + start=start, + end=end, + owner_id=1, + ) @pytest.fixture def event2(): start = datetime(year=2021, month=2, day=1, hour=13, minute=13) end = datetime(year=2021, month=2, day=1, hour=15, minute=46) - return Event(title='test2', content='test', - start=start, end=end, owner_id=1, color='blue') + return Event( + title="test2", + content="test", + start=start, + end=end, + owner_id=1, + color="blue", + ) @pytest.fixture def event3(): start = datetime(year=2021, month=2, day=3, hour=7, minute=5) end = datetime(year=2021, month=2, day=3, hour=9, minute=15) - return Event(title='test3', content='test', - start=start, end=end, owner_id=1) + return Event( + title="test3", + content="test", + start=start, + end=end, + owner_id=1, + ) @pytest.fixture def all_day_event1(): start = datetime(year=2021, month=2, day=3, hour=7, minute=5) end = datetime(year=2021, month=2, day=3, hour=9, minute=15) - return Event(title='test3', content='test', all_day=True, - start=start, end=end, owner_id=1) + return Event( + title="test3", + content="test", + all_day=True, + start=start, + end=end, + owner_id=1, + ) @pytest.fixture def small_event(): start = datetime(year=2021, month=2, day=3, hour=7) end = datetime(year=2021, month=2, day=3, hour=8, minute=30) - return Event(title='test3', content='test', - start=start, end=end, owner_id=1) + return Event( + title="test3", + content="test", + start=start, + end=end, + owner_id=1, + ) @pytest.fixture def event_with_no_minutes_modified(): start = datetime(year=2021, month=2, day=3, hour=7) end = datetime(year=2021, month=2, day=3, hour=8) - return Event(title='test_no_modify', content='test', - start=start, end=end, owner_id=1) + return Event( + title="test_no_modify", + content="test", + start=start, + end=end, + owner_id=1, + ) @pytest.fixture def multiday_event(): start = datetime(year=2021, month=2, day=1, hour=13) end = datetime(year=2021, month=2, day=3, hour=13) - return Event(title='test_multiday', content='test', - start=start, end=end, owner_id=1, color='blue') + return Event( + title="test_multiday", + content="test", + start=start, + end=end, + owner_id=1, + color="blue", + ) @pytest.fixture def weekdays(): return [ - 'Sunday', 'Monday', 'Tuesday', - 'Wednesday', 'Thursday', 'Friday', 'Saturday', + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", ] diff --git a/tests/event_fixture.py b/tests/fixtures/event_fixture.py similarity index 85% rename from tests/event_fixture.py rename to tests/fixtures/event_fixture.py index 989c41fb..ddbf91a0 100644 --- a/tests/event_fixture.py +++ b/tests/fixtures/event_fixture.py @@ -13,10 +13,10 @@ def event(sender: User, category: Category, session: Session) -> Event: return create_event( db=session, - title='event', + title="event", start=today_date, end=today_date, - content='test event', + content="test event", owner_id=sender.id, location="Some random location", vc_link=None, @@ -28,11 +28,11 @@ def event(sender: User, category: Category, session: Session) -> Event: def today_event(sender: User, session: Session) -> Event: return create_event( db=session, - title='event 1', + title="event 1", start=today_date + timedelta(hours=7), end=today_date + timedelta(hours=9), all_day=False, - content='test event', + content="test event", owner_id=sender.id, ) @@ -41,11 +41,11 @@ def today_event(sender: User, session: Session) -> Event: def today_event_2(sender: User, session: Session) -> Event: return create_event( db=session, - title='event 2', + title="event 2", start=today_date + timedelta(hours=3), end=today_date + timedelta(days=2, hours=3), all_day=False, - content='test event', + content="test event", owner_id=sender.id, ) @@ -54,11 +54,11 @@ def today_event_2(sender: User, session: Session) -> Event: def yesterday_event(sender: User, session: Session) -> Event: return create_event( db=session, - title='event 3', + title="event 3", start=today_date - timedelta(hours=8), end=today_date, all_day=False, - content='test event', + content="test event", owner_id=sender.id, ) @@ -67,11 +67,11 @@ def yesterday_event(sender: User, session: Session) -> Event: def next_week_event(sender: User, session: Session) -> Event: return create_event( db=session, - title='event 4', + title="event 4", start=today_date + timedelta(days=7, hours=2), end=today_date + timedelta(days=7, hours=4), all_day=False, - content='test event', + content="test event", owner_id=sender.id, ) @@ -80,11 +80,11 @@ def next_week_event(sender: User, session: Session) -> Event: def next_month_event(sender: User, session: Session) -> Event: return create_event( db=session, - title='event 5', + title="event 5", start=today_date + timedelta(days=20, hours=4), end=today_date + timedelta(days=20, hours=6), all_day=False, - content='test event', + content="test event", owner_id=sender.id, ) @@ -93,11 +93,11 @@ def next_month_event(sender: User, session: Session) -> Event: def old_event(sender: User, session: Session) -> Event: return create_event( db=session, - title='event 6', + title="event 6", start=today_date - timedelta(days=5), end=today_date - timedelta(days=1), all_day=False, - content='test event', + content="test event", owner_id=sender.id, ) @@ -106,11 +106,11 @@ def old_event(sender: User, session: Session) -> Event: def all_day_event(sender: User, category: Category, session: Session) -> Event: return create_event( db=session, - title='event', + title="event", start=today_date, end=today_date, all_day=True, - content='test event', + content="test event", owner_id=sender.id, location="Some random location", category_id=category.id, diff --git a/tests/invitation_fixture.py b/tests/fixtures/invitation_fixture.py similarity index 89% rename from tests/invitation_fixture.py rename to tests/fixtures/invitation_fixture.py index 7a37715b..aeafd201 100644 --- a/tests/invitation_fixture.py +++ b/tests/fixtures/invitation_fixture.py @@ -10,7 +10,9 @@ @pytest.fixture def invitation( - event: Event, user: User, session: Session + event: Event, + user: User, + session: Session, ) -> Generator[Invitation, None, None]: """Returns an Invitation object after being created in the database. @@ -23,7 +25,8 @@ def invitation( An Invitation object. """ invitation = create_model( - session, Invitation, + session, + Invitation, creation=datetime.now(), recipient=user, event=event, diff --git a/tests/jokes_fixture.py b/tests/fixtures/jokes_fixture.py similarity index 89% rename from tests/jokes_fixture.py rename to tests/fixtures/jokes_fixture.py index d7e3258c..062d5d45 100644 --- a/tests/jokes_fixture.py +++ b/tests/fixtures/jokes_fixture.py @@ -16,5 +16,5 @@ def joke(session: Session) -> Joke: yield from add_joke( session=session, id_joke=1, - text='Chuck Norris can slam a revolving door.', + text="Chuck Norris can slam a revolving door.", ) diff --git a/tests/logger_fixture.py b/tests/fixtures/logger_fixture.py similarity index 56% rename from tests/logger_fixture.py rename to tests/fixtures/logger_fixture.py index f6102f80..bbae8ebc 100644 --- a/tests/logger_fixture.py +++ b/tests/fixtures/logger_fixture.py @@ -8,14 +8,16 @@ from app.internal.logger_customizer import LoggerCustomizer -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def logger_instance(): - _logger = LoggerCustomizer.make_logger(config.LOG_PATH, - config.LOG_FILENAME, - config.LOG_LEVEL, - config.LOG_ROTATION_INTERVAL, - config.LOG_RETENTION_INTERVAL, - config.LOG_FORMAT) + _logger = LoggerCustomizer.make_logger( + config.LOG_PATH, + config.LOG_FILENAME, + config.LOG_LEVEL, + config.LOG_ROTATION_INTERVAL, + config.LOG_RETENTION_INTERVAL, + config.LOG_FORMAT, + ) return _logger diff --git a/tests/quotes_fixture.py b/tests/fixtures/quotes_fixture.py similarity index 74% rename from tests/quotes_fixture.py rename to tests/fixtures/quotes_fixture.py index 3f9d4e80..ef7c0bbd 100644 --- a/tests/quotes_fixture.py +++ b/tests/fixtures/quotes_fixture.py @@ -6,7 +6,10 @@ def add_quote( - session: Session, id_quote: int, text: str, author: str + session: Session, + id_quote: int, + text: str, + author: str, ) -> Quote: quote = create_model( session, @@ -24,8 +27,8 @@ def quote1(session: Session) -> Quote: yield from add_quote( session=session, id_quote=1, - text='You have to believe in yourself.', - author='Sun Tzu', + text="You have to believe in yourself.", + author="Sun Tzu", ) @@ -34,6 +37,6 @@ def quote2(session: Session) -> Quote: yield from add_quote( session=session, id_quote=2, - text='Wisdom begins in wonder.', - author='Socrates', + text="Wisdom begins in wonder.", + author="Socrates", ) diff --git a/tests/user_fixture.py b/tests/fixtures/user_fixture.py similarity index 88% rename from tests/user_fixture.py rename to tests/fixtures/user_fixture.py index a8b30056..6674ed50 100644 --- a/tests/user_fixture.py +++ b/tests/fixtures/user_fixture.py @@ -25,10 +25,11 @@ def user(session: Session) -> Generator[User, None, None]: @pytest.fixture def user2(session: Session) -> Generator[User, None, None]: mock_user = create_model( - session, User, - username='test_username2', - password='test_password2', - email='test2.email@gmail.com', + session, + User, + username="test_username2", + password="test_password2", + email="test2.email@gmail.com", language_id=1, ) yield mock_user diff --git a/tests/weekly_tasks_fixture.py b/tests/fixtures/weekly_tasks_fixture.py similarity index 100% rename from tests/weekly_tasks_fixture.py rename to tests/fixtures/weekly_tasks_fixture.py diff --git a/tests/zodiac_fixture.py b/tests/fixtures/zodiac_fixture.py similarity index 92% rename from tests/zodiac_fixture.py rename to tests/fixtures/zodiac_fixture.py index f5ebee5e..fab6e784 100644 --- a/tests/zodiac_fixture.py +++ b/tests/fixtures/zodiac_fixture.py @@ -8,7 +8,8 @@ @pytest.fixture def zodiac_sign(session: Session) -> Zodiac: zodiac = create_model( - session, Zodiac, + session, + Zodiac, name="aries", start_month=3, start_day_in_month=20, From 487fd663d0854b91b496220c9dd49fdb524c0dc4 Mon Sep 17 00:00:00 2001 From: itzik Date: Wed, 24 Feb 2021 21:33:06 +0200 Subject: [PATCH 32/32] Revert "Arranging files" This reverts commit dab05ee0b9dbb5c452679da68bfb08140d53534f. --- tests/{fixtures => }/association_fixture.py | 3 +- tests/{fixtures => }/asyncio_fixture.py | 8 +-- tests/{fixtures => }/category_fixture.py | 8 +-- tests/{fixtures => }/client_fixture.py | 0 tests/{fixtures => }/comment_fixture.py | 8 +-- tests/conftest.py | 53 +++++++------- tests/{fixtures => }/dayview_fixture.py | 75 +++++--------------- tests/{fixtures => }/event_fixture.py | 32 ++++----- tests/{fixtures => }/invitation_fixture.py | 7 +- tests/{fixtures => }/jokes_fixture.py | 2 +- tests/{fixtures => }/logger_fixture.py | 16 ++--- tests/{fixtures => }/quotes_fixture.py | 13 ++-- tests/{fixtures => }/user_fixture.py | 9 ++- tests/{fixtures => }/weekly_tasks_fixture.py | 0 tests/{fixtures => }/zodiac_fixture.py | 3 +- 15 files changed, 88 insertions(+), 149 deletions(-) rename tests/{fixtures => }/association_fixture.py (71%) rename tests/{fixtures => }/asyncio_fixture.py (90%) rename tests/{fixtures => }/category_fixture.py (64%) rename tests/{fixtures => }/client_fixture.py (100%) rename tests/{fixtures => }/comment_fixture.py (79%) rename tests/{fixtures => }/dayview_fixture.py (54%) rename tests/{fixtures => }/event_fixture.py (85%) rename tests/{fixtures => }/invitation_fixture.py (89%) rename tests/{fixtures => }/jokes_fixture.py (89%) rename tests/{fixtures => }/logger_fixture.py (56%) rename tests/{fixtures => }/quotes_fixture.py (74%) rename tests/{fixtures => }/user_fixture.py (88%) rename tests/{fixtures => }/weekly_tasks_fixture.py (100%) rename tests/{fixtures => }/zodiac_fixture.py (92%) diff --git a/tests/fixtures/association_fixture.py b/tests/association_fixture.py similarity index 71% rename from tests/fixtures/association_fixture.py rename to tests/association_fixture.py index f56d3e57..92c845c2 100644 --- a/tests/fixtures/association_fixture.py +++ b/tests/association_fixture.py @@ -7,5 +7,6 @@ @pytest.fixture def association(event: Event, session: Session) -> UserEvent: return ( - session.query(UserEvent).filter(UserEvent.event_id == event.id) + session.query(UserEvent) + .filter(UserEvent.event_id == event.id) ).first() diff --git a/tests/fixtures/asyncio_fixture.py b/tests/asyncio_fixture.py similarity index 90% rename from tests/fixtures/asyncio_fixture.py rename to tests/asyncio_fixture.py index 6493f879..db6645c5 100644 --- a/tests/fixtures/asyncio_fixture.py +++ b/tests/asyncio_fixture.py @@ -32,22 +32,22 @@ def fake_user_events(session): session.commit() create_event( db=session, - title="Cool today event", + title='Cool today event', start=today_date, end=today_date + timedelta(days=2), all_day=False, - content="test event", + content='test event', owner_id=user.id, location="Here", is_google_event=False, ) create_event( db=session, - title="Cool (somewhen in two days) event", + title='Cool (somewhen in two days) event', start=today_date + timedelta(days=1), end=today_date + timedelta(days=3), all_day=False, - content="this week test event", + content='this week test event', owner_id=user.id, location="Here", is_google_event=False, diff --git a/tests/fixtures/category_fixture.py b/tests/category_fixture.py similarity index 64% rename from tests/fixtures/category_fixture.py rename to tests/category_fixture.py index fcca9680..469b3593 100644 --- a/tests/fixtures/category_fixture.py +++ b/tests/category_fixture.py @@ -6,12 +6,8 @@ @pytest.fixture def category(session: Session, sender: User) -> Category: - category = Category.create( - session, - name="Guitar Lesson", - color="121212", - user_id=sender.id, - ) + category = Category.create(session, name="Guitar Lesson", color="121212", + user_id=sender.id) yield category session.delete(category) session.commit() diff --git a/tests/fixtures/client_fixture.py b/tests/client_fixture.py similarity index 100% rename from tests/fixtures/client_fixture.py rename to tests/client_fixture.py diff --git a/tests/fixtures/comment_fixture.py b/tests/comment_fixture.py similarity index 79% rename from tests/fixtures/comment_fixture.py rename to tests/comment_fixture.py index 651f01f9..5c0a3671 100644 --- a/tests/fixtures/comment_fixture.py +++ b/tests/comment_fixture.py @@ -11,10 +11,10 @@ @pytest.fixture def comment(session: Session, event: Event, user: User) -> Iterator[Comment]: data = { - "user": user, - "event": event, - "content": "test comment", - "time": datetime(2021, 1, 1, 0, 1), + 'user': user, + 'event': event, + 'content': 'test comment', + 'time': datetime(2021, 1, 1, 0, 1), } create_model(session, Comment, **data) comment = session.query(Comment).first() diff --git a/tests/conftest.py b/tests/conftest.py index f5243885..500ede4a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,21 +8,21 @@ from app.database.models import Base pytest_plugins = [ - "fixtures.tests.user_fixture", - "fixtures.tests.event_fixture", - "fixtures.tests.dayview_fixture", - "fixtures.tests.invitation_fixture", - "fixtures.tests.association_fixture", - "fixtures.tests.client_fixture", - "fixtures.tests.weekly_tasks_fixture", - "fixtures.tests.asyncio_fixture", - "fixtures.tests.logger_fixture", - "fixtures.tests.category_fixture", - "fixtures.tests.quotes_fixture", - "fixtures.tests.zodiac_fixture", - "fixtures.tests.jokes_fixture", - "fixtures.tests.comment_fixture", - "smtpdfix", + 'tests.user_fixture', + 'tests.event_fixture', + 'tests.dayview_fixture', + 'tests.invitation_fixture', + 'tests.association_fixture', + 'tests.client_fixture', + 'tests.weekly_tasks_fixture', + 'tests.asyncio_fixture', + 'tests.logger_fixture', + 'tests.category_fixture', + 'smtpdfix', + 'tests.quotes_fixture', + 'tests.zodiac_fixture', + 'tests.jokes_fixture', + 'tests.comment_fixture', ] # When testing in a PostgreSQL environment please make sure that: @@ -31,22 +31,21 @@ if PSQL_ENVIRONMENT: SQLALCHEMY_TEST_DATABASE_URL = ( - "postgresql://postgres:1234" "@localhost/postgres" + "postgresql://postgres:1234" + "@localhost/postgres" + ) + test_engine = create_engine( + SQLALCHEMY_TEST_DATABASE_URL ) - test_engine = create_engine(SQLALCHEMY_TEST_DATABASE_URL) else: SQLALCHEMY_TEST_DATABASE_URL = "sqlite:///./test.db" test_engine = create_engine( - SQLALCHEMY_TEST_DATABASE_URL, - connect_args={"check_same_thread": False}, + SQLALCHEMY_TEST_DATABASE_URL, connect_args={"check_same_thread": False} ) TestingSessionLocal = sessionmaker( - autocommit=False, - autoflush=False, - bind=test_engine, -) + autocommit=False, autoflush=False, bind=test_engine) def get_test_db(): @@ -67,15 +66,11 @@ def session(): def sqlite_engine(): SQLALCHEMY_TEST_DATABASE_URL = "sqlite:///./test.db" sqlite_test_engine = create_engine( - SQLALCHEMY_TEST_DATABASE_URL, - connect_args={"check_same_thread": False}, + SQLALCHEMY_TEST_DATABASE_URL, connect_args={"check_same_thread": False} ) TestingSession = sessionmaker( - autocommit=False, - autoflush=False, - bind=sqlite_test_engine, - ) + autocommit=False, autoflush=False, bind=sqlite_test_engine) yield sqlite_test_engine session = TestingSession() diff --git a/tests/fixtures/dayview_fixture.py b/tests/dayview_fixture.py similarity index 54% rename from tests/fixtures/dayview_fixture.py rename to tests/dayview_fixture.py index 10087e9c..769651a3 100644 --- a/tests/fixtures/dayview_fixture.py +++ b/tests/dayview_fixture.py @@ -9,106 +9,63 @@ def event1(): start = datetime(year=2021, month=2, day=1, hour=7, minute=5) end = datetime(year=2021, month=2, day=1, hour=9, minute=15) - return Event( - title="test1", - content="test", - start=start, - end=end, - owner_id=1, - ) + return Event(title='test1', content='test', + start=start, end=end, owner_id=1) @pytest.fixture def event2(): start = datetime(year=2021, month=2, day=1, hour=13, minute=13) end = datetime(year=2021, month=2, day=1, hour=15, minute=46) - return Event( - title="test2", - content="test", - start=start, - end=end, - owner_id=1, - color="blue", - ) + return Event(title='test2', content='test', + start=start, end=end, owner_id=1, color='blue') @pytest.fixture def event3(): start = datetime(year=2021, month=2, day=3, hour=7, minute=5) end = datetime(year=2021, month=2, day=3, hour=9, minute=15) - return Event( - title="test3", - content="test", - start=start, - end=end, - owner_id=1, - ) + return Event(title='test3', content='test', + start=start, end=end, owner_id=1) @pytest.fixture def all_day_event1(): start = datetime(year=2021, month=2, day=3, hour=7, minute=5) end = datetime(year=2021, month=2, day=3, hour=9, minute=15) - return Event( - title="test3", - content="test", - all_day=True, - start=start, - end=end, - owner_id=1, - ) + return Event(title='test3', content='test', all_day=True, + start=start, end=end, owner_id=1) @pytest.fixture def small_event(): start = datetime(year=2021, month=2, day=3, hour=7) end = datetime(year=2021, month=2, day=3, hour=8, minute=30) - return Event( - title="test3", - content="test", - start=start, - end=end, - owner_id=1, - ) + return Event(title='test3', content='test', + start=start, end=end, owner_id=1) @pytest.fixture def event_with_no_minutes_modified(): start = datetime(year=2021, month=2, day=3, hour=7) end = datetime(year=2021, month=2, day=3, hour=8) - return Event( - title="test_no_modify", - content="test", - start=start, - end=end, - owner_id=1, - ) + return Event(title='test_no_modify', content='test', + start=start, end=end, owner_id=1) @pytest.fixture def multiday_event(): start = datetime(year=2021, month=2, day=1, hour=13) end = datetime(year=2021, month=2, day=3, hour=13) - return Event( - title="test_multiday", - content="test", - start=start, - end=end, - owner_id=1, - color="blue", - ) + return Event(title='test_multiday', content='test', + start=start, end=end, owner_id=1, color='blue') @pytest.fixture def weekdays(): return [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", + 'Sunday', 'Monday', 'Tuesday', + 'Wednesday', 'Thursday', 'Friday', 'Saturday', ] diff --git a/tests/fixtures/event_fixture.py b/tests/event_fixture.py similarity index 85% rename from tests/fixtures/event_fixture.py rename to tests/event_fixture.py index ddbf91a0..989c41fb 100644 --- a/tests/fixtures/event_fixture.py +++ b/tests/event_fixture.py @@ -13,10 +13,10 @@ def event(sender: User, category: Category, session: Session) -> Event: return create_event( db=session, - title="event", + title='event', start=today_date, end=today_date, - content="test event", + content='test event', owner_id=sender.id, location="Some random location", vc_link=None, @@ -28,11 +28,11 @@ def event(sender: User, category: Category, session: Session) -> Event: def today_event(sender: User, session: Session) -> Event: return create_event( db=session, - title="event 1", + title='event 1', start=today_date + timedelta(hours=7), end=today_date + timedelta(hours=9), all_day=False, - content="test event", + content='test event', owner_id=sender.id, ) @@ -41,11 +41,11 @@ def today_event(sender: User, session: Session) -> Event: def today_event_2(sender: User, session: Session) -> Event: return create_event( db=session, - title="event 2", + title='event 2', start=today_date + timedelta(hours=3), end=today_date + timedelta(days=2, hours=3), all_day=False, - content="test event", + content='test event', owner_id=sender.id, ) @@ -54,11 +54,11 @@ def today_event_2(sender: User, session: Session) -> Event: def yesterday_event(sender: User, session: Session) -> Event: return create_event( db=session, - title="event 3", + title='event 3', start=today_date - timedelta(hours=8), end=today_date, all_day=False, - content="test event", + content='test event', owner_id=sender.id, ) @@ -67,11 +67,11 @@ def yesterday_event(sender: User, session: Session) -> Event: def next_week_event(sender: User, session: Session) -> Event: return create_event( db=session, - title="event 4", + title='event 4', start=today_date + timedelta(days=7, hours=2), end=today_date + timedelta(days=7, hours=4), all_day=False, - content="test event", + content='test event', owner_id=sender.id, ) @@ -80,11 +80,11 @@ def next_week_event(sender: User, session: Session) -> Event: def next_month_event(sender: User, session: Session) -> Event: return create_event( db=session, - title="event 5", + title='event 5', start=today_date + timedelta(days=20, hours=4), end=today_date + timedelta(days=20, hours=6), all_day=False, - content="test event", + content='test event', owner_id=sender.id, ) @@ -93,11 +93,11 @@ def next_month_event(sender: User, session: Session) -> Event: def old_event(sender: User, session: Session) -> Event: return create_event( db=session, - title="event 6", + title='event 6', start=today_date - timedelta(days=5), end=today_date - timedelta(days=1), all_day=False, - content="test event", + content='test event', owner_id=sender.id, ) @@ -106,11 +106,11 @@ def old_event(sender: User, session: Session) -> Event: def all_day_event(sender: User, category: Category, session: Session) -> Event: return create_event( db=session, - title="event", + title='event', start=today_date, end=today_date, all_day=True, - content="test event", + content='test event', owner_id=sender.id, location="Some random location", category_id=category.id, diff --git a/tests/fixtures/invitation_fixture.py b/tests/invitation_fixture.py similarity index 89% rename from tests/fixtures/invitation_fixture.py rename to tests/invitation_fixture.py index aeafd201..7a37715b 100644 --- a/tests/fixtures/invitation_fixture.py +++ b/tests/invitation_fixture.py @@ -10,9 +10,7 @@ @pytest.fixture def invitation( - event: Event, - user: User, - session: Session, + event: Event, user: User, session: Session ) -> Generator[Invitation, None, None]: """Returns an Invitation object after being created in the database. @@ -25,8 +23,7 @@ def invitation( An Invitation object. """ invitation = create_model( - session, - Invitation, + session, Invitation, creation=datetime.now(), recipient=user, event=event, diff --git a/tests/fixtures/jokes_fixture.py b/tests/jokes_fixture.py similarity index 89% rename from tests/fixtures/jokes_fixture.py rename to tests/jokes_fixture.py index 062d5d45..d7e3258c 100644 --- a/tests/fixtures/jokes_fixture.py +++ b/tests/jokes_fixture.py @@ -16,5 +16,5 @@ def joke(session: Session) -> Joke: yield from add_joke( session=session, id_joke=1, - text="Chuck Norris can slam a revolving door.", + text='Chuck Norris can slam a revolving door.', ) diff --git a/tests/fixtures/logger_fixture.py b/tests/logger_fixture.py similarity index 56% rename from tests/fixtures/logger_fixture.py rename to tests/logger_fixture.py index bbae8ebc..f6102f80 100644 --- a/tests/fixtures/logger_fixture.py +++ b/tests/logger_fixture.py @@ -8,16 +8,14 @@ from app.internal.logger_customizer import LoggerCustomizer -@pytest.fixture(scope="module") +@pytest.fixture(scope='module') def logger_instance(): - _logger = LoggerCustomizer.make_logger( - config.LOG_PATH, - config.LOG_FILENAME, - config.LOG_LEVEL, - config.LOG_ROTATION_INTERVAL, - config.LOG_RETENTION_INTERVAL, - config.LOG_FORMAT, - ) + _logger = LoggerCustomizer.make_logger(config.LOG_PATH, + config.LOG_FILENAME, + config.LOG_LEVEL, + config.LOG_ROTATION_INTERVAL, + config.LOG_RETENTION_INTERVAL, + config.LOG_FORMAT) return _logger diff --git a/tests/fixtures/quotes_fixture.py b/tests/quotes_fixture.py similarity index 74% rename from tests/fixtures/quotes_fixture.py rename to tests/quotes_fixture.py index ef7c0bbd..3f9d4e80 100644 --- a/tests/fixtures/quotes_fixture.py +++ b/tests/quotes_fixture.py @@ -6,10 +6,7 @@ def add_quote( - session: Session, - id_quote: int, - text: str, - author: str, + session: Session, id_quote: int, text: str, author: str ) -> Quote: quote = create_model( session, @@ -27,8 +24,8 @@ def quote1(session: Session) -> Quote: yield from add_quote( session=session, id_quote=1, - text="You have to believe in yourself.", - author="Sun Tzu", + text='You have to believe in yourself.', + author='Sun Tzu', ) @@ -37,6 +34,6 @@ def quote2(session: Session) -> Quote: yield from add_quote( session=session, id_quote=2, - text="Wisdom begins in wonder.", - author="Socrates", + text='Wisdom begins in wonder.', + author='Socrates', ) diff --git a/tests/fixtures/user_fixture.py b/tests/user_fixture.py similarity index 88% rename from tests/fixtures/user_fixture.py rename to tests/user_fixture.py index 6674ed50..a8b30056 100644 --- a/tests/fixtures/user_fixture.py +++ b/tests/user_fixture.py @@ -25,11 +25,10 @@ def user(session: Session) -> Generator[User, None, None]: @pytest.fixture def user2(session: Session) -> Generator[User, None, None]: mock_user = create_model( - session, - User, - username="test_username2", - password="test_password2", - email="test2.email@gmail.com", + session, User, + username='test_username2', + password='test_password2', + email='test2.email@gmail.com', language_id=1, ) yield mock_user diff --git a/tests/fixtures/weekly_tasks_fixture.py b/tests/weekly_tasks_fixture.py similarity index 100% rename from tests/fixtures/weekly_tasks_fixture.py rename to tests/weekly_tasks_fixture.py diff --git a/tests/fixtures/zodiac_fixture.py b/tests/zodiac_fixture.py similarity index 92% rename from tests/fixtures/zodiac_fixture.py rename to tests/zodiac_fixture.py index fab6e784..f5ebee5e 100644 --- a/tests/fixtures/zodiac_fixture.py +++ b/tests/zodiac_fixture.py @@ -8,8 +8,7 @@ @pytest.fixture def zodiac_sign(session: Session) -> Zodiac: zodiac = create_model( - session, - Zodiac, + session, Zodiac, name="aries", start_month=3, start_day_in_month=20,