From f0097f728e4415bc714447f100c5370cbdab40be Mon Sep 17 00:00:00 2001 From: Joseph Pintozzi Date: Sun, 3 Mar 2019 09:35:21 -0800 Subject: [PATCH] Adding check to ensure boarding passes exist --- southwest/southwest.py | 3 + tests/checkin_test.py | 11 + .../cassettes/test_checkin_without_passes.yml | 277 ++++++++++++++++++ 3 files changed, 291 insertions(+) create mode 100644 tests/fixtures/cassettes/test_checkin_without_passes.yml diff --git a/southwest/southwest.py b/southwest/southwest.py index cd8e9eb..299c3aa 100644 --- a/southwest/southwest.py +++ b/southwest/southwest.py @@ -73,6 +73,9 @@ class Reservation(): return confirmation def send_notification(self, checkindata): + if not checkindata['_links']: + print("Mobile boarding passes not eligible for this reservation") + return info_needed = checkindata['_links']['boardingPasses'] url = "{}mobile-air-operations{}".format(BASE_URL, info_needed['href']) mbpdata = self.load_json_page(url, info_needed['body']) diff --git a/tests/checkin_test.py b/tests/checkin_test.py index 0910b66..44f9391 100644 --- a/tests/checkin_test.py +++ b/tests/checkin_test.py @@ -32,6 +32,17 @@ def test_checkin(): pytest.fail("Error checking in") +@my_vcr.use_cassette() +def test_checkin_without_passes(): + phone = southwest.Notifications.Phone('1234567890') + email = southwest.Notifications.Email('test@example.com') + r.notifications = [phone, email] + try: + r.checkin() + except Exception: + pytest.fail("Error checking in") + + @my_vcr.use_cassette() def test_openflights_api(): assert southwest.timezone_for_airport('LAX').zone == "America/Los_Angeles" diff --git a/tests/fixtures/cassettes/test_checkin_without_passes.yml b/tests/fixtures/cassettes/test_checkin_without_passes.yml new file mode 100644 index 0000000..3456c77 --- /dev/null +++ b/tests/fixtures/cassettes/test_checkin_without_passes.yml @@ -0,0 +1,277 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + Content-Type: [application/json] + Host: [mobile.southwest.com] + User-Agent: [python-requests/2.21.0] + X-API-Key: [l7xxb3dcccc4a5674bada48fc6fcf0946bc8] + X-User-Experience-Id: [AAAA3198-4545-46F4-9A05-BB3E868BEFF5] + method: GET + uri: https://mobile.southwest.com/api/mobile-air-operations/v1/mobile-air-operations/page/check-in/XXXXXX + response: + body: {string: '{"checkInSessionToken": "[REDACTED]", "checkInViewReservationPage": + {"pnr": {"confirmationNumber": "XXXXXX", "passengers": "[REDACTED]"}, "cards": + [{"dates": {"first": "2019-02-18", "second": null}, "destinationDescription": + "Los Angeles", "departureDate": "2019-02-18", "departureAirport": "PDX", "departureTime": + "13:45", "arrivalAirport": "LAX", "arrivalTime": "16:05", "hazmatCheckInDisclaimer": + "By tapping ''Check in'' you acknowledge that you understand the hazardous + materials restrictions and penalties.", "flights": [{"flightNumber": "1614", + "hasWifi": true, "originAirportCode": "PDX", "destinationAirportCode": "LAX", + "destinationStationName": "Los Angeles", "departureDate": "Feb 18", "departureGate": + null, "departureTime": "13:45"}], "travelTime": "2h 20m"}], "hazmatText": + "Federal law forbids the carriage of hazardous materials such as aerosols, + fireworks, lithium batteries and flammable liquids aboard the aircraft in + your checked or carryon baggage. E-cigarettes are not permitted in checked + baggage and must be transported in carryon baggage only.", "_v1_infoNeededToCheckin": + {"href": "/v1/mobile/reservations/record-locator/XXXXXX/boarding-passes", + "method": "POST", "body": {"names": [{"firstName": "[REDACTED]", "lastName": + "[REDACTED]"}]}}, "_links": {"checkIn": {"href": "/v1/mobile-air-operations/page/check-in", + "method": "POST", "body": {"recordLocator": "[REDACTED]", "checkInSessionToken": + "[REDACTED]", "firstName": "[REDACTED]", "lastName": "[REDACTED]"}}, "travelDocuments": + null}}, "prefillPassengerAPISDocuments": null}'} + headers: + Access-Control-Allow-Credentials: ['true'] + Access-Control-Allow-Headers: ['origin, content-type, accept, authorization, + token, User-Agent, X-Forwarded-For, X-User-Experience-ID, X-Request-ID, + X-API-Key, X-Account-Number, X-Swa-Region, X-Channel-Id, X-Api-IDToken, + true-host'] + Access-Control-Allow-Methods: ['GET, POST, PUT, DELETE, OPTIONS, HEAD'] + Access-Control-Allow-Origin: [''] + Access-Control-Expose-Headers: ['X-User-Experience-ID, X-Request-ID'] + Access-Control-Max-Age: ['1'] + Cache-Control: ['max-age=0, no-cache, no-store'] + Connection: [keep-alive] + Content-Type: [application/json] + Date: ['Mon, 18 Feb 2019 07:24:48 GMT'] + Expires: ['Mon, 18 Feb 2019 07:24:48 GMT'] + Pragma: [no-cache] + Server: [Apache-Coyote/1.1] + Strict-Transport-Security: [max-age=60] + Vary: [Accept-Encoding] + X-Request-ID: [QZCIaesZQnuKkmmy37tLrg] + X-User-Experience-ID: [AAAA3198-4545-46F4-9A05-BB3E868BEFF5] + content-length: ['13088'] + status: {code: 200, message: OK} +- request: + body: '{}' + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + Content-Length: ['5921'] + Content-Type: [application/json] + Host: [mobile.southwest.com] + User-Agent: [python-requests/2.21.0] + X-API-Key: [l7xxb3dcccc4a5674bada48fc6fcf0946bc8] + X-User-Experience-Id: [AAAA3198-4545-46F4-9A05-BB3E868BEFF5] + method: POST + uri: https://mobile.southwest.com/api/mobile-air-operations/v1/mobile-air-operations/page/check-in + response: + body: {string: '{"checkInConfirmationPage": {"messages": null, "flights": [{"boundIndex": + 0, "departureTime": "13:45", "gate": null, "passengers": "[REDACTED]", "flightNumber": + "1614", "hasWifi": true, "travelTime": "2h 20m"}], "_v1_infoNeededToViewBoardingPasses": + {"href": "/v1/mobile/record-locator/XXXXXX/mobile-boarding-passes", "method": + "GET", "query": {"first-name": "[REDACTED]", "last-name": "[REDACTED]"}}, + "_links": null}}'} + headers: + Access-Control-Allow-Credentials: ['true'] + Access-Control-Allow-Headers: ['origin, content-type, accept, authorization, + token, User-Agent, X-Forwarded-For, X-User-Experience-ID, X-Request-ID, + X-API-Key, X-Account-Number, X-Swa-Region, X-Channel-Id, X-Api-IDToken, + true-host'] + Access-Control-Allow-Methods: ['GET, POST, PUT, DELETE, OPTIONS, HEAD'] + Access-Control-Allow-Origin: [''] + Access-Control-Expose-Headers: ['X-User-Experience-ID, X-Request-ID'] + Access-Control-Max-Age: ['1'] + Cache-Control: ['max-age=0, no-cache, no-store'] + Connection: [keep-alive] + Content-Type: [application/json] + Date: ['Mon, 18 Feb 2019 07:24:48 GMT'] + Expires: ['Mon, 18 Feb 2019 07:24:48 GMT'] + Pragma: [no-cache] + Server: [Apache-Coyote/1.1] + Strict-Transport-Security: [max-age=60] + Vary: [Accept-Encoding] + X-Request-ID: [YKbshcq_RJ2cCrd0FRsctQ] + X-User-Experience-ID: [AAAA3198-4545-46F4-9A05-BB3E868BEFF5] + content-length: ['12674'] + status: {code: 200, message: OK} +- request: + body: '{}' + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + Content-Length: ['6009'] + Content-Type: [application/json] + Host: [mobile.southwest.com] + User-Agent: [python-requests/2.21.0] + X-API-Key: [l7xxb3dcccc4a5674bada48fc6fcf0946bc8] + X-User-Experience-Id: [AAAA3198-4545-46F4-9A05-BB3E868BEFF5] + method: POST + uri: https://mobile.southwest.com/api/mobile-air-operations/v1/mobile-air-operations/page/check-in + response: + body: {string: '{"checkInConfirmationPage": {"messages": null, "flights": [{"boundIndex": + 0, "departureTime": "13:45", "gate": "C15", "passengers": "[REDACTED]", "flightNumber": + "1614", "hasWifi": true, "travelTime": "2h 20m"}], "_v1_infoNeededToViewBoardingPasses": + {"href": "/v1/mobile/record-locator/XXXXXX/mobile-boarding-passes", "method": + "GET", "query": {"first-name": "[REDACTED]", "last-name": "[REDACTED]"}}, + "_links": {"boardingPasses": {"href": "/v1/mobile-air-operations/page/check-in/view-boarding-pass", + "method": "POST", "body": {"recordLocator": "[REDACTED]", "firstName": "[REDACTED]", + "lastName": "[REDACTED]", "checkInSessionToken": "[REDACTED]", "travelerID": + "2005DBDA00087702"}}, "viewBoardingPassIssuance": {"href": "/v1/mobile-air-operations/page/check-in/mobile-issuance/XXXXXX", + "method": "POST", "body": {"passengers": "[REDACTED]"}}}}}'} + headers: + Access-Control-Allow-Credentials: ['true'] + Access-Control-Allow-Headers: ['origin, content-type, accept, authorization, + token, User-Agent, X-Forwarded-For, X-User-Experience-ID, X-Request-ID, + X-API-Key, X-Account-Number, X-Swa-Region, X-Channel-Id, X-Api-IDToken, + true-host'] + Access-Control-Allow-Methods: ['GET, POST, PUT, DELETE, OPTIONS, HEAD'] + Access-Control-Allow-Origin: [''] + Access-Control-Expose-Headers: ['X-User-Experience-ID, X-Request-ID'] + Access-Control-Max-Age: ['1'] + Cache-Control: ['max-age=0, no-cache, no-store'] + Connection: [keep-alive] + Content-Type: [application/json] + Date: ['Mon, 18 Feb 2019 18:10:17 GMT'] + Expires: ['Mon, 18 Feb 2019 18:10:17 GMT'] + Pragma: [no-cache] + Server: [Apache-Coyote/1.1] + Strict-Transport-Security: [max-age=60] + Vary: [Accept-Encoding] + X-Request-ID: [nqkkq63YTjK32ta1sWMlCA] + X-User-Experience-ID: [AAAA3198-4545-46F4-9A05-BB3E868BEFF5] + content-length: ['12851'] + status: {code: 200, message: OK} +- request: + body: '{"travelerID": "2005DBDA00087702"}' + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + Content-Length: ['6043'] + Content-Type: [application/json] + Host: [mobile.southwest.com] + User-Agent: [python-requests/2.21.0] + X-API-Key: [l7xxb3dcccc4a5674bada48fc6fcf0946bc8] + X-User-Experience-Id: [AAAA3198-4545-46F4-9A05-BB3E868BEFF5] + method: POST + uri: https://mobile.southwest.com/api/mobile-air-operations/v1/mobile-air-operations/page/check-in/view-boarding-pass + response: + body: {string: '{"checkInViewBoardingPassPage": {"messages": null, "mobileBoardingPassURLs": + ["https://mbp.southwest.com/mobiqa/wap/3e422f2/kSqHRGJvSGA/"], "mobileBoardingPassTabs": + [{"title": "PDX - LAX", "departureDate": "Feb 18", "destinationDescription": + "Los Angeles"}], "destinationDescription": "Los Angeles", "originAirportCode": + "PDX", "destinationAirportCode": "LAX", "dates": {"first": "2019-02-18", "second": + null}, "_v1_infoNeededForSharingBoardingPass": {"href": "/v1/mobile/record-locator/XXXXXX/operation-infos/mobile-boarding-pass/notifications", + "method": "POST", "body": {"firstName": "[REDACTED]", "lastName": "[REDACTED]"}}, + "_links": {"href": "/v1/mobile-air-operations/feature/check-in/send-boarding-pass", + "method": "POST", "body": {"recordLocator": "[REDACTED]", "checkInSessionToken": + "[REDACTED]", "travelerID": "2005DBDA00087702"}}}}'} + headers: + Access-Control-Allow-Credentials: ['true'] + Access-Control-Allow-Headers: ['origin, content-type, accept, authorization, + token, User-Agent, X-Forwarded-For, X-User-Experience-ID, X-Request-ID, + X-API-Key, X-Account-Number, X-Swa-Region, X-Channel-Id, X-Api-IDToken, + true-host'] + Access-Control-Allow-Methods: ['GET, POST, PUT, DELETE, OPTIONS, HEAD'] + Access-Control-Allow-Origin: [''] + Access-Control-Expose-Headers: ['X-User-Experience-ID, X-Request-ID'] + Access-Control-Max-Age: ['1'] + Cache-Control: ['max-age=0, no-cache, no-store'] + Connection: [keep-alive] + Content-Type: [application/json] + Date: ['Mon, 18 Feb 2019 18:10:18 GMT'] + Expires: ['Mon, 18 Feb 2019 18:10:18 GMT'] + Pragma: [no-cache] + Server: [Apache-Coyote/1.1] + Strict-Transport-Security: [max-age=60] + Vary: [Accept-Encoding] + X-Request-ID: [BPQyXOwiS2C7PQd72_9rjQ] + X-User-Experience-ID: [AAAA3198-4545-46F4-9A05-BB3E868BEFF5] + content-length: ['3927'] + status: {code: 200, message: OK} +- request: + body: '{"travelerID": "2005DBDA00087702", "recordLocator": "[REDACTED]", "checkInSessionToken": "[REDACTED]", "mediaType": "SMS", "phoneNumber": "1234567890"}' + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + Content-Length: ['160'] + Content-Type: [application/json] + Host: [mobile.southwest.com] + User-Agent: [python-requests/2.21.0] + X-API-Key: [l7xxb3dcccc4a5674bada48fc6fcf0946bc8] + X-User-Experience-Id: [AAAA3198-4545-46F4-9A05-BB3E868BEFF5] + method: POST + uri: https://mobile.southwest.com/api/mobile-air-operations/v1/mobile-air-operations/feature/check-in/send-boarding-pass + response: + body: {string: ''} + headers: + Access-Control-Allow-Credentials: ['true'] + Access-Control-Allow-Headers: ['origin, content-type, accept, authorization, + token, User-Agent, X-Forwarded-For, X-User-Experience-ID, X-Request-ID, + X-API-Key, X-Account-Number, X-Swa-Region, X-Channel-Id, X-Api-IDToken, + true-host'] + Access-Control-Allow-Methods: ['GET, POST, PUT, DELETE, OPTIONS, HEAD'] + Access-Control-Allow-Origin: [''] + Access-Control-Expose-Headers: ['X-User-Experience-ID, X-Request-ID'] + Access-Control-Max-Age: ['1'] + Cache-Control: ['max-age=0, no-cache, no-store'] + Connection: [keep-alive] + Content-Type: [application/json] + Date: ['Mon, 18 Feb 2019 18:10:18 GMT'] + Expires: ['Mon, 18 Feb 2019 18:10:18 GMT'] + Pragma: [no-cache] + Server: [Apache-Coyote/1.1] + Strict-Transport-Security: [max-age=60] + Vary: [Accept-Encoding] + X-Request-ID: [BPQyXOwiS2C7PQd72_9rjQ] + X-User-Experience-ID: [AAAA3198-4545-46F4-9A05-BB3E868BEFF5] + content-length: ['0'] + status: {code: 204, message: OK} +- request: + body: '{"travelerID": "2005DBDA00087702", "recordLocator": "[REDACTED]", "checkInSessionToken": "[REDACTED]", "mediaType": "EMAIL", "phoneNumber": "test@example.com"}' + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip, deflate'] + Connection: [keep-alive] + Content-Length: ['160'] + Content-Type: [application/json] + Host: [mobile.southwest.com] + User-Agent: [python-requests/2.21.0] + X-API-Key: [l7xxb3dcccc4a5674bada48fc6fcf0946bc8] + X-User-Experience-Id: [AAAA3198-4545-46F4-9A05-BB3E868BEFF5] + method: POST + uri: https://mobile.southwest.com/api/mobile-air-operations/v1/mobile-air-operations/feature/check-in/send-boarding-pass + response: + body: {string: ''} + headers: + Access-Control-Allow-Credentials: ['true'] + Access-Control-Allow-Headers: ['origin, content-type, accept, authorization, + token, User-Agent, X-Forwarded-For, X-User-Experience-ID, X-Request-ID, + X-API-Key, X-Account-Number, X-Swa-Region, X-Channel-Id, X-Api-IDToken, + true-host'] + Access-Control-Allow-Methods: ['GET, POST, PUT, DELETE, OPTIONS, HEAD'] + Access-Control-Allow-Origin: [''] + Access-Control-Expose-Headers: ['X-User-Experience-ID, X-Request-ID'] + Access-Control-Max-Age: ['1'] + Cache-Control: ['max-age=0, no-cache, no-store'] + Connection: [keep-alive] + Content-Type: [application/json] + Date: ['Mon, 18 Feb 2019 18:10:18 GMT'] + Expires: ['Mon, 18 Feb 2019 18:10:18 GMT'] + Pragma: [no-cache] + Server: [Apache-Coyote/1.1] + Strict-Transport-Security: [max-age=60] + Vary: [Accept-Encoding] + X-Request-ID: [BPQyXOwiS2C7PQd72_9rjQ] + X-User-Experience-ID: [AAAA3198-4545-46F4-9A05-BB3E868BEFF5] + content-length: ['0'] + status: {code: 204, message: OK} +version: 1