def test_park_garage_full(self):
        garage_doc = get_garage_data(fn='full_garage_v1.json')

        # ---------- call method ----------
        # vehicle type 1 is car
        self.req.body = {'vehicle_type': 1}
        with self.assertRaises(APIError) as context:
            http_put(self.req, self.resp, self.params, document=garage_doc)

        # ---------- evaluate response ----------
        self.assertEqual(context.exception.code, 'Garage Full')
    def test_park_bus(self):
        # vehicle type 2 is bus
        self.req.body = {'vehicle_type': 2}

        # ---------- call method ----------
        # get original
        original = get_garage_data()

        http_put(self.req, self.resp, self.params)

        # get updated document
        updated = get_garage_data()

        # ---------- evaluate response ----------
        # assert response body
        self.assertIn('vehicle_id', self.resp.body)
        self.assertIn('vehicle_type', self.resp.body)
        self.assertIn('level', self.resp.body)
        self.assertIn('row', self.resp.body)
        self.assertIn('spot_id', self.resp.body)
        self.assertIn('spot_type', self.resp.body)
        self.assertEqual('BUS', self.resp.body['vehicle_type'])

        # assert response status
        self.assertEqual(self.resp.status, status_codes.HTTP_CREATED)

        # assert document has changed
        self.assertNotEqual(original, updated)

        # assert 5 spots occupied
        spots = Garage.decouple_spot_id(self.resp.body['spot_id'])
        self.assertEqual(len(spots), 5)

        last_spot = int(spots[0]) - 1
        for spot in spots:
            # assert spot is consecutive
            self.assertEqual(int(spot), last_spot + 1)
            last_spot = int(spot)

            # assert spot was empty in original
            original_location = \
                original['levels'][self.resp.body['level']]['rows'][self.resp.body['row']]['spots'][spot]
            self.assertEqual({}, original_location['vehicle'])

            # assert vehicle is in location
            updated_location = \
                updated['levels'][self.resp.body['level']]['rows'][self.resp.body['row']]['spots'][spot]
            self.assertEqual(self.resp.body['vehicle_id'],
                             updated_location['vehicle']['vehicle_id'])
            self.assertEqual(self.req.body['vehicle_type'],
                             updated_location['vehicle']['vehicle_type'])

            # assert location is permissible for vehicle type
            self.assertEqual(updated_location['spot_type'], 2)
    def test_park_motorcycle(self):
        # vehicle type 0 is motorcycle
        self.req.body = {'vehicle_type': 0}

        # ---------- call method ----------
        # get original document
        original = get_garage_data()

        http_put(self.req, self.resp, self.params)

        # get updated document
        updated = get_garage_data()

        # ---------- evaluate response ----------
        # assert response body
        self.assertIn('vehicle_id', self.resp.body)
        self.assertIn('vehicle_type', self.resp.body)
        self.assertIn('level', self.resp.body)
        self.assertIn('row', self.resp.body)
        self.assertIn('spot_id', self.resp.body)
        self.assertIn('spot_type', self.resp.body)
        self.assertEqual('MOTORCYCLE', self.resp.body['vehicle_type'])

        # assert response status
        self.assertEqual(self.resp.status, status_codes.HTTP_CREATED)

        # assert document has changed
        self.assertNotEqual(original, updated)

        # assert 1 spots occupied
        spots = Garage.decouple_spot_id(self.resp.body['spot_id'])
        self.assertEqual(len(spots), 1)

        for spot in spots:
            # assert spot was empty in original
            original_location = \
                original['levels'][self.resp.body['level']]['rows'][self.resp.body['row']]['spots'][spot]
            self.assertEqual({}, original_location['vehicle'])

            # assert vehicle is in location
            updated_location = \
                updated['levels'][self.resp.body['level']]['rows'][self.resp.body['row']]['spots'][spot]
            self.assertEqual(self.resp.body['vehicle_id'],
                             updated_location['vehicle']['vehicle_id'])
            self.assertEqual(self.req.body['vehicle_type'],
                             updated_location['vehicle']['vehicle_type'])

            # assert location is permissible for vehicle type
            self.assertIn(updated_location['spot_type'], [0, 1, 2])
    def test_park_invalid_vehicle_type(self):
        # get original
        original = get_garage_data()

        # ---------- call method ----------
        self.req.body = {'vehicle_type': 'invalid'}

        # get not_updated
        not_updated = get_garage_data()

        with self.assertRaises(APIError) as context:
            http_put(self.req, self.resp, self.params)

        # ---------- evaluate response ----------
        self.assertEqual(context.exception.code, 'Invalid Input: vehicle_type')
        self.assertEqual(original, not_updated)