623 lines
25 KiB
Python
623 lines
25 KiB
Python
# Passerelle - uniform access to data and services
|
|
# Copyright (C) 2021 Entr'ouvert
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify it
|
|
# under the terms of the GNU Affero General Public License as published
|
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; exclude even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a.deepcopy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
from unittest import mock
|
|
|
|
import pytest
|
|
from django.urls import reverse
|
|
|
|
import tests.utils
|
|
from passerelle.contrib.isere_ens.models import API_VERSION, IsereENS
|
|
|
|
|
|
@pytest.fixture
|
|
def setup(db):
|
|
return tests.utils.setup_access_rights(
|
|
IsereENS.objects.create(slug="test", base_url="https://ens38.example.net/", token="toktok")
|
|
)
|
|
|
|
|
|
SITES_RESPONSE = """[
|
|
{
|
|
"name": "Save - étangs de la Serre",
|
|
"code": "SD29a",
|
|
"city": "Arandon-Passins - Courtenay",
|
|
"school_group": true,
|
|
"social": true
|
|
},
|
|
{
|
|
"name": "Save - étangs de Passins",
|
|
"code": "SD29b",
|
|
"city": "Arandon-Passins",
|
|
"school_group": true,
|
|
"social": true
|
|
},
|
|
{
|
|
"name": "Save - lac de Save",
|
|
"code": "SD29c",
|
|
"city": "Arandon-Passins",
|
|
"school_group": true,
|
|
"social": false
|
|
}
|
|
]"""
|
|
|
|
SD29B_RESPONSE = """{
|
|
"name": "Save - étangs de Passins",
|
|
"code": "SD29b",
|
|
"type": "DEPARTMENTAL_ENS",
|
|
"city": "Arandon-Passins",
|
|
"natural_environment": "Etangs, tourbières, mares, forêts, rivière, pelouses sèches",
|
|
"lunch_equipment": null,
|
|
"pmr_access": "NO",
|
|
"school_group": true,
|
|
"social": true,
|
|
"user_informations": "<p>Un album jeunesse a été réalisé sur l'ENS de la Save. Il permet aux enfants de s'approprier le site en amont d'une sortie.</p>",
|
|
"dogs": "LEASH",
|
|
"educational_equipments": null,
|
|
"eps_regulation": null,
|
|
"main_manager": {
|
|
"first_name": "Jo",
|
|
"last_name": "Smith",
|
|
"managing_entity": "Département de l'Isère",
|
|
"main_phone": "01 23 45 67 89",
|
|
"email": "jo.smith@example.net"
|
|
}
|
|
}"""
|
|
|
|
SITE_404_RESPONSE = """{
|
|
"user_message": "Impossible de trouver le site",
|
|
"message": "Site not found with code SD29x"
|
|
}"""
|
|
|
|
ANIMATORS_RESPONSE = """[
|
|
{
|
|
"id": 1,
|
|
"first_name": "Francis",
|
|
"last_name": "Kuntz",
|
|
"email": "fk@mail.grd",
|
|
"phone": "123",
|
|
"entity": "Association Nature Morte"
|
|
},
|
|
{
|
|
"id": 2,
|
|
"first_name": "Michael",
|
|
"last_name": "Kael",
|
|
"email": "mk@mail.grd",
|
|
"phone": "456",
|
|
"entity": "Association Porte de l'Enfer"
|
|
}
|
|
]"""
|
|
|
|
SITE_CALENDAR_RESPONSE = """[
|
|
{
|
|
"date": "2020-01-21",
|
|
"morning": "AVAILABLE",
|
|
"lunch": "CLOSE",
|
|
"afternoon": "AVAILABLE"
|
|
},
|
|
{
|
|
"date": "2020-01-22",
|
|
"morning": "AVAILABLE",
|
|
"lunch": "OPEN",
|
|
"afternoon": "COMPLETE"
|
|
},
|
|
{
|
|
"date": "2020-01-23",
|
|
"morning": "COMPLETE",
|
|
"lunch": "CLOSE",
|
|
"afternoon": "COMPLETE"
|
|
}
|
|
]"""
|
|
|
|
BOOK_RESPONSE = """{
|
|
"status": "BOOKING"
|
|
}"""
|
|
BOOK_RESPONSE_OVERBOOKING = """{
|
|
"status": "OVERBOOKING"
|
|
}"""
|
|
BOOK_RESPONSE_REFUSED = """{
|
|
"status": "REFUSED"
|
|
}"""
|
|
CANCEL_RESPONSE = """{
|
|
"status": "CANCELED"
|
|
}"""
|
|
|
|
API_VERSIONS = [vers[1] for vers in API_VERSION]
|
|
|
|
|
|
@pytest.mark.parametrize('api_version', API_VERSIONS)
|
|
@mock.patch("passerelle.utils.Request.get")
|
|
def test_get_sites(mocked_get, app, setup, api_version):
|
|
setup.api_version = api_version
|
|
setup.save()
|
|
mocked_get.return_value = tests.utils.FakedResponse(content=SITES_RESPONSE, status_code=200)
|
|
endpoint = reverse(
|
|
"generic-endpoint",
|
|
kwargs={"connector": "isere-ens", "slug": setup.slug, "endpoint": "sites"},
|
|
)
|
|
response = app.get(endpoint)
|
|
assert mocked_get.call_args[0][0].endswith("api/" + api_version + "/site")
|
|
assert mocked_get.call_args[1]["headers"]["token"] == "toktok"
|
|
assert mocked_get.call_count == 1
|
|
assert "data" in response.json
|
|
assert response.json["err"] == 0
|
|
for item in response.json["data"]:
|
|
assert "id" in item
|
|
assert "text" in item
|
|
assert "city" in item
|
|
assert "code" in item
|
|
|
|
# test cache system
|
|
response = app.get(endpoint)
|
|
assert mocked_get.call_count == 1
|
|
|
|
response = app.get(endpoint + "?q=etangs")
|
|
assert len(response.json["data"]) == 2
|
|
response = app.get(endpoint + "?q=CourTe")
|
|
assert len(response.json["data"]) == 1
|
|
response = app.get(endpoint + "?kind=social")
|
|
assert len(response.json["data"]) == 2
|
|
|
|
mocked_get.return_value = tests.utils.FakedResponse(content=SD29B_RESPONSE, status_code=200)
|
|
response = app.get(endpoint + "?id=SD29b")
|
|
assert mocked_get.call_args[0][0].endswith("api/" + api_version + "/site/SD29b")
|
|
assert len(response.json["data"]) == 1
|
|
assert response.json["data"][0]["id"] == "SD29b"
|
|
assert response.json["data"][0]["dogs"] == "LEASH"
|
|
|
|
# bad response for ENS API
|
|
mocked_get.return_value = tests.utils.FakedResponse(content=SITE_404_RESPONSE, status_code=404)
|
|
response = app.get(endpoint + "?id=SD29x")
|
|
assert mocked_get.call_args[0][0].endswith("api/" + api_version + "/site/SD29x")
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"].startswith("error status:404")
|
|
assert response.json["data"]["status_code"] == 404
|
|
assert response.json["data"]["json_content"]["message"] == "Site not found with code SD29x"
|
|
mocked_get.return_value = tests.utils.FakedResponse(content="crash", status_code=500)
|
|
response = app.get(endpoint + "?id=foo500")
|
|
assert mocked_get.call_args[0][0].endswith("api/" + api_version + "/site/foo500")
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_desc"].startswith("error status:500")
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["data"]["status_code"] == 500
|
|
assert response.json["data"]["json_content"] is None
|
|
mocked_get.return_value = tests.utils.FakedResponse(content=None, status_code=204)
|
|
response = app.get(endpoint + "?id=foo204")
|
|
assert mocked_get.call_args[0][0].endswith("api/" + api_version + "/site/foo204")
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"] == "abnormal empty response"
|
|
mocked_get.return_value = tests.utils.FakedResponse(content="not json", status_code=200)
|
|
response = app.get(endpoint + "?id=foo")
|
|
assert mocked_get.call_args[0][0].endswith("api/" + api_version + "/site/foo")
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"].startswith("invalid JSON in response:")
|
|
|
|
|
|
@pytest.mark.parametrize('api_version', API_VERSIONS)
|
|
@mock.patch("passerelle.utils.Request.get")
|
|
def test_get_animators(mocked_get, app, setup, api_version):
|
|
setup.api_version = api_version
|
|
setup.save()
|
|
mocked_get.return_value = tests.utils.FakedResponse(content=ANIMATORS_RESPONSE, status_code=200)
|
|
endpoint = reverse(
|
|
"generic-endpoint",
|
|
kwargs={"connector": "isere-ens", "slug": setup.slug, "endpoint": "animators"},
|
|
)
|
|
response = app.get(endpoint)
|
|
assert mocked_get.call_args[0][0].endswith("api/" + api_version + "/schoolAnimator")
|
|
assert mocked_get.call_count == 1
|
|
assert "data" in response.json
|
|
assert response.json["err"] == 0
|
|
for item in response.json["data"]:
|
|
assert "id" in item
|
|
assert "text" in item
|
|
assert "first_name" in item
|
|
assert "email" in item
|
|
|
|
# test cache system
|
|
response = app.get(endpoint)
|
|
assert mocked_get.call_count == 1
|
|
|
|
response = app.get(endpoint + "?q=Kael")
|
|
assert len(response.json["data"]) == 1
|
|
response = app.get(endpoint + "?q=association")
|
|
assert len(response.json["data"]) == 2
|
|
response = app.get(endpoint + "?q=mail.grd")
|
|
assert len(response.json["data"]) == 2
|
|
response = app.get(endpoint + "?id=2")
|
|
assert len(response.json["data"]) == 1
|
|
assert response.json["data"][0]["first_name"] == "Michael"
|
|
|
|
|
|
@pytest.mark.parametrize('api_version', API_VERSIONS)
|
|
@mock.patch("passerelle.utils.Request.get")
|
|
def test_get_site_calendar(mocked_get, app, setup, freezer, api_version):
|
|
setup.api_version = api_version
|
|
setup.save()
|
|
freezer.move_to("2021-01-21 12:00:00")
|
|
mocked_get.return_value = tests.utils.FakedResponse(content=SITE_CALENDAR_RESPONSE, status_code=200)
|
|
endpoint = reverse(
|
|
"generic-endpoint",
|
|
kwargs={
|
|
"connector": "isere-ens",
|
|
"slug": setup.slug,
|
|
"endpoint": "site-calendar",
|
|
},
|
|
)
|
|
response = app.get(endpoint + "?site=SD29b")
|
|
assert mocked_get.call_args[0][0].endswith("api/" + api_version + "/site/SD29b/calendar")
|
|
assert mocked_get.call_args[1]["params"]["start_date"] == "2021-01-21"
|
|
assert mocked_get.call_args[1]["params"]["end_date"] == "2021-04-23"
|
|
assert response.json["err"] == 0
|
|
assert len(response.json["data"]) == 3
|
|
|
|
assert response.json["data"][0]["disabled"] is False
|
|
assert response.json["data"][1]["disabled"] is False
|
|
assert response.json["data"][2]["disabled"] is True
|
|
assert response.json["data"][0]["status"] == "open"
|
|
assert response.json["data"][1]["status"] == "partially-open"
|
|
assert response.json["data"][2]["status"] == "closed"
|
|
assert response.json["data"][0]["details"] == "Morning (available), Lunch (closed), Afternoon (available)"
|
|
assert response.json["data"][1]["details"] == "Morning (available), Lunch (open), Afternoon (complete)"
|
|
assert response.json["data"][2]["details"] == "Morning (complete), Lunch (closed), Afternoon (complete)"
|
|
|
|
# "2020-01-21"
|
|
assert response.json["data"][0]["date_number"] == "21"
|
|
assert response.json["data"][0]["date_weekday"] == "Tuesday"
|
|
assert response.json["data"][0]["date_weekdayindex"] == "2"
|
|
assert response.json["data"][0]["date_weeknumber"] == "4"
|
|
assert response.json["data"][0]["date_month"] == "January 2020"
|
|
|
|
response = app.get(endpoint + "?site=SD29b&start_date=2021-01-22")
|
|
assert mocked_get.call_args[1]["params"]["start_date"] == "2021-01-22"
|
|
assert mocked_get.call_args[1]["params"]["end_date"] == "2021-04-24"
|
|
assert response.json["err"] == 0
|
|
response = app.get(endpoint + "?site=SD29b&start_date=2021-01-22&end_date=2021-01-30")
|
|
assert mocked_get.call_args[1]["params"]["start_date"] == "2021-01-22"
|
|
assert mocked_get.call_args[1]["params"]["end_date"] == "2021-01-30"
|
|
assert response.json["err"] == 0
|
|
response = app.get(endpoint + "?site=SD29b&start_date=foo", status=400)
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"] == "bad start_date format (foo), should be YYYY-MM-DD"
|
|
response = app.get(endpoint + "?site=SD29b&end_date=bar", status=400)
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"] == "bad end_date format (bar), should be YYYY-MM-DD"
|
|
|
|
|
|
@mock.patch("passerelle.utils.Request.post")
|
|
def test_post_book_v1(mocked_post, app, setup):
|
|
mocked_post.return_value = tests.utils.FakedResponse(content=BOOK_RESPONSE, status_code=200)
|
|
endpoint = reverse(
|
|
"generic-endpoint",
|
|
kwargs={
|
|
"connector": "isere-ens",
|
|
"slug": setup.slug,
|
|
"endpoint": "site-booking",
|
|
},
|
|
)
|
|
book = {
|
|
"code": "resa",
|
|
"status": "OK",
|
|
"beneficiary_id": "42",
|
|
"beneficiary_first_name": "Foo",
|
|
"beneficiary_last_name": "Bar",
|
|
"beneficiary_email": "foobar@example.net",
|
|
"beneficiary_phone": "9876",
|
|
"beneficiary_cellphone": "06",
|
|
"entity_id": "38420D",
|
|
"entity_name": "Ecole FooBar",
|
|
"entity_type": "school",
|
|
"project": "Publik",
|
|
"site": "SD29b",
|
|
"applicant": "app",
|
|
"public": "GS",
|
|
"date": "2020-01-22",
|
|
"participants": "50",
|
|
"morning": True,
|
|
"lunch": False,
|
|
"afternoon": False,
|
|
"pmr": True,
|
|
"grade_levels": ["CP", "CE1"],
|
|
"animator": "42",
|
|
}
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/1.0.0/booking")
|
|
assert mocked_post.call_count == 1
|
|
assert mocked_post.call_args.kwargs['json']['booking']['schoolAnimator'] == 42
|
|
assert response.json["err"] == 0
|
|
assert response.json["data"]["status"] == "BOOKING"
|
|
|
|
mocked_post.return_value = tests.utils.FakedResponse(content=BOOK_RESPONSE_OVERBOOKING, status_code=200)
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/1.0.0/booking")
|
|
assert mocked_post.call_count == 2
|
|
assert response.json["err"] == 0
|
|
assert response.json["data"]["status"] == "OVERBOOKING"
|
|
|
|
mocked_post.return_value = tests.utils.FakedResponse(content=BOOK_RESPONSE_REFUSED, status_code=200)
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/1.0.0/booking")
|
|
assert mocked_post.call_count == 3
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"] == "booking status is REFUSED"
|
|
assert response.json["data"]["status"] == "REFUSED"
|
|
|
|
mocked_post.return_value = tests.utils.FakedResponse(content="""["not", "a", "dict"]""", status_code=200)
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/1.0.0/booking")
|
|
assert mocked_post.call_count == 4
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"] == "response is not a dict"
|
|
assert response.json["data"] == ["not", "a", "dict"]
|
|
|
|
mocked_post.return_value = tests.utils.FakedResponse(content="""{"foo": "bar"}""", status_code=200)
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/1.0.0/booking")
|
|
assert mocked_post.call_count == 5
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"] == "no status in response"
|
|
assert response.json["data"] == {"foo": "bar"}
|
|
|
|
book["animator"] = ""
|
|
mocked_post.return_value = tests.utils.FakedResponse(content=BOOK_RESPONSE, status_code=200)
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/1.0.0/booking")
|
|
assert 'schoolAnimator' not in mocked_post.call_args.kwargs['json']['booking']
|
|
assert mocked_post.call_count == 6
|
|
assert response.json["err"] == 0
|
|
assert response.json["data"]["status"] == "BOOKING"
|
|
|
|
del book["animator"]
|
|
mocked_post.return_value = tests.utils.FakedResponse(content=BOOK_RESPONSE, status_code=200)
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/1.0.0/booking")
|
|
assert 'schoolAnimator' not in mocked_post.call_args.kwargs['json']['booking']
|
|
assert mocked_post.call_count == 7
|
|
assert response.json["err"] == 0
|
|
assert response.json["data"]["status"] == "BOOKING"
|
|
|
|
del book['code']
|
|
response = app.post_json(endpoint, params=book, status=400)
|
|
assert response.json['err'] == 'bad-request'
|
|
assert response.json['data'] is None
|
|
assert response.json['err_desc'] == 'code is mandatory (API v1.0.0)'
|
|
|
|
|
|
@pytest.mark.parametrize('api_version', API_VERSIONS[1:])
|
|
@mock.patch("passerelle.utils.Request.post")
|
|
def test_post_book(mocked_post, app, setup, api_version):
|
|
setup.api_version = api_version
|
|
setup.save()
|
|
mocked_post.return_value = tests.utils.FakedResponse(content=BOOK_RESPONSE, status_code=200)
|
|
endpoint = reverse(
|
|
"generic-endpoint",
|
|
kwargs={
|
|
"connector": "isere-ens",
|
|
"slug": setup.slug,
|
|
"endpoint": "site-booking",
|
|
},
|
|
)
|
|
book = {
|
|
"site": "SD29b",
|
|
"date": "2020-01-22",
|
|
"pmr": True,
|
|
"morning": True,
|
|
"lunch": False,
|
|
"afternoon": False,
|
|
"participants": "50",
|
|
"animator": "42",
|
|
"group": "3",
|
|
"grade_levels": ["CP", "CE1"],
|
|
"beneficiary_first_name": "Foo",
|
|
"beneficiary_last_name": "Bar",
|
|
"beneficiary_email": "foobar@example.net",
|
|
"beneficiary_phone": "9876",
|
|
}
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/" + api_version + "/site/booking/school")
|
|
assert mocked_post.call_count == 1
|
|
assert mocked_post.call_args.kwargs['json']['schoolAnimator'] == 42
|
|
assert mocked_post.call_args.kwargs['json']['participants'] == 50
|
|
assert mocked_post.call_args.kwargs['json']['beneficiary']['lastName'] == 'Bar'
|
|
assert mocked_post.call_args.kwargs['json']['beneficiary']['cellphone'] == ''
|
|
assert 'idExternal' not in mocked_post.call_args.kwargs['json']
|
|
assert 'projectCode' not in mocked_post.call_args.kwargs['json']
|
|
assert response.json["err"] == 0
|
|
assert response.json["data"]["status"] == "BOOKING"
|
|
|
|
book['external_id'] = '12-34'
|
|
book['project'] = 'pc'
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/" + api_version + "/site/booking/school")
|
|
assert mocked_post.call_count == 2
|
|
assert mocked_post.call_args.kwargs['json']['idExternal'] == '12-34'
|
|
assert mocked_post.call_args.kwargs['json']['projectCode'] == 'pc'
|
|
assert response.json["err"] == 0
|
|
|
|
mocked_post.return_value = tests.utils.FakedResponse(content=BOOK_RESPONSE_OVERBOOKING, status_code=200)
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/" + api_version + "/site/booking/school")
|
|
assert mocked_post.call_count == 3
|
|
assert response.json["err"] == 0
|
|
assert response.json["data"]["status"] == "OVERBOOKING"
|
|
|
|
mocked_post.return_value = tests.utils.FakedResponse(content=BOOK_RESPONSE_REFUSED, status_code=200)
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/" + api_version + "/site/booking/school")
|
|
assert mocked_post.call_count == 4
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"] == "booking status is REFUSED"
|
|
assert response.json["data"]["status"] == "REFUSED"
|
|
|
|
mocked_post.return_value = tests.utils.FakedResponse(content="""["not", "a", "dict"]""", status_code=200)
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/" + api_version + "/site/booking/school")
|
|
assert mocked_post.call_count == 5
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"] == "response is not a dict"
|
|
assert response.json["data"] == ["not", "a", "dict"]
|
|
|
|
mocked_post.return_value = tests.utils.FakedResponse(content="""{"foo": "bar"}""", status_code=200)
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/" + api_version + "/site/booking/school")
|
|
assert mocked_post.call_count == 6
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"] == "no status in response"
|
|
assert response.json["data"] == {"foo": "bar"}
|
|
|
|
book["animator"] = ""
|
|
mocked_post.return_value = tests.utils.FakedResponse(content=BOOK_RESPONSE, status_code=200)
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/" + api_version + "/site/booking/school")
|
|
assert 'schoolAnimator' not in mocked_post.call_args.kwargs['json']
|
|
assert mocked_post.call_count == 7
|
|
assert response.json["err"] == 0
|
|
assert response.json["data"]["status"] == "BOOKING"
|
|
|
|
del book["animator"]
|
|
mocked_post.return_value = tests.utils.FakedResponse(content=BOOK_RESPONSE, status_code=200)
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/" + api_version + "/site/booking/school")
|
|
assert 'schoolAnimator' not in mocked_post.call_args.kwargs['json']
|
|
assert mocked_post.call_count == 8
|
|
assert response.json["err"] == 0
|
|
assert response.json["data"]["status"] == "BOOKING"
|
|
|
|
book['group'] = 'G'
|
|
response = app.post_json(endpoint, params=book, status=400)
|
|
assert response.json['err'] == 1
|
|
assert response.json['data'] is None
|
|
assert response.json['err_desc'] == "group: 'G' does not match '^[0-9]*$'"
|
|
|
|
book['group'] = ''
|
|
response = app.post_json(endpoint, params=book, status=400)
|
|
assert response.json['err'] == 'bad-request'
|
|
assert response.json['data'] is None
|
|
assert response.json['err_desc'] == 'group or applicant are mandatory (API v2.1.0/v2.1.1)'
|
|
|
|
del book['group']
|
|
response = app.post_json(endpoint, params=book, status=400)
|
|
assert response.json['err'] == 'bad-request'
|
|
assert response.json['data'] is None
|
|
assert response.json['err_desc'] == 'group or applicant are mandatory (API v2.1.0/v2.1.1)'
|
|
|
|
book['applicant'] = 'ecole 1'
|
|
response = app.post_json(endpoint, params=book)
|
|
assert mocked_post.call_args[0][0].endswith("api/" + api_version + "/site/booking/school")
|
|
assert mocked_post.call_args.kwargs['json']['schoolGroup'] is None
|
|
assert mocked_post.call_args.kwargs['json']['applicant'] == 'ecole 1'
|
|
|
|
|
|
@pytest.mark.parametrize('api_version', API_VERSIONS)
|
|
@mock.patch("passerelle.utils.Request.get")
|
|
def test_get_booking_status(mocked_get, app, setup, api_version):
|
|
setup.api_version = api_version
|
|
setup.save()
|
|
endpoint = reverse(
|
|
"generic-endpoint",
|
|
kwargs={
|
|
"connector": "isere-ens",
|
|
"slug": setup.slug,
|
|
"endpoint": "get-site-booking",
|
|
},
|
|
)
|
|
|
|
mocked_get.return_value = tests.utils.FakedResponse(content=BOOK_RESPONSE, status_code=200)
|
|
response = app.get(endpoint + "?code=123")
|
|
if api_version == '1.0.0':
|
|
assert mocked_get.call_args[0][0].endswith("api/1.0.0/booking/123/status")
|
|
else:
|
|
assert mocked_get.call_args[0][0].endswith("api/" + api_version + "/site/booking/school/123/status/")
|
|
assert mocked_get.call_count == 1
|
|
assert response.json["err"] == 0
|
|
assert response.json["data"]["status"] == "BOOKING"
|
|
|
|
response = app.get(endpoint, status=400) # no code specified
|
|
assert mocked_get.call_count == 1
|
|
|
|
mocked_get.return_value = tests.utils.FakedResponse(content="""["not", "a", "dict"]""", status_code=200)
|
|
response = app.get(endpoint + "?code=123")
|
|
assert mocked_get.call_count == 2
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"] == "response is not a dict"
|
|
assert response.json["data"] == ["not", "a", "dict"]
|
|
|
|
mocked_get.return_value = tests.utils.FakedResponse(content="""{"foo": "bar"}""", status_code=200)
|
|
response = app.get(endpoint + "?code=123")
|
|
assert mocked_get.call_count == 3
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"] == "no status in response"
|
|
assert response.json["data"] == {"foo": "bar"}
|
|
|
|
|
|
@pytest.mark.parametrize('api_version', API_VERSIONS)
|
|
@mock.patch("passerelle.utils.Request.post")
|
|
def test_cancel_booking(mocked_post, app, setup, api_version):
|
|
setup.api_version = api_version
|
|
setup.save()
|
|
endpoint = reverse(
|
|
"generic-endpoint",
|
|
kwargs={
|
|
"connector": "isere-ens",
|
|
"slug": setup.slug,
|
|
"endpoint": "cancel-site-booking",
|
|
},
|
|
)
|
|
mocked_post.return_value = tests.utils.FakedResponse(content=CANCEL_RESPONSE, status_code=200)
|
|
response = app.post(endpoint + "?code=123")
|
|
if api_version == '1.0.0':
|
|
assert response.json["err"] == 1
|
|
assert response.json["data"] is None
|
|
assert response.json["err_desc"] == "not available on API v1.0.0"
|
|
return
|
|
assert mocked_post.call_args[0][0].endswith("api/" + api_version + "/site/booking/school/cancel/123")
|
|
assert mocked_post.call_count == 1
|
|
assert response.json["err"] == 0
|
|
assert response.json["data"]["status"] == "CANCELED"
|
|
|
|
response = app.post(endpoint, status=400) # no code specified
|
|
assert mocked_post.call_count == 1 # same as before
|
|
|
|
mocked_post.return_value = tests.utils.FakedResponse(content="""["not", "a", "dict"]""", status_code=200)
|
|
response = app.post(endpoint + "?code=123")
|
|
assert mocked_post.call_count == 2
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"] == "response is not a dict"
|
|
assert response.json["data"] == ["not", "a", "dict"]
|
|
|
|
mocked_post.return_value = tests.utils.FakedResponse(content="""{"foo": "bar"}""", status_code=200)
|
|
response = app.post(endpoint + "?code=123")
|
|
assert mocked_post.call_count == 3
|
|
assert response.json["err"] == 1
|
|
assert response.json["err_class"].endswith("APIError")
|
|
assert response.json["err_desc"] == "no status in response"
|
|
assert response.json["data"] == {"foo": "bar"}
|