import json from unittest import mock import pytest from django.contrib.contenttypes.models import ContentType import tests.utils from passerelle.apps.okina.models import Okina from passerelle.base.models import AccessRight, ApiUser CITIES = '''[ { "city" : 83355, "cityObject" : { "id" : 83355, "insee" : "36005", "nameCity" : "ARDENTES", "zipCode" : "36120", "nameCityRouting" : "ARDENTES", "line5" : null } }, { "city" : 80237, "cityObject" : { "id" : 80237, "insee" : "36044", "nameCity" : "CHATEAUROUX", "zipCode" : "36000", "nameCityRouting" : "CHATEAUROUX", "line5" : null } } ] ''' # new API (march 2020) CITIES_NEW = '''[ { "id": 83355, "insee": "36005", "name": "ARDENTES", "zipCode": "36120", "nameCityRouting": null, "line5": null, "latitude": null, "longitude": null, "geoJson": null } ] ''' CLASSES = ''' [ { "id": 1, "label": "École maternelle - Petite section" }, { "id": 2, "label": "École maternelle - Moyenne section" }, { "id": 4, "label": "École élémentaire – CP" }, { "id": 5, "label": "École élémentaire – CE 1" } ] ''' INSTITUTIONS = '''[ { "id" : 276, "schoolEstablishment" : { "uai" : "0360155Y", "uaiLabel" : "Ecole élémentaire Saint-Martin", "mainTitle" : "ECOLE ELEMENTAIRE PUBLIQUE", "type" : "Public", "address" : "RUE CALMETTE ET GUERIN", "zipCode" : "36120", "cityName" : "ARDENTES", "locationX" : "1.82965415466176", "locationY" : "46.740247926141706", "nature" : "151", "natureTitle" : "Ecole élémentaire" }, "schoolEstablishmentUai" : "0360155Y", "zipAndCity" : "36120 - ARDENTES", "institutionContacts" : [ ] }, { "id" : 277, "schoolEstablishment" : { "uai" : "0360048G", "uaiLabel" : "Collège Touvent", "mainTitle" : "COLLEGE", "type" : "Public", "address" : "4 ALLÉE DES LAURIERS", "zipCode" : "36007", "cityName" : "CHATEAUROUX CEDEX", "locationX" : "1.6926355997775921", "locationY" : "46.791332586468016", "nature" : "340", "natureTitle" : "Collège" }, "schoolEstablishmentUai" : "0360048G", "zipAndCity" : "36007 - CHATEAUROUX CEDEX", "institutionContacts" : [ ] } ] ''' # new API (march 2020) INSTITUTIONS_NEW = '''[ { "id" : 276, "schoolEstablishment" : { "uai" : "0360155Y", "uaiLabel" : "Ecole élémentaire Saint-Martin", "type" : "Public", "address" : "Rue Calmette et Guérin", "zipCode" : "36120", "codeCity" : "36005", "cityName" : "Ardentes", "locationX" : "1.8296541547236063", "locationY" : "46.74024796567764", "nature" : "1000", "natureTitle" : "Ecole", "restoration" : true, "accommodation" : false, "ulis" : false, "segpa" : false, "sirenSiret" : "21360005900033", "webSite" : null, "phone" : "254362184", "fax" : "", "email" : "ec-saint-martin-ardentes@ac-orleans-tours.fr", "departmentLabel" : "Indre", "academyLabel" : "Orléans-Tours", "regionLabel" : "Centre-Val de Loire", "schoolSectionList" : [ ], "schoolEstablishmentTypeInfos" : [ { "key" : "ecole_elementaire", "value" : "École élémentaire" } ] }, "schoolEstablishmentDisplayName" : "Ecole élémentaire Saint-Martin", "schoolEstablishmentUai" : "0360155Y", "zipAndCity" : "36120 - Ardentes", "withContract" : true, "institutionContacts" : [ ], "institutionTimes" : [ { "id" : 27, "day" : "MONDAY", "way" : "WAY_TO", "time" : "08:46:00", "institutionId" : 0, "timeString" : null }, { "id" : 28, "day" : "MONDAY", "way" : "WAY_BACK", "time" : "16:30:00", "institutionId" : 0, "timeString" : null }, { "id" : 29, "day" : "TUESDAY", "way" : "WAY_TO", "time" : "08:46:00", "institutionId" : 0, "timeString" : null }, { "id" : 30, "day" : "TUESDAY", "way" : "WAY_BACK", "time" : "16:30:00", "institutionId" : 0, "timeString" : null }, { "id" : 31, "day" : "THURSDAY", "way" : "WAY_TO", "time" : "08:46:00", "institutionId" : 0, "timeString" : null }, { "id" : 32, "day" : "THURSDAY", "way" : "WAY_BACK", "time" : "16:30:00", "institutionId" : 0, "timeString" : null }, { "id" : 33, "day" : "FRIDAY", "way" : "WAY_TO", "time" : "08:46:00", "institutionId" : 0, "timeString" : null }, { "id" : 34, "day" : "FRIDAY", "way" : "WAY_BACK", "time" : "16:30:00", "institutionId" : 0, "timeString" : null } ], "cities" : null, "optionsDerogatory" : [ ], "institutionCenterName" : "ARDENTES", "institutionCenterId" : 3, "customLocationX" : "1.8296541547236063", "customLocationY" : "46.74024796567764" }, { "id" : 277, "schoolEstablishment" : { "uai" : "0360048G", "uaiLabel" : "Collège Touvent", "type" : "Public", "address" : "4 allée des Lauriers", "zipCode" : "36000", "codeCity" : "36044", "cityName" : "Châteauroux", "locationX" : "1.6926355997775921", "locationY" : "46.791332586468016", "nature" : "340", "natureTitle" : "Collège", "restoration" : false, "accommodation" : false, "ulis" : true, "segpa" : false, "sirenSiret" : "19360048300013", "webSite" : null, "phone" : "02 54 34 03 30", "fax" : "02 54 08 01 09", "email" : "ce.0360048g@ac-orleans-tours.fr", "departmentLabel" : "Indre", "academyLabel" : "Orléans-Tours", "regionLabel" : "Centre-Val de Loire", "schoolSectionList" : [ { "key" : "section_sport", "name" : "Section sport" } ], "schoolEstablishmentTypeInfos" : [ ] }, "schoolEstablishmentDisplayName" : "Collège Touvent", "schoolEstablishmentUai" : "0360048G", "zipAndCity" : "36000 - Châteauroux", "withContract" : true, "institutionContacts" : [ ], "institutionTimes" : [ { "id" : 249, "day" : "MONDAY", "way" : "WAY_TO", "time" : "08:20:00", "institutionId" : 0, "timeString" : null }, { "id" : 250, "day" : "MONDAY", "way" : "WAY_BACK", "time" : "17:05:00", "institutionId" : 0, "timeString" : null }, { "id" : 251, "day" : "TUESDAY", "way" : "WAY_TO", "time" : "08:20:00", "institutionId" : 0, "timeString" : null }, { "id" : 252, "day" : "TUESDAY", "way" : "WAY_BACK", "time" : "17:05:00", "institutionId" : 0, "timeString" : null }, { "id" : 253, "day" : "WEDNESDAY", "way" : "WAY_TO", "time" : "07:50:00", "institutionId" : 0, "timeString" : null }, { "id" : 254, "day" : "WEDNESDAY", "way" : "WAY_BACK", "time" : "12:05:00", "institutionId" : 0, "timeString" : null }, { "id" : 255, "day" : "THURSDAY", "way" : "WAY_TO", "time" : "08:20:00", "institutionId" : 0, "timeString" : null }, { "id" : 256, "day" : "THURSDAY", "way" : "WAY_BACK", "time" : "17:05:00", "institutionId" : 0, "timeString" : null }, { "id" : 257, "day" : "FRIDAY", "way" : "WAY_TO", "time" : "08:20:00", "institutionId" : 0, "timeString" : null }, { "id" : 258, "day" : "FRIDAY", "way" : "WAY_BACK", "time" : "17:05:00", "institutionId" : 0, "timeString" : null } ], "cities" : null, "optionsDerogatory" : [ ], "institutionCenterName" : "CHATEAUROUX", "institutionCenterId" : 2, "customLocationX" : "1.6926355997775921", "customLocationY" : "46.791332586468016" } ] ''' SEARCH = '''[ { "id" : 3312, "stop_point_id" : 1498, "name" : "Le Grand Verger", "latitude" : 46.8444186, "longitude" : 1.708197, "bearing" : 0.0, "position" : 6, "forBoarding" : null, "forAlighting" : null, "colorUsage" : null, "isRecommended" : false, "titreRelaisId" : null, "networkType" : "SCHOLAR", "commercial_stop_area" : 3312, "commercial_name" : "Le Grand Verger", "liaisons" : [ ], "registrationNumber" : "36063_009", "cityCode" : "36063", "cityName" : "Déols", "zipCode" : "36130", "isDuplicatedCompute" : 0, "nbClosedStopAreas" : null, "isValidated" : null, "isUnique" : null, "isDuplicated" : null, "network" : { "id" : 2, "name" : "réseau scolaire", "supprime" : false, "networkType" : "SCHOLAR" }, "external_ref" : null, "distanceBetweenPreviousStopCalculated" : 0.0, "distanceBetweenPreviousStopReal" : null }, { "id" : 3311, "stop_point_id" : 1499, "name" : "Jean Bizet U", "latitude" : 46.8359017, "longitude" : 1.7045139, "bearing" : 0.0, "position" : 7, "forBoarding" : null, "forAlighting" : null, "colorUsage" : null, "isRecommended" : true, "titreRelaisId" : null, "networkType" : "SCHOLAR", "commercial_stop_area" : 3311, "commercial_name" : "Jean Bizet U", "liaisons" : [ ], "registrationNumber" : "36063_008", "cityCode" : "36063", "cityName" : "Déols", "zipCode" : "36130", "isDuplicatedCompute" : 0, "nbClosedStopAreas" : null, "isValidated" : null, "isUnique" : null, "isDuplicated" : null, "network" : { "id" : 2, "name" : "réseau scolaire", "supprime" : false, "networkType" : "SCHOLAR" }, "external_ref" : null, "distanceBetweenPreviousStopCalculated" : 0.0, "distanceBetweenPreviousStopReal" : null } ] ''' STOPS = ''' [ { "id" : 3281, "stop_point_id" : 827, "name" : "Les Loges de Dressais", "latitude" : 46.7317874000000018, "longitude" : 1.7887462999999999, "bearing" : 0.0, "position" : 2, "commercial_stop_area" : 3281, "commercial_name" : "Les Loges de Dressais", "liaisons" : [ ], "registrationNumber" : null }, { "id" : 3279, "stop_point_id" : 828, "name" : "La Cueille", "latitude" : 46.7500219000000001, "longitude" : 1.7890467000000001, "bearing" : 0.0, "position" : 3, "commercial_stop_area" : 3279, "commercial_name" : "La Cueille", "liaisons" : [ ], "registrationNumber" : null }, { "id" : 3560, "stop_point_id" : 869, "name" : "Ecole Primaire SAINT-VINCENT", "latitude" : 46.7423843999999988, "longitude" : 1.83196010000000009, "bearing" : 0.0, "position" : 3, "commercial_stop_area" : 3560, "commercial_name" : "Ecole Primaire SAINT-VINCENT", "liaisons" : [ ], "registrationNumber" : null } ] ''' # https://iti.okina.fr/api/Okina/REST/b2b/ods ODS = '''[ { "id" : { "institutionId" : 276, "sequenceNumber" : 1 }, "institution" : { "id" : 276, "schoolEstablishmentUai" : "0360155Y", "okinaStopAreas" : null }, "originDestinationSequenceElements" : [ { "id" : 6, "okinaVehicleJourney" : { "detached" : false, "objectId" : "Europe Voyages 23:VehicleJourney:84", "objectVersion" : 1, "creationTime" : 1491516000000, "creatorId" : null, "saved" : false, "id" : 84, "comment" : null, "transportMode" : null, "publishedJourneyName" : "SYNDICAT ARDENTES 4 (semaine Aller)", "publishedJourneyIdentifier" : "SYNDICAT ARDENTES 4 (semaine Aller)", "facility" : null, "vehicleTypeIdentifier" : null, "number" : 84, "mobilityRestrictedSuitability" : null, "flexibleService" : null, "route" : null, "journeyPattern" : null, "company" : null, "footnotes" : null, "timetables" : null, "vehicleJourneyAtStops" : null, "journeyCategory" : "Timesheet", "journeyFrequencies" : null, "okinaJourneyPattern" : null, "okinaRoute" : null, "etat" : 0, "supprime" : false, "okinaVehicleJourneyAtStops" : null, "counterGroups" : null, "registrationNumber" : null, "filled" : false }, "okinaJourneyPattern" : null, "position" : 1, "originDestination" : { "institutionId" : 276, "sequenceNumber" : 1 } } ], "oppositeOds" : null, "way" : "WAY_TO" }, { "id" : { "institutionId" : 276, "sequenceNumber" : 2 }, "institution" : { "id" : 276, "schoolEstablishmentUai" : "0360155Y", "okinaStopAreas" : null }, "originDestinationSequenceElements" : [ { "id" : 203, "okinaVehicleJourney" : { "detached" : false, "objectId" : "STI CENTRE:VehicleJourney:90", "objectVersion" : 1, "creationTime" : 1491516000000, "creatorId" : null, "saved" : false, "id" : 90, "comment" : null, "transportMode" : null, "publishedJourneyName" : "SYNDICAT ARDENTES 6 (semaine Aller)", "publishedJourneyIdentifier" : "SYNDICAT ARDENTES 6 (semaine Aller)", "facility" : null, "vehicleTypeIdentifier" : null, "number" : 90, "mobilityRestrictedSuitability" : null, "flexibleService" : null, "route" : null, "journeyPattern" : null, "company" : null, "footnotes" : null, "timetables" : null, "vehicleJourneyAtStops" : null, "journeyCategory" : "Timesheet", "journeyFrequencies" : null, "okinaJourneyPattern" : null, "okinaRoute" : null, "etat" : 0, "supprime" : false, "okinaVehicleJourneyAtStops" : null, "counterGroups" : null, "registrationNumber" : null, "filled" : false }, "okinaJourneyPattern" : null, "position" : 1, "originDestination" : { "institutionId" : 276, "sequenceNumber" : 2 } } ], "oppositeOds" : null, "way" : "WAY_TO" } ] ''' # https://iti.okina.fr/api/Okina/REST/b2b/ods/institution/276/stop-area/3282 ODS_LINES = '''[ [ { "id" : 24, "name" : "LIGNE 24" } ], [ { "id": 22,"name": "LIGNE 22" } ], [ { "id": 24, "name" : "LIGNE 24" }, { "id": 23, "name": "LIGNE 23" } ] ] ''' # https://iti.okina.fr/api/Okina/REST/b2b/ods/institution/276/subscriberCity/36005 # https://iti.okina.fr/api/Okina/REST/b2b/ods/subscriberCity/36005 ODS_FULL = '''[ { "id" : { "institutionId" : 276, "sequenceNumber" : 1 }, "institution" : { "id" : 276, "schoolEstablishmentUai" : "0360155Y", "okinaStopAreas" : null }, "originDestinationSequenceElements" : [ { "id" : 6, "okinaVehicleJourney" : { "detached" : false, "objectId" : "Europe Voyages 23:VehicleJourney:84", "objectVersion" : 1, "creationTime" : 1491516000000, "creatorId" : null, "saved" : false, "id" : 84, "comment" : null, "transportMode" : null, "publishedJourneyName" : "SYNDICAT ARDENTES 4 (semaine Aller)", "publishedJourneyIdentifier" : "SYNDICAT ARDENTES 4 (semaine Aller)", "facility" : null, "vehicleTypeIdentifier" : null, "number" : 84, "mobilityRestrictedSuitability" : null, "flexibleService" : null, "route" : null, "journeyPattern" : null, "company" : null, "footnotes" : null, "timetables" : null, "vehicleJourneyAtStops" : null, "journeyCategory" : "Timesheet", "journeyFrequencies" : null, "okinaJourneyPattern" : { "detached" : false, "objectId" : "europevoyages:JourneyPattern:86", "objectVersion" : 1, "creationTime" : 1491516000000, "creatorId" : null, "saved" : false, "id" : 86, "name" : "Brenne 1 vers écoles Antoine Fée, Saint Martin et Saint Vincent (semaine Aller)", "comment" : null, "registrationNumber" : null, "publishedName" : "Brenne 1 vers écoles Antoine Fée, Saint Martin et Saint Vincent", "sectionStatus" : "Todo", "route" : null, "departureStopPoint" : null, "arrivalStopPoint" : null, "stopPoints" : null, "vehicleJourneys" : null, "routeSections" : null, "okinaStopPoints" : [ { "id" : 825, "detached" : false, "objectId" : "chateauroux:StopPoint:825", "objectVersion" : 1, "creationTime" : 1491551801241, "creatorId" : null, "saved" : false, "position" : 0, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : { "detached" : false, "objectId" : "chateauroux:StopArea:Boarding_36005_004", "objectVersion" : 1, "creationTime" : null, "creatorId" : null, "saved" : false, "longitude" : 1.81673930000000006, "latitude" : 46.719458699999997, "longLatType" : null, "x" : null, "y" : null, "projectionType" : null, "countryCode" : "36005", "zipCode" : "36120", "cityName" : "Ardentes", "streetName" : null, "id" : 3273, "name" : "Brenne 1", "comment" : null, "areaType" : "BoardingPosition", "registrationNumber" : "36005_004", "nearestTopicName" : null, "url" : null, "timeZone" : null, "fareCode" : null, "liftAvailable" : null, "mobilityRestrictedSuitable" : null, "stairsAvailable" : null, "intUserNeeds" : null, "parent" : null, "routingConstraintLines" : null, "routingConstraintAreas" : null, "containedStopAreas" : null, "containedStopPoints" : null, "accessLinks" : null, "routeSectionDepartures" : null, "routeSectionArrivals" : null, "connectionStartLinks" : null, "connectionEndLinks" : null, "accessPoints" : null, "okinaContainedStopPoints" : null, "okinaParent" : null, "bearing" : 0.0, "cityCode" : "36005", "okinaContainedStopAreas" : null, "userNeeds" : [ ], "filled" : false }, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 826, "detached" : false, "objectId" : "chateauroux:StopPoint:826", "objectVersion" : 1, "creationTime" : 1491551801241, "creatorId" : null, "saved" : false, "position" : 1, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : { "detached" : false, "objectId" : "chateauroux:StopArea:Boarding_36005_005", "objectVersion" : 1, "creationTime" : null, "creatorId" : null, "saved" : false, "longitude" : 1.80696429999999997, "latitude" : 46.7233643000000001, "longLatType" : null, "x" : null, "y" : null, "projectionType" : null, "countryCode" : "36005", "zipCode" : "36120", "cityName" : "Ardentes", "streetName" : null, "id" : 3274, "name" : "Brenne 2", "comment" : null, "areaType" : "BoardingPosition", "registrationNumber" : "36005_005", "nearestTopicName" : null, "url" : null, "timeZone" : null, "fareCode" : null, "liftAvailable" : null, "mobilityRestrictedSuitable" : null, "stairsAvailable" : null, "intUserNeeds" : null, "parent" : null, "routingConstraintLines" : null, "routingConstraintAreas" : null, "containedStopAreas" : null, "containedStopPoints" : null, "accessLinks" : null, "routeSectionDepartures" : null, "routeSectionArrivals" : null, "connectionStartLinks" : null, "connectionEndLinks" : null, "accessPoints" : null, "okinaContainedStopPoints" : null, "okinaParent" : null, "bearing" : 0.0, "cityCode" : "36005", "okinaContainedStopAreas" : null, "userNeeds" : [ ], "filled" : false }, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 827, "detached" : false, "objectId" : "chateauroux:StopPoint:827", "objectVersion" : 1, "creationTime" : 1491551801242, "creatorId" : null, "saved" : false, "position" : 2, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : { "detached" : false, "objectId" : "chateauroux:StopArea:Boarding_36005_012", "objectVersion" : 1, "creationTime" : null, "creatorId" : null, "saved" : false, "longitude" : 1.7887462999999999, "latitude" : 46.7317874000000018, "longLatType" : null, "x" : null, "y" : null, "projectionType" : null, "countryCode" : "36005", "zipCode" : "36120", "cityName" : "Ardentes", "streetName" : null, "id" : 3281, "name" : "Les Loges de Dressais", "comment" : null, "areaType" : "BoardingPosition", "registrationNumber" : "36005_012", "nearestTopicName" : null, "url" : null, "timeZone" : null, "fareCode" : null, "liftAvailable" : null, "mobilityRestrictedSuitable" : null, "stairsAvailable" : null, "intUserNeeds" : null, "parent" : null, "routingConstraintLines" : null, "routingConstraintAreas" : null, "containedStopAreas" : null, "containedStopPoints" : null, "accessLinks" : null, "routeSectionDepartures" : null, "routeSectionArrivals" : null, "connectionStartLinks" : null, "connectionEndLinks" : null, "accessPoints" : null, "okinaContainedStopPoints" : null, "okinaParent" : null, "bearing" : 0.0, "cityCode" : "36005", "okinaContainedStopAreas" : null, "userNeeds" : [ ], "filled" : false }, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 828, "detached" : false, "objectId" : "chateauroux:StopPoint:828", "objectVersion" : 1, "creationTime" : 1491551801242, "creatorId" : null, "saved" : false, "position" : 3, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : { "detached" : false, "objectId" : "chateauroux:StopArea:Boarding_36005_010", "objectVersion" : 1, "creationTime" : null, "creatorId" : null, "saved" : false, "longitude" : 1.7890467000000001, "latitude" : 46.7500219000000001, "longLatType" : null, "x" : null, "y" : null, "projectionType" : null, "countryCode" : "36005", "zipCode" : "36120", "cityName" : "Ardentes", "streetName" : null, "id" : 3279, "name" : "La Cueille", "comment" : null, "areaType" : "BoardingPosition", "registrationNumber" : "36005_010", "nearestTopicName" : null, "url" : null, "timeZone" : null, "fareCode" : null, "liftAvailable" : null, "mobilityRestrictedSuitable" : null, "stairsAvailable" : null, "intUserNeeds" : null, "parent" : null, "routingConstraintLines" : null, "routingConstraintAreas" : null, "containedStopAreas" : null, "containedStopPoints" : null, "accessLinks" : null, "routeSectionDepartures" : null, "routeSectionArrivals" : null, "connectionStartLinks" : null, "connectionEndLinks" : null, "accessPoints" : null, "okinaContainedStopPoints" : null, "okinaParent" : null, "bearing" : 0.0, "cityCode" : "36005", "okinaContainedStopAreas" : null, "userNeeds" : [ ], "filled" : false }, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 829, "detached" : false, "objectId" : "chateauroux:StopPoint:829", "objectVersion" : 1, "creationTime" : 1491551801242, "creatorId" : null, "saved" : false, "position" : 4, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : { "detached" : false, "objectId" : "chateauroux:StopArea:Boarding_36005_013", "objectVersion" : 1, "creationTime" : null, "creatorId" : null, "saved" : false, "longitude" : 1.79444730000000008, "latitude" : 46.7477992999999969, "longLatType" : null, "x" : null, "y" : null, "projectionType" : null, "countryCode" : "36005", "zipCode" : "36120", "cityName" : "Ardentes", "streetName" : null, "id" : 3282, "name" : "Les Loges du Plessis", "comment" : null, "areaType" : "BoardingPosition", "registrationNumber" : "36005_013", "nearestTopicName" : null, "url" : null, "timeZone" : null, "fareCode" : null, "liftAvailable" : null, "mobilityRestrictedSuitable" : null, "stairsAvailable" : null, "intUserNeeds" : null, "parent" : null, "routingConstraintLines" : null, "routingConstraintAreas" : null, "containedStopAreas" : null, "containedStopPoints" : null, "accessLinks" : null, "routeSectionDepartures" : null, "routeSectionArrivals" : null, "connectionStartLinks" : null, "connectionEndLinks" : null, "accessPoints" : null, "okinaContainedStopPoints" : null, "okinaParent" : null, "bearing" : 0.0, "cityCode" : "36005", "okinaContainedStopAreas" : null, "userNeeds" : [ ], "filled" : false }, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 830, "detached" : false, "objectId" : "chateauroux:StopPoint:830", "objectVersion" : 1, "creationTime" : 1491551801243, "creatorId" : null, "saved" : false, "position" : 5, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 831, "detached" : false, "objectId" : "chateauroux:StopPoint:831", "objectVersion" : 1, "creationTime" : 1491551801243, "creatorId" : null, "saved" : false, "position" : 6, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 832, "detached" : false, "objectId" : "chateauroux:StopPoint:832", "objectVersion" : 1, "creationTime" : 1491551801244, "creatorId" : null, "saved" : false, "position" : 7, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false } ], "okinaVehicleJourneys" : null, "etat" : 0, "supprime" : false, "okinaRoute" : null, "okinaDepartureStopPoint" : null, "okinaArrivalStopPoint" : null, "filled" : false }, "okinaRoute" : null, "etat" : 0, "supprime" : false, "okinaVehicleJourneyAtStops" : null, "counterGroups" : null, "registrationNumber" : null, "filled" : false }, "okinaJourneyPattern" : null, "position" : 1, "originDestination" : { "institutionId" : 276, "sequenceNumber" : 1 } } ], "oppositeOds" : [ { "id" : { "institutionId" : 276, "sequenceNumber" : 3 }, "institution" : { "id" : 276, "schoolEstablishmentUai" : "0360155Y", "okinaStopAreas" : null }, "originDestinationSequenceElements" : [ { "id" : 3, "okinaVehicleJourney" : { "detached" : false, "objectId" : "Europe Voyages 23:VehicleJourney:86", "objectVersion" : 1, "creationTime" : 1491516000000, "creatorId" : null, "saved" : false, "id" : 86, "comment" : null, "transportMode" : null, "publishedJourneyName" : "SYNDICAT ARDENTES 4 (mercredi Retour)", "publishedJourneyIdentifier" : "SYNDICAT ARDENTES 4 (mercredi Retour)", "facility" : null, "vehicleTypeIdentifier" : null, "number" : 86, "mobilityRestrictedSuitability" : null, "flexibleService" : null, "route" : null, "journeyPattern" : null, "company" : null, "footnotes" : null, "timetables" : null, "vehicleJourneyAtStops" : null, "journeyCategory" : "Timesheet", "journeyFrequencies" : null, "okinaJourneyPattern" : { "detached" : false, "objectId" : "europevoyages:JourneyPattern:89", "objectVersion" : 1, "creationTime" : 1491516000000, "creatorId" : null, "saved" : false, "id" : 89, "name" : "écoles St Vincent, Antoine Fée et St Martin vers Brenne 1 (mercredi Retour) 2017-04-07 10:10:43.949", "comment" : null, "registrationNumber" : null, "publishedName" : "écoles St Vincent, Antoine Fée et St Martin vers Brenne 1 2017-04-07 10:10:43.949", "sectionStatus" : "Todo", "route" : null, "departureStopPoint" : null, "arrivalStopPoint" : null, "stopPoints" : null, "vehicleJourneys" : null, "routeSections" : null, "okinaStopPoints" : [ { "id" : 849, "detached" : false, "objectId" : "chateauroux:StopPoint:849", "objectVersion" : 1, "creationTime" : 1491552643953, "creatorId" : null, "saved" : false, "position" : 0, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 850, "detached" : false, "objectId" : "chateauroux:StopPoint:850", "objectVersion" : 1, "creationTime" : 1491552643953, "creatorId" : null, "saved" : false, "position" : 1, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 851, "detached" : false, "objectId" : "chateauroux:StopPoint:851", "objectVersion" : 1, "creationTime" : 1491552643954, "creatorId" : null, "saved" : false, "position" : 2, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 852, "detached" : false, "objectId" : "chateauroux:StopPoint:852", "objectVersion" : 1, "creationTime" : 1491552643954, "creatorId" : null, "saved" : false, "position" : 3, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 853, "detached" : false, "objectId" : "chateauroux:StopPoint:853", "objectVersion" : 1, "creationTime" : 1491552643954, "creatorId" : null, "saved" : false, "position" : 4, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 854, "detached" : false, "objectId" : "chateauroux:StopPoint:854", "objectVersion" : 1, "creationTime" : 1491552643954, "creatorId" : null, "saved" : false, "position" : 5, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 855, "detached" : false, "objectId" : "chateauroux:StopPoint:855", "objectVersion" : 1, "creationTime" : 1491552643954, "creatorId" : null, "saved" : false, "position" : 6, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 856, "detached" : false, "objectId" : "chateauroux:StopPoint:856", "objectVersion" : 1, "creationTime" : 1491552643954, "creatorId" : null, "saved" : false, "position" : 7, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false } ], "okinaVehicleJourneys" : null, "etat" : 1, "supprime" : true, "okinaRoute" : null, "okinaDepartureStopPoint" : null, "okinaArrivalStopPoint" : null, "filled" : false }, "okinaRoute" : null, "etat" : 1, "supprime" : false, "okinaVehicleJourneyAtStops" : null, "counterGroups" : null, "registrationNumber" : null, "filled" : false }, "okinaJourneyPattern" : null, "position" : 1, "originDestination" : { "institutionId" : 276, "sequenceNumber" : 3 } } ], "oppositeOds" : [ { "institutionId" : 276, "sequenceNumber" : 1 } ], "way" : "WAY_BACK" }, { "id" : { "institutionId" : 276, "sequenceNumber" : 4 }, "institution" : { "id" : 276, "schoolEstablishmentUai" : "0360155Y", "okinaStopAreas" : null }, "originDestinationSequenceElements" : [ { "id" : 4, "okinaVehicleJourney" : { "detached" : false, "objectId" : "Europe Voyages 23:VehicleJourney:85", "objectVersion" : 1, "creationTime" : 1491516000000, "creatorId" : null, "saved" : false, "id" : 85, "comment" : null, "transportMode" : null, "publishedJourneyName" : "SYNDICAT ARDENTES 4 (semaine Retour)", "publishedJourneyIdentifier" : "SYNDICAT ARDENTES 4 (semaine Retour)", "facility" : null, "vehicleTypeIdentifier" : null, "number" : 85, "mobilityRestrictedSuitability" : null, "flexibleService" : null, "route" : null, "journeyPattern" : null, "company" : null, "footnotes" : null, "timetables" : null, "vehicleJourneyAtStops" : null, "journeyCategory" : "Timesheet", "journeyFrequencies" : null, "okinaJourneyPattern" : { "detached" : false, "objectId" : "europevoyages:JourneyPattern:87", "objectVersion" : 1, "creationTime" : 1491516000000, "creatorId" : null, "saved" : false, "id" : 87, "name" : "écoles St Vincent, Antoine Fée et St Martin vers Brenne 1 (semaine Retour)", "comment" : null, "registrationNumber" : null, "publishedName" : "écoles St Vincent, Antoine Fée et St Martin vers Brenne 1", "sectionStatus" : "Todo", "route" : null, "departureStopPoint" : null, "arrivalStopPoint" : null, "stopPoints" : null, "vehicleJourneys" : null, "routeSections" : null, "okinaStopPoints" : [ { "id" : 833, "detached" : false, "objectId" : "chateauroux:StopPoint:833", "objectVersion" : 1, "creationTime" : 1491552070527, "creatorId" : null, "saved" : false, "position" : 0, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 834, "detached" : false, "objectId" : "chateauroux:StopPoint:834", "objectVersion" : 1, "creationTime" : 1491552070528, "creatorId" : null, "saved" : false, "position" : 1, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 835, "detached" : false, "objectId" : "chateauroux:StopPoint:835", "objectVersion" : 1, "creationTime" : 1491552070528, "creatorId" : null, "saved" : false, "position" : 2, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 836, "detached" : false, "objectId" : "chateauroux:StopPoint:836", "objectVersion" : 1, "creationTime" : 1491552070529, "creatorId" : null, "saved" : false, "position" : 3, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 837, "detached" : false, "objectId" : "chateauroux:StopPoint:837", "objectVersion" : 1, "creationTime" : 1491552070529, "creatorId" : null, "saved" : false, "position" : 4, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 838, "detached" : false, "objectId" : "chateauroux:StopPoint:838", "objectVersion" : 1, "creationTime" : 1491552070530, "creatorId" : null, "saved" : false, "position" : 5, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 839, "detached" : false, "objectId" : "chateauroux:StopPoint:839", "objectVersion" : 1, "creationTime" : 1491552070530, "creatorId" : null, "saved" : false, "position" : 6, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false }, { "id" : 840, "detached" : false, "objectId" : "chateauroux:StopPoint:840", "objectVersion" : 1, "creationTime" : 1491552070530, "creatorId" : null, "saved" : false, "position" : 7, "forBoarding" : null, "forAlighting" : null, "containedInStopArea" : null, "route" : null, "comment" : null, "okinaRoute" : null, "okinaContainedInStopArea" : null, "journeyPatternsDestination" : null, "journeyPatternsOrigin" : null, "okinaJourneyPatterns" : null, "vehicleJourneyAtStops" : null, "registrationNumber" : null, "filled" : false } ], "okinaVehicleJourneys" : null, "etat" : 0, "supprime" : true, "okinaRoute" : null, "okinaDepartureStopPoint" : null, "okinaArrivalStopPoint" : null, "filled" : false }, "okinaRoute" : null, "etat" : 0, "supprime" : false, "okinaVehicleJourneyAtStops" : null, "counterGroups" : null, "registrationNumber" : null, "filled" : false }, "okinaJourneyPattern" : null, "position" : 1, "originDestination" : { "institutionId" : 276, "sequenceNumber" : 4 } } ], "oppositeOds" : [ { "institutionId" : 276, "sequenceNumber" : 1 } ], "way" : "WAY_BACK" } ], "way" : "WAY_TO" } ] ''' # https://iti.okina.fr/api/Okina/REST/b2b/topology/lines LINES = '''[ { "id" : 45, "name" : "019 - 02 - VELLES LYCEES DE CHATEAUROUX" }, { "id" : 3, "name" : "ARTHON COLLEGE 1" }, { "id" : 4, "name" : "ARTHON COLLEGE 2" } ] ''' # https://iti.okina.fr/api/Okina/REST/b2b/topology/networks NETWORKS = '''[ { "id" : 2, "name" : "réseau scolaire" } ] ''' # https://iti.okina.fr/api/Okina/REST/b2b/topology/vehicle-journeys VEHICLE_JOURNEYS = '''[ { "id" : 306, "name" : "019 02 - VELLES LYCEES DE CHATEAUROUX" }, { "id" : 307, "name" : "019-02 - VELLES LYCEES DE CHATEAUROUX" }, { "id" : 305, "name" : "019-02 - VELLES LYCEES DE CHATEAUROUX" } ] ''' QRCODE_400 = '''{ "code" : 3, "status" : 400, "message" : "Subscriber with ID 123 has no passcard number to generate qr code from." }''' QRCODE_404 = '''{ "code" : 1, "status" : 404, "message" : "Subscriber with ID 123 not found." }''' @pytest.fixture def okina(db): return Okina.objects.create( slug='test', service_url='https://okina.example.net/b2b/', username='usertest', password='userpass' ) def test_okina_cities(app, okina): endpoint = tests.utils.generic_endpoint_url('okina', 'cities', slug=okina.slug) assert endpoint == '/okina/test/cities' with mock.patch('passerelle.utils.Request.get') as requests_get: requests_get.return_value = tests.utils.FakedResponse(content=CITIES, status_code=200) resp = app.get(endpoint, status=200) assert requests_get.call_count == 1 assert requests_get.call_args[0][0] == 'https://okina.example.net/b2b/cities' assert requests_get.call_args[1]['auth'] == ('usertest', 'userpass') assert 'data' in resp.json assert resp.json['err'] == 0 assert len(resp.json['data']) == 2 assert resp.json['data'][0]['id'] == '83355' assert resp.json['data'][0]['insee'] == '36005' assert resp.json['data'][0]['text'] == 'ARDENTES (36120)' assert resp.json['data'][0]['lat'] is None requests_get.return_value = tests.utils.FakedResponse(content=CITIES_NEW, status_code=200) resp = app.get(endpoint, status=200) assert requests_get.call_count == 2 assert 'data' in resp.json assert resp.json['err'] == 0 assert len(resp.json['data']) == 1 assert resp.json['data'][0]['id'] == '83355' assert resp.json['data'][0]['insee'] == '36005' assert resp.json['data'][0]['text'] == 'ARDENTES (36120)' assert resp.json['data'][0]['lat'] is None def test_okina_classes(app, okina): endpoint = tests.utils.generic_endpoint_url('okina', 'classes', slug=okina.slug) assert endpoint == '/okina/test/classes' with mock.patch('passerelle.utils.Request.get') as requests_get: requests_get.return_value = tests.utils.FakedResponse(content=CLASSES, status_code=200) resp = app.get(endpoint, status=200) assert requests_get.call_count == 1 assert requests_get.call_args[0][0] == 'https://okina.example.net/b2b/classes' assert resp.json['err'] == 0 assert len(resp.json['data']) == 4 assert resp.json['data'][0]['id'] == '1' assert resp.json['data'][0]['text'] == 'École maternelle - Petite section' def test_okina_institutions(app, okina): endpoint = tests.utils.generic_endpoint_url('okina', 'institutions', slug=okina.slug) assert endpoint == '/okina/test/institutions' with mock.patch('passerelle.utils.Request.get') as requests_get: for content in (INSTITUTIONS, INSTITUTIONS_NEW): requests_get.return_value = tests.utils.FakedResponse(content=content, status_code=200) resp = app.get(endpoint, status=200) assert requests_get.call_args[0][0] == 'https://okina.example.net/b2b/institutions' assert resp.json['err'] == 0 assert len(resp.json['data']) == 2 assert resp.json['data'][0]['id'] == '277' assert resp.json['data'][0]['text'] == 'Collège Touvent' assert resp.json['data'][0]['lat'] == '46.791332586468016' assert resp.json['data'][0]['lon'] == '1.6926355997775921' resp = app.get(endpoint, params={'insee': '36005'}, status=200) assert ( requests_get.call_args[0][0] == 'https://okina.example.net/b2b/institutions?inseeCode=36005' ) assert resp.json['err'] == 0 assert len(resp.json['data']) == 2 assert resp.json['data'][0]['id'] == '277' assert resp.json['data'][0]['text'] == 'Collège Touvent' resp = app.get(endpoint + '/from-city/36005/', status=200) assert ( requests_get.call_args[0][0] == 'https://okina.example.net/b2b/institutions/subscriberCity/36005' ) assert resp.json['err'] == 0 assert len(resp.json['data']) == 2 assert resp.json['data'][0]['id'] == '277' assert resp.json['data'][0]['text'] == 'Collège Touvent' def test_okina_search(app, okina): endpoint = tests.utils.generic_endpoint_url('okina', 'search', slug=okina.slug) assert endpoint == '/okina/test/search' with mock.patch('passerelle.utils.Request.post') as requests_post: requests_post.return_value = tests.utils.FakedResponse(content=SEARCH, status_code=200) # refuse anonymous access resp = app.get(endpoint + '?lat=46.828652&lon=1.701463&institution=277', status=403) apiuser = ApiUser.objects.create(username='all', keytype='', key='') obj_type = ContentType.objects.get_for_model(okina) AccessRight.objects.create( codename='can_access', apiuser=apiuser, resource_type=obj_type, resource_pk=okina.pk ) app.get(endpoint + '?lat=46.828652', status=400) # missing argument resp = app.get(endpoint + '?lat=46.828652&lon=1.701463&institution=277', status=200) assert requests_post.call_args[0][0] == 'https://okina.example.net/b2b/wishes/search' assert json.loads(requests_post.call_args[1]['data']) == { 'type': 'CLOSE_SCHOLAR', 'from-address': '', 'from-lat': '46.828652', 'from-long': '1.701463', 'institution-id': '277', } assert resp.json['err'] == 0 assert len(resp.json['data']) == 2 assert resp.json['data'][0]['id'] == '3312' assert resp.json['data'][0]['text'] == 'Le Grand Verger' assert resp.json['data'][0]['lat'] == 46.8444186 assert resp.json['data'][0]['lon'] == 1.708197 # french decimals resp = app.get( endpoint + '?lat=46,8&lon=1,71&address=nowhere&mode=FAR_ALL&institution=280', status=200 ) assert requests_post.call_args[0][0] == 'https://okina.example.net/b2b/wishes/search' assert json.loads(requests_post.call_args[1]['data']) == { 'type': 'FAR_ALL', 'from-address': 'nowhere', 'from-lat': '46.8', 'from-long': '1.71', 'institution-id': '280', } assert resp.json['err'] == 0 def test_okina_stops_area(app, okina): endpoint = tests.utils.generic_endpoint_url('okina', 'stop-areas', slug=okina.slug) assert endpoint == '/okina/test/stop-areas' with mock.patch('passerelle.utils.Request.get') as requests_get: requests_get.return_value = tests.utils.FakedResponse(content=STOPS, status_code=200) resp = app.get(endpoint + '/from-city/36005/to-institution/276/', status=200) assert ( requests_get.call_args[0][0] == 'https://okina.example.net/b2b/stop-areas/subscriberCity/36005/institution/276' ) assert resp.json['err'] == 0 assert len(resp.json['data']) == 3 assert resp.json['data'][0]['id'] == '3281' assert resp.json['data'][0]['text'] == 'Les Loges de Dressais' def test_okina_ods(app, okina): endpoint = tests.utils.generic_endpoint_url('okina', 'origin-destinations', slug=okina.slug) assert endpoint == '/okina/test/origin-destinations' with mock.patch('passerelle.utils.Request.get') as requests_get: requests_get.return_value = tests.utils.FakedResponse(content=ODS, status_code=200) resp = app.get(endpoint, status=200) assert requests_get.call_count == 1 assert requests_get.call_args[0][0] == 'https://okina.example.net/b2b/ods' assert resp.json['err'] == 0 assert len(resp.json['data']) == 2 assert resp.json['data'][0]['id'] == 'inst:276-seq:1-6-84' assert resp.json['data'][0]['text'] == 'SYNDICAT ARDENTES 4 (semaine Aller)' assert resp.json['data'][0]['identifier'] == 'SYNDICAT ARDENTES 4 (semaine Aller)' assert resp.json['data'][0]['vehicle_journey_id'] == '84' requests_get.return_value = tests.utils.FakedResponse(content=ODS, status_code=200) resp = app.get(endpoint + '/to-institution/276/', status=200) assert requests_get.call_args[0][0] == 'https://okina.example.net/b2b/ods/institution/276' assert resp.json['err'] == 0 assert len(resp.json['data']) == 2 assert resp.json['data'][0]['id'] == 'inst:276-seq:1-6-84' assert resp.json['data'][0]['text'] == 'SYNDICAT ARDENTES 4 (semaine Aller)' assert resp.json['data'][0]['identifier'] == 'SYNDICAT ARDENTES 4 (semaine Aller)' assert resp.json['data'][0]['vehicle_journey_id'] == '84' requests_get.return_value = tests.utils.FakedResponse(content=ODS_LINES, status_code=200) resp = app.get(endpoint + '/from-stop-area/3282/to-institution/276/', status=200) assert ( requests_get.call_args[0][0] == 'https://okina.example.net/b2b/ods/institution/276/stop-area/3282' ) assert resp.json['err'] == 0 assert len(resp.json['data']) == 3 assert resp.json['data'][0]['id'] == '1' assert resp.json['data'][0]['text'] == 'LIGNE 24' assert len(resp.json['data'][0]['lines']) == 1 assert resp.json['data'][0]['lines'][0]['id'] == '24' assert resp.json['data'][0]['lines'][0]['text'] == 'LIGNE 24' assert resp.json['data'][1]['id'] == '2' assert resp.json['data'][1]['text'] == 'LIGNE 22' assert len(resp.json['data'][1]['lines']) == 1 assert resp.json['data'][1]['lines'][0]['id'] == '22' assert resp.json['data'][1]['lines'][0]['text'] == 'LIGNE 22' assert resp.json['data'][2]['id'] == '3' assert resp.json['data'][2]['text'] == 'LIGNE 24 + LIGNE 23' assert len(resp.json['data'][2]['lines']) == 2 assert resp.json['data'][2]['lines'][0]['id'] == '24' assert resp.json['data'][2]['lines'][0]['text'] == 'LIGNE 24' assert resp.json['data'][2]['lines'][1]['id'] == '23' assert resp.json['data'][2]['lines'][1]['text'] == 'LIGNE 23' requests_get.return_value = tests.utils.FakedResponse(content=ODS_FULL, status_code=200) resp = app.get(endpoint + '/from-city/36005/to-institution/276/', status=200) assert ( requests_get.call_args[0][0] == 'https://okina.example.net/b2b/ods/institution/276/subscriberCity/36005' ) assert resp.json['err'] == 0 assert len(resp.json['data']) == 1 assert resp.json['data'][0]['id'] == 'inst:276-seq:1-6-84' assert ( resp.json['data'][0]['text'] == 'Brenne 1 vers écoles Antoine Fée, Saint Martin et Saint Vincent' ) assert resp.json['data'][0]['identifier'] == 'SYNDICAT ARDENTES 4 (semaine Aller)' assert resp.json['data'][0]['vehicle_journey_id'] == '84' requests_get.return_value = tests.utils.FakedResponse(content=ODS_FULL, status_code=200) resp = app.get(endpoint + '/from-city/36005/', status=200) assert requests_get.call_args[0][0] == 'https://okina.example.net/b2b/ods/subscriberCity/36005' assert resp.json['err'] == 0 assert len(resp.json['data']) == 1 assert resp.json['data'][0]['id'] == 'inst:276-seq:1-6-84' assert ( resp.json['data'][0]['text'] == 'Brenne 1 vers écoles Antoine Fée, Saint Martin et Saint Vincent' ) assert resp.json['data'][0]['identifier'] == 'SYNDICAT ARDENTES 4 (semaine Aller)' assert resp.json['data'][0]['vehicle_journey_id'] == '84' def test_okina_topology(app, okina): endpoint = tests.utils.generic_endpoint_url('okina', 'topology', slug=okina.slug) assert endpoint == '/okina/test/topology' with mock.patch('passerelle.utils.Request.get') as requests_get: requests_get.return_value = tests.utils.FakedResponse(content=LINES, status_code=200) resp = app.get(endpoint + '/lines/', status=200) assert requests_get.call_args[0][0] == 'https://okina.example.net/b2b/topology/lines' assert resp.json['err'] == 0 assert len(resp.json['data']) == 3 assert resp.json['data'][0]['id'] == '45' assert resp.json['data'][0]['text'] == '019 - 02 - VELLES LYCEES DE CHATEAUROUX' requests_get.return_value = tests.utils.FakedResponse(content=NETWORKS, status_code=200) resp = app.get(endpoint + '/networks/', status=200) assert requests_get.call_args[0][0] == 'https://okina.example.net/b2b/topology/networks' assert resp.json['err'] == 0 assert len(resp.json['data']) == 1 assert resp.json['data'][0]['id'] == '2' assert resp.json['data'][0]['text'] == 'réseau scolaire' requests_get.return_value = tests.utils.FakedResponse(content=VEHICLE_JOURNEYS, status_code=200) resp = app.get(endpoint + '/vehicle-journeys/', status=200) assert requests_get.call_args[0][0] == 'https://okina.example.net/b2b/topology/vehicle-journeys' assert resp.json['err'] == 0 assert len(resp.json['data']) == 3 assert resp.json['data'][0]['id'] == '306' assert resp.json['data'][0]['text'] == '019 02 - VELLES LYCEES DE CHATEAUROUX' def test_okina_errors(app, okina): with mock.patch('passerelle.utils.Request.get') as requests_get: for response in ( (200, '{"foo": "bar"}'), # not a list (200, '{["foo": "bar"]}'), # list of malformatted dict (200, '

Welcome

'), # bad json (403, '

Bad creds

'), (404, '

Not Found

'), (400, '{"message": "bad request"}'), (400, '[{"message": "bad request"}]'), (500, '

Crash

'), ): requests_get.return_value = tests.utils.FakedResponse( content=response[1], status_code=response[0] ) resp = app.get('/okina/test/cities', status=200) assert resp.json['err'] == 1 if resp.json['data'] and 'status_code' in resp.json['data']: assert resp.json['data']['status_code'] == response[0] # "normal" 401/403 response, ie problem with login/password for status_code in (401, 403): requests_get.return_value = tests.utils.FakedResponse( content='''{"message": "Invalid credentials", "code": 4, "status" : %d}''' % status_code, status_code=status_code, ) resp = app.get('/okina/test/cities', status=200) assert resp.json['err'] == 1 assert resp.json['err_desc'].startswith('Invalid credentials') def test_okina_suscribe(app, okina): for service in ('subscriber', 'subscription'): endpoint = tests.utils.generic_endpoint_url('okina', service, slug=okina.slug) assert endpoint == '/okina/test/%s' % service with mock.patch('passerelle.utils.Request.get') as requests_get: resp = app.post(endpoint, status=403) assert requests_get.call_count == 0 assert resp.json['err'] == 1 assert resp.json['err_class'] == 'django.core.exceptions.PermissionDenied' # open access api = ApiUser.objects.create(username='all', keytype='', key='') obj_type = ContentType.objects.get_for_model(okina) AccessRight.objects.create( codename='can_access', apiuser=api, resource_type=obj_type, resource_pk=okina.pk ) for service in ('subscriber', 'subscription'): endpoint = tests.utils.generic_endpoint_url('okina', service, slug=okina.slug) assert endpoint == '/okina/test/%s' % service with mock.patch('passerelle.utils.Request.post') as requests_get: resp = app.post(endpoint, status=400) # no payload assert requests_get.call_count == 0 assert resp.json['err'] == 1 assert resp.json['err_class'] == 'passerelle.utils.jsonresponse.APIError' assert resp.json['err_desc'] == 'payload must be a JSON object' resp = app.post_json(endpoint, params=[], status=400) # bad payload assert requests_get.call_count == 0 assert resp.json['err'] == 1 assert resp.json['err_class'] == 'passerelle.utils.jsonresponse.APIError' assert resp.json['err_desc'] == 'payload must be a dict' requests_get.return_value = tests.utils.FakedResponse(content='{"foo":"bar"}', status_code=200) resp = app.post_json(endpoint, params={'x': 'y'}) assert requests_get.call_count == 1 assert resp.json['err'] == 0 assert resp.json['data'] == {'foo': 'bar'} # multiple subscriptions endpoint = tests.utils.generic_endpoint_url('okina', 'subscription', slug=okina.slug) with mock.patch('passerelle.utils.Request.post') as requests_post: requests_post.return_value = tests.utils.FakedResponse(content='{"sub":"ok"}', status_code=200) resp = app.post_json(endpoint, params={'lineIds': '1 ,2, 3', 'foo': 'bar'}) assert requests_post.call_count == 3 assert json.loads(requests_post.call_args_list[0][1]['data']) == {'foo': 'bar', 'lineId': '1'} assert json.loads(requests_post.call_args_list[1][1]['data']) == {'foo': 'bar', 'lineId': '2'} assert json.loads(requests_post.call_args_list[2][1]['data']) == {'foo': 'bar', 'lineId': '3'} assert resp.json['err'] == 0 assert resp.json['data'] == [{'sub': 'ok'}, {'sub': 'ok'}, {'sub': 'ok'}] # qrcode endpoint = '/okina/test/subscriber/123/qrcode' with mock.patch('passerelle.utils.Request.get') as requests_get: requests_get.return_value = tests.utils.FakedResponse( content='PNGfoo', headers={'Content-Type': 'image/png'}, status_code=200 ) resp = app.get(endpoint) assert requests_get.call_count == 1 assert resp.headers['content-type'] == 'image/png' assert resp.content == b'PNGfoo' requests_get.return_value = tests.utils.FakedResponse( content=QRCODE_400, headers={'Content-Type': 'application/json'}, status_code=400 ) resp = app.get(endpoint, status=200) assert requests_get.call_count == 2 assert resp.json['err'] == 1 assert resp.json['err_desc'].startswith( 'Subscriber with ID 123 has no passcard number to generate qr code from.' ) requests_get.return_value = tests.utils.FakedResponse( content=QRCODE_404, headers={'Content-Type': 'application/json'}, status_code=404 ) resp = app.get(endpoint, status=200) assert requests_get.call_count == 3 assert resp.json['err'] == 1 assert resp.json['err_desc'].startswith('Subscriber with ID 123 not found.')