From e7286393bd8b937cf7eab1f679559e584f2eb841 Mon Sep 17 00:00:00 2001 From: Jerry Alania Date: Mon, 13 Apr 2026 16:04:42 -0600 Subject: [PATCH 1/4] Saving changes! --- .coverage | Bin 53248 -> 53248 bytes app/modules/jobs/routes.py | 13 +++--- app/tests/conftest.py | 5 +-- uv.lock | 81 +------------------------------------ 4 files changed, 10 insertions(+), 89 deletions(-) diff --git a/.coverage b/.coverage index b378fef9f1f5c60dce65d727559296ad4afa984e..168ba4574392ab37ebded9ee5462f562f6a7948e 100644 GIT binary patch literal 53248 zcmeI4Pi*8?9mnml#~zP8^Fp`FC>vGr1!bdVvP9LgY**Dbw2??@MN4)|cX!&UXXYj2 zGGk|LPj-WZ(3GOBdf|qk;>3Xihl&MpL%meuz@efN2Ts5N%3c5=QKYII_&xubKiQos zQY=-8zShh<|9S80-|zE&?>#>|&ejXhx)Hax{h;qe_G8kVB+Js1wk=7LN#6>6vqh&B zHQS(6o>-r?YD%kbJzQZgN|yGL#9pbKVRdWA`nUNL>&wPf)74juRXTtL1V8`;K;Xm> z7`|ZXwfTAZ_3uPZtH-0jY4afYtvvOOjrA)V_LcRoJiB2h`|Pu2o0fXrUbh4Pmc7dZ zd)w`C+x0qb+lgFn$Bw!@%RLBrM~qptk47z#aWyV4)|zgIN=1B!Bz6P0?*#kyxA^`_ zoFP41#BWE*4ie$+jwf>1XVc=#cEGoJz`ZsP6D!WTo#pcK_r6=!Yo|`hcX;fR6SV1L zPI*H+#;$B`lTh0aI>P!^;CSsW4_9nw~E3q4% zzhVm~C<4AH zMw>8}Y_MBBzcn3eam0k28VL0TS+?zg*A`7B6h5^5Jsvnad^J6qbPJz#AW`V78Cq>) zaaQPzLZG=eS}hOfHNCd5Air+JVU*TZn&?v@l-1+|y3y=VpF80o$U2fw>m;)h<6bgr zBk2)xr><+Y^@UmPr1_d_=}Kv+t9tG9X?d8m2+=QzZ*j^Av1i-_4h#f`H-FcOy7v9H zi```SQch#4|nKD`I8JqkyzF*&SdeocjI&MHs zmipji1h7TMjzgK9mOqH%_!XORc#5%SY;Phk-p<%luH`s8HSg#BFm!2H6~k8ec(&JG z>N=t5g~BDf<@-JEc*)p6B{oAkryJU_4fl^qm&Y36zR=j&TZ(PU1{cxIU!g{qwJ%!f z_Z_d3j#pwBPE@Jy7mZV#C+S3}puI$mGNdMYKr<6fkBS~E(_h^sCPKCEbdu&SDrG|P zR+rx=myAYFI}wlEKDR}d*qAu5ZaJad4mcf5$I{p^BGx@R8?vC#8Zzqu7>pDa)bVvMHn^c#oMO?caPh3+YJY+yfbKQdQsqSeRHGn zjNhtnaeDQ-TVH>Ev*GOSHu`>N(BomF%bi}-Z8V#%=SIyYz1V!cLh2WDRS)Q;avln8 zD?jZpa-y(71oqrEC+%w{XQ@g7-BeKf7P^Ta!p$Dv|X0eC&>; zM?|jcq?}Wb#L5#u8X9Tm6yA>K^!C5aC&J`Lk<@dl%S?TQhMyo(vx$X9PK_Z|2M9w!}B@WJw5*~5?R$xp~C%NQDu|)f8jZGxM&=$YnreO|Njre z9SDE`2!H?xfB*=900@8p2!H?xoM-}ytVk8{{9k7Oljws51V8`;KmY_l00ck)1V8`; zKmY_l-~KZB%id+bW;-KmY_l00ck) z1V8`;KmY_l00eR*U|FhcoUzIu@4w&sP$`+T^^o~9ZBr}LTD2@22Bi-h?|=UX^LmL^ z=Sp8vG+i9iWlN*M%}l{H1Aid-sC`cUCd`$|z(4Wn8R z&;KpJA;|6%`NAJQFwKe7+l@7R0nH*^=^og5v66bOI-2!H?xfB*=900@8p2!H?x zfWV;$h-toT#j}0cG~=yuIZg~CPD-UX(e*gdv^Xgi<3v^CL{Z|TP*CXxK>Yk)nmg3V zkqHDq00ck)1V8`;KmY_l00ck)1VG@J5)jY-G5&@P9ir?pOc- delta 409 zcmZozz}&Ead4e<}=R_H2M$U~1OYFIr`6U_nH}R+OOKuhv;O1BKW@ce%ly~M4 Date: Mon, 13 Apr 2026 17:12:45 -0600 Subject: [PATCH 2/4] conftest.py and test_jobs.py --- app/tests/conftest.py | 33 ++++++++++++++++++++++++++++++++- app/tests/test_jobs.py | 16 +++++++++++++--- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/app/tests/conftest.py b/app/tests/conftest.py index 5587c3b..bf73d49 100644 --- a/app/tests/conftest.py +++ b/app/tests/conftest.py @@ -1,7 +1,38 @@ """Pytest configuration and shared fixtures.""" import pytest -from unittest.mock import AsyncMock, patch +from unittest.mock import AsyncMock, Mock, patch @pytest.fixture def mock_adzuna_response(): + #mock data for Adzuna to return + mock_payload = { + "results": [ + { + "id": "12345", + "title": "Software Engineer", + "company": {"display_name": "Apple Inc."}, + "location": {"display_name": "Cupertino, CA"}, + "description": "We are looking for a Software Engineer to join our team.", + "redirect_url": "https://www.apple.com", + } + ] + } + + # mock HTTP response + mock_response = Mock(status_code=200) + mock_response.json.return_value = mock_payload + + # mock AsyncClient + mock_client = AsyncMock() + mock_client.get = AsyncMock(return_value=mock_response) + + # patch the client and credientials globally for all tests + with ( + patch("job_search_app.job_search.AdzunaJobSearch.app_id", "test_app_id"), + patch("job_search_app.job_search.AdzunaJobSearch.app_key", "test_app_key"), + patch("app.modules.jobs.service.httpx.AsyncClient") as mock_async_client + ): + # set the mock client to be returned whenever AsyncClient is instantiated + mock_async_client.return_value.__aenter__.return_value = mock_client + yield mock_client \ No newline at end of file diff --git a/app/tests/test_jobs.py b/app/tests/test_jobs.py index 5c08ae2..133747d 100644 --- a/app/tests/test_jobs.py +++ b/app/tests/test_jobs.py @@ -13,14 +13,24 @@ client = TestClient(app) -def test_jobs_endpoint_success(): +def test_jobs_endpoint_success(mock_adzuna_response): """Returns the expected payload for a valid jobs query.""" response = client.get("/jobs", params={"q": "python"}) assert response.status_code == 200 + assert response.json() == { - "message": "Yay! Jobs endpoint is working", - "query": "python", + "total_found": 1, + "jobs": [ + { + "id": "123", + "title": "Python Developer", + "company": "IBM", + "location": "Remote", + "description": "Build APIs", + "url": "https://example.com/job-123" + } + ] } From 1f893243a654e23aa28ab9d4fde96ff3145344e3 Mon Sep 17 00:00:00 2001 From: Jerry Alania Date: Mon, 13 Apr 2026 17:48:12 -0600 Subject: [PATCH 3/4] fix pytest errors --- .coverage | Bin 53248 -> 53248 bytes app/modules/stats/routes.py | 2 +- app/tests/conftest.py | 4 ++-- app/tests/test_jobs.py | 12 ++++++------ app/tests/test_stats_integration.py | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.coverage b/.coverage index 168ba4574392ab37ebded9ee5462f562f6a7948e..8000f35a2ee6d8a2d02865671127e420e7637029 100644 GIT binary patch delta 79 zcmV-V0I>gnpaX!Q1F!~w8i)W7`48_8=MUcx)DOlFz7Mqzs1KkImJf)t5fEq(lZuZZ l77Gak0SOoh&P9C8@}CC?1OW*U2x<2tZ|h8&UuO delta 77 zcmZozz}&Eac>`O6R2KvPPyYA(&-w53U*SK-zmI<_|0@1P{4@BwHVX=5@lWpPR}kUk hWMSkK;XK#cFUigUWD0PYF;CvtZ^>A>`A0v80{{_07~}u| diff --git a/app/modules/stats/routes.py b/app/modules/stats/routes.py index 3034e29..8632c3f 100644 --- a/app/modules/stats/routes.py +++ b/app/modules/stats/routes.py @@ -6,7 +6,7 @@ router = APIRouter() -@router.get("/stats") +@router.get("/") async def get_stats(q: str = "python"): """ Fetches live job data from Adzuna and calculates market statistics. diff --git a/app/tests/conftest.py b/app/tests/conftest.py index bf73d49..d265df1 100644 --- a/app/tests/conftest.py +++ b/app/tests/conftest.py @@ -29,8 +29,8 @@ def mock_adzuna_response(): # patch the client and credientials globally for all tests with ( - patch("job_search_app.job_search.AdzunaJobSearch.app_id", "test_app_id"), - patch("job_search_app.job_search.AdzunaJobSearch.app_key", "test_app_key"), + patch("app.modules.jobs.service.ADZUNA_APP_ID", "test_app_id"), + patch("app.modules.jobs.service.ADZUNA_APP_KEY", "test_app_key"), patch("app.modules.jobs.service.httpx.AsyncClient") as mock_async_client ): # set the mock client to be returned whenever AsyncClient is instantiated diff --git a/app/tests/test_jobs.py b/app/tests/test_jobs.py index 133747d..dee271b 100644 --- a/app/tests/test_jobs.py +++ b/app/tests/test_jobs.py @@ -23,12 +23,12 @@ def test_jobs_endpoint_success(mock_adzuna_response): "total_found": 1, "jobs": [ { - "id": "123", - "title": "Python Developer", - "company": "IBM", - "location": "Remote", - "description": "Build APIs", - "url": "https://example.com/job-123" + "id": "12345", + "title": "Software Engineer", + "company": "Apple Inc.", + "location": "Cupertino, CA", + "description": "We are looking for a Software Engineer to join our team.", + "url": "https://www.apple.com" } ] } diff --git a/app/tests/test_stats_integration.py b/app/tests/test_stats_integration.py index dff24f6..a51a2c0 100644 --- a/app/tests/test_stats_integration.py +++ b/app/tests/test_stats_integration.py @@ -4,7 +4,7 @@ # Create a fake web browser to test your app client = TestClient(app) -def test_stats_endpoint_success(): +def test_stats_endpoint_success(mock_adzuna_response): # 1. ACT: Send a fake GET request to the stats route response = client.get("/stats") From ef39041266877d72c22a909162bba1f18418310e Mon Sep 17 00:00:00 2001 From: Jerry Alania Date: Fri, 24 Apr 2026 09:21:17 -0600 Subject: [PATCH 4/4] Fix remaining week 3 tests --- app/tests/.coverage | Bin 0 -> 53248 bytes app/tests/test_jobs.py | 4 ++-- app/tests/test_stats_integration.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 app/tests/.coverage diff --git a/app/tests/.coverage b/app/tests/.coverage new file mode 100644 index 0000000000000000000000000000000000000000..d7c88e6ea557645913b14c76499da0f3645e4e18 GIT binary patch literal 53248 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 literal 0 HcmV?d00001 diff --git a/app/tests/test_jobs.py b/app/tests/test_jobs.py index 9c13d92..0293281 100644 --- a/app/tests/test_jobs.py +++ b/app/tests/test_jobs.py @@ -15,8 +15,8 @@ def test_jobs_endpoint_success(): mocked_jobs = { "total_found": 2, "jobs": [ - {"id": "job-1", "title": "Python Developer", "company": "TechFlow", "location": "Remote"}, - {"id": "job-2", "title": "Backend Engineer", "company": "DataWorks", "location": "New York"}, + {"id": "job-1", "title": "Python Developer", "company": "Apple Inc.", "location": "Cupertino, CA"}, + {"id": "job-2", "title": "Backend Engineer", "company": "DataWorks", "location": "New York, NY"}, ], } diff --git a/app/tests/test_stats_integration.py b/app/tests/test_stats_integration.py index 253b6be..5a397fd 100644 --- a/app/tests/test_stats_integration.py +++ b/app/tests/test_stats_integration.py @@ -14,8 +14,8 @@ } @patch("app.modules.stats.routes.fetch_jobs_from_adzuna") -def test_stats_endpoint_success(mock_fetch): - mock_fetch.return_value = MOCK_ADZUNA_DATA +def test_stats_endpoint_success(mock_adzuna_response): + mock_adzuna_response.return_value = MOCK_ADZUNA_DATA response = client.get("/stats?q=python")