Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug/wf1 post error #3023

Merged
merged 19 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion api/app/routers/morecast_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from app.utils.time import vancouver_tz
from typing import List
from datetime import date, datetime, time, timedelta, timezone
from fastapi import APIRouter, Response, Depends, status
from fastapi import APIRouter, Response, Depends, status, HTTPException
from app.auth import (auth_with_forecaster_role_required,
audit,
authentication_required)
Expand Down Expand Up @@ -107,6 +107,7 @@
await post_forecasts(client_session, token=forecasts.token, forecasts=wf1_forecast_records)
except Exception as exc:
logger.error('Encountered error posting forecast data to WF1 API', exc_info=exc)
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Error submitting forecast(s) to WF1')

Check warning on line 110 in api/app/routers/morecast_v2.py

View check run for this annotation

Codecov / codecov/patch

api/app/routers/morecast_v2.py#L110

Added line #L110 was not covered by tests

with get_write_session_scope() as db_session:
save_all_forecasts(db_session, forecasts_to_save)
Expand Down
12 changes: 9 additions & 3 deletions api/app/tests/morecast_v2/test_morecast_v2_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def test_post_forecast_unauthorized(client: TestClient):
assert response.status_code == 401


@pytest.mark.anyio
def test_post_forecast_authorized(client: TestClient,
monkeypatch: pytest.MonkeyPatch):
""" Allowed to post station changes with correct role"""
Expand All @@ -77,10 +78,15 @@ def mock_admin_role_function(*_, **__):

monkeypatch.setattr(decode_fn, mock_admin_role_function)

# Create a mock function
def mock_function(): return None
async def mock_format_as_wf1_post_forecasts(client_session, forecasts_to_save):
return []

monkeypatch.setattr(app.routers.morecast_v2, 'format_as_wf1_post_forecasts', mock_format_as_wf1_post_forecasts)

async def mock_post_forecasts(client_session, token, forecasts):
return None

monkeypatch.setattr(app.routers.morecast_v2, 'post_forecasts', mock_function)
monkeypatch.setattr(app.routers.morecast_v2, 'post_forecasts', mock_post_forecasts)

response = client.post(morecast_v2_post_url, json=forecast.dict())
assert response.status_code == 201
Expand Down
13 changes: 13 additions & 0 deletions api/app/tests/wildfire_one/test_wildfire_one.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
""" Unit testing for WFWX API code """
import asyncio
from unittest.mock import patch, AsyncMock
import pytest
from fastapi import HTTPException
from pytest_mock import MockFixture

from app.wildfire_one.query_builders import (BuildQueryAllForecastsByAfterStart,
BuildQueryAllHourliesByRange,
BuildQueryDailiesByStationCode,
BuildQueryStationGroups)
from app.wildfire_one.wfwx_api import (WFWXWeatherStation,
get_wfwx_stations_from_station_codes)
from app.wildfire_one.wfwx_post_api import post_forecasts


def test_build_all_hourlies_query():
Expand Down Expand Up @@ -110,3 +114,12 @@ async def run_test():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(run_test())


@pytest.mark.anyio
@patch('app.wildfire_one.wfwx_post_api.ClientSession')
async def test_wf1_post_failure(mock_client):
""" Verifies that posting to WF1 raises an exception upon failure """
mock_client.post.return_value.__aenter__.return_value = AsyncMock(status=400)
with pytest.raises(HTTPException):
await post_forecasts(mock_client, 'token', [])
dgboss marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 4 additions & 0 deletions api/app/wildfire_one/wfwx_post_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import logging
from typing import List
from aiohttp import ClientSession
from fastapi import status, HTTPException
from app import config
from app.schemas.morecast_v2 import WF1PostForecast

Expand All @@ -22,4 +23,7 @@ async def post_forecasts(session: ClientSession,

async with session.post(WF1_FORECAST_POST_URL, json=forecasts_json, headers=headers) as response:
response_json = await response.json()
if response.status != status.HTTP_201_CREATED:
logger.error(f'error submitting forecasts to wf1 {response_json}')
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Error submitting forecast(s) to WF1')
logger.info('submitted forecasts to wf1 %s.', response_json)
2 changes: 1 addition & 1 deletion web/src/api/moreCast2API.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('moreCast2API', () => {
buildMorecast2Forecast('1', 1, 'one', DateTime.fromObject({ year: 2021, month: 1, day: 1 })),
buildMorecast2Forecast('2', 2, 'two', DateTime.fromObject({ year: 2021, month: 1, day: 1 }))
])
expect(res).toBe(true)
expect(res).toEqual({ success: true })
})
it('should fetch weather indeterminates with no stations requested', async () => {
const res = await fetchWeatherIndeterminates(
Expand Down
8 changes: 4 additions & 4 deletions web/src/api/moreCast2API.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,19 +185,19 @@
export async function submitMoreCastForecastRecords(
token: string,
forecasts: MoreCast2ForecastRow[]
): Promise<boolean> {
): Promise<{ success: boolean; errorMessage?: string }> {
const forecastRecords = marshalMoreCast2ForecastRecords(forecasts)
const url = `/morecast-v2/forecast`
try {
const { status } = await axios.post<MoreCastForecastRequest>(url, {
token,
forecasts: forecastRecords
})
return status === 201
return { success: status === 201 }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
console.error(error.message || error)
return false
console.error(error.response.data.detail || error)
return { success: false, errorMessage: error.response.data.detail }

Check warning on line 200 in web/src/api/moreCast2API.ts

View check run for this annotation

Codecov / codecov/patch

web/src/api/moreCast2API.ts#L200

Added line #L200 was not covered by tests
}
}

Expand Down
4 changes: 2 additions & 2 deletions web/src/features/moreCast2/components/TabbedDataGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -282,12 +282,12 @@ const TabbedDataGrid = ({ morecast2Rows, fromTo, setFromTo }: TabbedDataGridProp
if (isForecastValid(visibleRows) && !isUndefined(wf1Token)) {
const rowsToSave: MoreCast2ForecastRow[] = getRowsToSave(visibleRows)
const result = await submitMoreCastForecastRecords(wf1Token, rowsToSave)
if (result) {
if (result.success) {
setSnackbarMessage(FORECAST_SAVED_MESSAGE)
setSnackbarSeverity('success')
setSnackbarOpen(true)
} else {
setSnackbarMessage(FORECAST_ERROR_MESSAGE)
setSnackbarMessage(result.errorMessage ?? FORECAST_ERROR_MESSAGE)
setSnackbarSeverity('error')
setSnackbarOpen(true)
}
Expand Down
Loading