예제 #1
0
    def test_get_all(self):
        client = TestClient(PiccoloCRUD(table=TopSecret, exclude_secrets=True))
        response = client.get("/")
        self.assertEqual(
            response.json(),
            {"rows": [{
                "id": 1,
                "name": "My secret",
                "confidential": None
            }]},
        )

        client = TestClient(PiccoloCRUD(table=TopSecret,
                                        exclude_secrets=False))
        response = client.get("/")
        self.assertEqual(
            response.json(),
            {
                "rows": [{
                    "id": 1,
                    "name": "My secret",
                    "confidential": "secret123"
                }]
            },
        )
예제 #2
0
    def test_visible_fields_with_join(self):
        """
        Make sure that GETs with the ``__visible_fields`` parameter return the
        correct data, when using joins.
        """
        # Test 1 - should be rejected, as by default `max_joins` is 0:
        client = TestClient(PiccoloCRUD(table=Role, read_only=False))
        response = client.get(
            "/",
            params={"__visible_fields": "name,movie.name", "__order": "id"},
        )
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.content, b"Max join depth exceeded")

        # Test 2 - should work as `max_joins` is set:
        client = TestClient(
            PiccoloCRUD(table=Role, read_only=False, max_joins=1)
        )
        response = client.get(
            "/",
            params={"__visible_fields": "name,movie.name", "__order": "id"},
        )
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response.json(),
            {
                "rows": [
                    {"movie": {"name": "Star Wars"}, "name": "Luke Skywalker"}
                ]
            },
        )
예제 #3
0
    def test_pre_patch_hook(self):
        """
        Make sure pre_patch hook executes successfully
        """
        client = TestClient(
            PiccoloCRUD(
                table=Movie,
                read_only=False,
                hooks=[
                    Hook(hook_type=HookType.pre_patch, callable=remove_spaces)
                ],
            ))

        movie = Movie(name="Star Wars", rating=93)
        movie.save().run_sync()

        new_name = "Star Wars: A New Hope"
        new_name_modified = new_name.replace(" ", "")

        response = client.patch(f"/{movie.id}/", json={"name": new_name})
        self.assertTrue(response.status_code == 200)

        # Make sure the row is returned:
        response_json = json.loads(response.json())
        self.assertTrue(response_json["name"] == new_name_modified)

        # Make sure the underlying database row was changed:
        movies = Movie.select().run_sync()
        self.assertTrue(movies[0]["name"] == new_name_modified)
예제 #4
0
    def test_get_visible_fields(self):
        """
        Make sure a get can return a row successfully with the
        ``__visible_fields`` parameter.
        """
        client = TestClient(PiccoloCRUD(table=Role, read_only=False))

        movie = Movie(name="Star Wars", rating=93)
        movie.save().run_sync()

        role = Role(name="Luke Skywalker", movie=movie.id)
        role.save().run_sync()

        response = client.get(f"/{role.id}/",
                              params={"__visible_fields": "name"})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response.json(),
            {
                "name": "Luke Skywalker",
            },
        )

        # Test with unrecognised columns
        response = client.get(f"/{role.id}/",
                              params={"__visible_fields": "foobar"})
        self.assertEqual(response.status_code, 400)
        self.assertEqual(
            response.content,
            (b"No matching column found with name == foobar - the column "
             b"options are ('id', 'movie', 'name')."),
        )
예제 #5
0
    def test_visible_fields_with_readable(self):
        """
        Make sure that GETs with the ``__visible_fields`` parameter return the
        correct data, when also used wit the ``__readable`` parameter.
        """
        client = TestClient(PiccoloCRUD(table=Role, read_only=False))

        response = client.get(
            "/",
            params={
                "__visible_fields": "name,movie",
                "__readable": "true",
                "__order": "id",
            },
        )

        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response.json(),
            {
                "rows": [
                    {
                        "name": "Luke Skywalker",
                        "movie_readable": "Star Wars",
                        "movie": 1,
                    }
                ]
            },
        )
예제 #6
0
    def test_readable(self):
        """
        Make sure that bulk GETs with the ``__readable`` parameter return the
        correct data.
        """
        client = TestClient(PiccoloCRUD(table=Role, read_only=False))

        response = client.get("/", params={"__readable": "true"})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response.json(),
            {
                "rows": [
                    {
                        "id": 1,
                        "name": "Luke Skywalker",
                        "movie": 1,
                        "movie_readable": "Star Wars",
                    }
                ]
            },
        )

        response = client.get("/", params={})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response.json(),
            {"rows": [{"id": 1, "name": "Luke Skywalker", "movie": 1}]},
        )
예제 #7
0
    def test_get(self):
        """
        Make sure a get can return a row successfully.
        """
        client = TestClient(PiccoloCRUD(table=Role, read_only=False))

        movie = Movie(name="Star Wars", rating=93)
        movie.save().run_sync()

        role = Role(name="Luke Skywalker", movie=movie.id)
        role.save().run_sync()

        response = client.get(f"/{role.id}/")
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response.json(),
            {"id": role.id, "name": "Luke Skywalker", "movie": movie.id},
        )

        response = client.get(f"/{role.id}/", params={"__readable": "true"})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response.json(),
            {
                "id": role.id,
                "name": "Luke Skywalker",
                "movie": movie.id,
                "movie_readable": "Star Wars",
            },
        )

        response = client.get("/123/")
        self.assertEqual(response.status_code, 404)
예제 #8
0
    def test_get_ids_with_limit_offset(self):
        """
        Test the limit and offset parameter.
        """
        client = TestClient(PiccoloCRUD(table=Movie, read_only=False))

        Movie.insert(
            Movie(name="Star Wars", rating=93),
            Movie(name="Lord of the Rings", rating=90),
        ).run_sync()

        response = client.get("/ids/?limit=1")
        self.assertTrue(response.status_code == 200)
        self.assertEqual(response.json(), {"1": "Star Wars"})

        # Make sure only valid limit values are accepted.
        response = client.get("/ids/?limit=abc")
        self.assertEqual(response.status_code, 400)

        # Make sure only valid offset values are accepted.
        response = client.get("/ids/?offset=abc")
        self.assertEqual(response.status_code, 400)

        # Test with offset
        response = client.get("/ids/?limit=1&offset=1")
        self.assertTrue(response.status_code == 200)
        self.assertEqual(response.json(), {"2": "Lord of the Rings"})
예제 #9
0
    def test_page_sized_results(self):
        """
        Make sure the content-range header responds
        correctly requests with page_size
        """
        client = TestClient(PiccoloCRUD(table=Movie, read_only=False))

        movie = Movie(name="Star Wars", rating=93)
        movie.save().run_sync()
        movie2 = Movie(name="Blade Runner", rating=94)
        movie2.save().run_sync()
        movie3 = Movie(name="The Godfather", rating=95)
        movie3.save().run_sync()

        response = client.get("/?__page_size=1&__range_header=true")
        self.assertEqual(response.headers.get("Content-Range"), "movie 0-0/3")

        response = client.get("/?__page_size=1&__page=2&__range_header=true")
        self.assertEqual(response.headers.get("Content-Range"), "movie 1-1/3")

        response = client.get("/?__page_size=1&__page=2&__range_header=true")
        self.assertEqual(response.headers.get("Content-Range"), "movie 1-1/3")

        response = client.get("/?__page_size=99&__page=1&__range_header=true")
        self.assertEqual(response.headers.get("Content-Range"), "movie 0-2/3")
예제 #10
0
    def test_incorrect_verbs(self):
        client = TestClient(
            PiccoloCRUD(table=Movie, read_only=False, allow_bulk_delete=True)
        )

        response = client.patch("/", params={})
        self.assertEqual(response.status_code, 405)
예제 #11
0
    def test_parsing(self):
        app = PiccoloCRUD(table=Movie)

        parsed_1 = app._parse_params(
            QueryParams("tags=horror&tags=scifi&rating=90")
        )
        self.assertEqual(
            parsed_1, {"tags": ["horror", "scifi"], "rating": "90"}
        )

        parsed_2 = app._parse_params(
            QueryParams("tags[]=horror&tags[]=scifi&rating=90")
        )
        self.assertEqual(
            parsed_2, {"tags": ["horror", "scifi"], "rating": "90"}
        )
예제 #12
0
    def test_patch_succeeds(self):
        """
        Make sure a patch modifies the underlying database, and returns the
        new row data.
        """
        client = TestClient(PiccoloCRUD(table=Movie, read_only=False))

        rating = 93
        movie = Movie(name="Star Wars", rating=rating)
        movie.save().run_sync()

        new_name = "Star Wars: A New Hope"

        response = client.patch(f"/{movie.id}/", json={"name": new_name})
        self.assertTrue(response.status_code == 200)
        self.assertIsInstance(response.json(), dict)

        # Make sure the row is returned:
        response_json = response.json()
        self.assertTrue(response_json["name"] == new_name)
        self.assertTrue(response_json["rating"] == rating)

        # Make sure the underlying database row was changed:
        movies = Movie.select().run_sync()
        self.assertTrue(len(movies) == 1)
        self.assertTrue(movies[0]["name"] == new_name)
예제 #13
0
    def test_pre_patch_hook_db_lookup(self):
        """
        Make sure pre_patch hook can perform db lookups
        (function will always reset "name" to the original name)
        """
        client = TestClient(
            PiccoloCRUD(
                table=Movie,
                read_only=False,
                hooks=[
                    Hook(hook_type=HookType.pre_patch,
                         callable=look_up_existing)
                ],
            ))

        original_name = "Star Wars"
        movie = Movie(name="Star Wars", rating=93)
        movie.save().run_sync()

        new_name = "Star Wars: A New Hope"

        response = client.patch(f"/{movie.id}/", json={"name": new_name})
        self.assertTrue(response.status_code == 200)

        response_json = json.loads(response.json())
        self.assertTrue(response_json["name"] == original_name)

        movies = Movie.select().run_sync()
        self.assertTrue(movies[0]["name"] == original_name)
예제 #14
0
    def test_get_visible_fields_with_join_readable(self):
        """
        Make sure a get can return a row successfully with the
        ``__visible_fields`` parameter, when using joins and readable.
        """
        client = TestClient(
            PiccoloCRUD(table=Role, read_only=False, max_joins=1)
        )

        movie = Movie(name="Star Wars", rating=93)
        movie.save().run_sync()

        role = Role(name="Luke Skywalker", movie=movie.id)
        role.save().run_sync()

        response = client.get(
            f"/{role.id}/",
            params={
                "__visible_fields": "id,name,movie.name",
                "__readable": "true",
            },
        )
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response.json(),
            {
                "id": 1,
                "name": "Luke Skywalker",
                "movie_readable": "Star Wars",
                "movie": {
                    "name": "Star Wars",
                },
            },
        )
예제 #15
0
    def test_visible_fields(self):
        """
        Make sure that GETs with the ``__visible_fields`` parameter return the
        correct data.
        """
        client = TestClient(PiccoloCRUD(table=Movie, read_only=False))

        # Test a simple query
        response = client.get(
            "/", params={"__visible_fields": "id,name", "__order": "id"}
        )
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response.json(),
            {
                "rows": [
                    {"id": 1, "name": "Star Wars"},
                    {"id": 2, "name": "Lord of the Rings"},
                ]
            },
        )

        # Test with unrecognised columns
        response = client.get(
            "/", params={"__visible_fields": "foobar", "__order": "id"}
        )
        self.assertEqual(response.status_code, 400)
        self.assertEqual(
            response.content,
            (
                b"No matching column found with name == foobar - the column "
                b"options are ('id', 'name', 'rating')."
            ),
        )
예제 #16
0
    def test_get_schema_with_choices(self):
        """
        Make sure that if a Table has columns with choices specified, they
        appear in the schema.
        """
        class Review(Table):
            class Rating(Enum):
                bad = 1
                average = 2
                good = 3
                great = 4

            score = Integer(choices=Rating)

        client = TestClient(PiccoloCRUD(table=Review, read_only=False))

        response = client.get("/schema/")
        self.assertTrue(response.status_code == 200)

        self.assertEqual(
            response.json(),
            {
                "title": "ReviewIn",
                "type": "object",
                "properties": {
                    "score": {
                        "title": "Score",
                        "extra": {
                            "help_text": None,
                            "choices": {
                                "bad": {
                                    "display_name": "Bad",
                                    "value": 1
                                },
                                "average": {
                                    "display_name": "Average",
                                    "value": 2,
                                },
                                "good": {
                                    "display_name": "Good",
                                    "value": 3
                                },
                                "great": {
                                    "display_name": "Great",
                                    "value": 4
                                },
                            },
                        },
                        "nullable": False,
                        "type": "integer",
                    }
                },
                "help_text": None,
                "visible_fields_options": [
                    "id",
                    "score",
                ],
            },
        )
예제 #17
0
    def test_delete_404(self):
        """
        Should get a 404 if a matching row doesn't exist.
        """
        client = TestClient(PiccoloCRUD(table=Movie, read_only=False))

        response = client.delete("/123/")
        self.assertTrue(response.status_code == 404)
예제 #18
0
 def test_offset_limit_pagination(self):
     """
     If the page size is greater than one, offset and limit is applied
     """
     client = TestClient(PiccoloCRUD(table=Movie, read_only=False))
     response = client.get("/", params={"__page": 2})
     self.assertTrue(response.status_code, 403)
     self.assertEqual(response.json(), {"rows": []})
예제 #19
0
    def test_put_new(self):
        """
        We expect a 404 - we don't allow PUT requests to create new resources.
        """
        client = TestClient(PiccoloCRUD(table=Movie, read_only=False))

        response = client.put("/123/")
        self.assertTrue(response.status_code == 404)
예제 #20
0
 def test_page_size_limit(self):
     """
     If the page size limit is exceeded, the request should be rejected.
     """
     client = TestClient(PiccoloCRUD(table=Movie, read_only=False))
     response = client.get(
         "/", params={"__page_size": PiccoloCRUD.max_page_size + 1})
     self.assertTrue(response.status_code, 403)
     self.assertEqual(response.json(),
                      {"error": "The page size limit has been exceeded"})
예제 #21
0
    def test_reverse_order(self):
        """
        Make sure that descending ordering works, e.g. ``__order=-id``.
        """
        client = TestClient(PiccoloCRUD(table=Movie, read_only=False))

        rows = Movie.select().order_by(Movie.id, ascending=False).run_sync()

        response = client.get("/", params={"__order": "-id"})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json(), {"rows": rows})
예제 #22
0
    def test_get_404(self):
        """
        A 404 should be returned if there's no matching row.
        """
        client = TestClient(PiccoloCRUD(table=Movie, read_only=False))

        json = {"name": "Star Wars", "rating": "hello world"}

        response = client.post("/", json=json)
        self.assertEqual(response.status_code, 400)
        self.assertTrue(Movie.count().run_sync() == 0)
예제 #23
0
    def test_patch_fails(self):
        """
        Make sure a patch containing the wrong columns is rejected.
        """
        client = TestClient(PiccoloCRUD(table=Movie, read_only=False))

        movie = Movie(name="Star Wars", rating=93)
        movie.save().run_sync()

        response = client.patch(f"/{movie.id}/", json={"foo": "bar"})
        self.assertTrue(response.status_code == 400)
예제 #24
0
    def test_basic(self):
        """
        Make sure that bulk GETs return the correct data.
        """
        client = TestClient(PiccoloCRUD(table=Movie, read_only=False))

        rows = Movie.select().order_by(Movie.id).run_sync()

        response = client.get("/", params={"__order": "id"})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json(), {"rows": rows})
예제 #25
0
    def test_empty_list(self):
        """
        Make sure the content-range header responds correctly for empty rows
        """
        client = TestClient(PiccoloCRUD(table=Movie, read_only=False))

        response = client.get("/?__range_header=true")
        self.assertTrue(response.status_code == 200)
        # Make sure the content is correct:
        response_json = response.json()
        self.assertEqual(0, len(response_json["rows"]))
        self.assertEqual(response.headers.get("Content-Range"), "movie 0-0/0")
예제 #26
0
    def test_post_error(self):
        """
        Make sure a post returns a validation error with incorrect or missing
        data.
        """
        client = TestClient(PiccoloCRUD(table=Movie, read_only=False))

        json = {"name": "Star Wars", "rating": "hello world"}

        response = client.post("/", json=json)
        self.assertEqual(response.status_code, 400)
        self.assertTrue(Movie.count().run_sync() == 0)
예제 #27
0
    def test_false_range_header_param(self):
        """
        Make sure that __range_header=false is supported
        """
        client = TestClient(PiccoloCRUD(
            table=Movie,
            read_only=False,
        ))

        response = client.get("/?__range_header=false")
        self.assertTrue(response.status_code == 200)
        self.assertEqual(response.headers.get("Content-Range"), None)
예제 #28
0
    def test_get_schema_with_joins(self):
        """
        Make sure that if a Table has columns with joins specified, they
        appear in the schema.
        """
        client = TestClient(
            PiccoloCRUD(table=Role, read_only=False, max_joins=1))

        response = client.get("/schema/")
        self.assertTrue(response.status_code == 200)

        self.assertEqual(
            response.json(),
            {
                "title":
                "RoleIn",
                "type":
                "object",
                "properties": {
                    "movie": {
                        "title": "Movie",
                        "extra": {
                            "foreign_key": True,
                            "to": "movie",
                            "help_text": None,
                            "choices": None,
                        },
                        "nullable": True,
                        "type": "integer",
                    },
                    "name": {
                        "title": "Name",
                        "extra": {
                            "help_text": None,
                            "choices": None
                        },
                        "nullable": False,
                        "maxLength": 100,
                        "type": "string",
                    },
                },
                "help_text":
                None,
                "visible_fields_options": [
                    "id",
                    "movie",
                    "movie.id",
                    "movie.name",
                    "movie.rating",
                    "name",
                ],
            },
        )
예제 #29
0
    def test_delete_single(self):
        """
        Make sure an existing row is deleted successfully.
        """
        client = TestClient(PiccoloCRUD(table=Movie, read_only=False))

        movie = Movie(name="Star Wars", rating=93)
        movie.save().run_sync()

        response = client.delete(f"/{movie.id}/")
        self.assertTrue(response.status_code == 204)

        self.assertTrue(Movie.count().run_sync() == 0)
예제 #30
0
    def test_get_visible_fields_with_join(self):
        """
        Make sure a get can return a row successfully
        with the ``__visible_fields`` parameter, when using joins.
        """
        movie = Movie(name="Star Wars", rating=93)
        movie.save().run_sync()

        role = Role(name="Luke Skywalker", movie=movie.id)
        role.save().run_sync()

        # Test 1 - should be rejected, as by default `max_joins` is 0:
        client = TestClient(PiccoloCRUD(table=Role, read_only=False))
        response = client.get(
            f"/{role.id}/",
            params={"__visible_fields": "name,movie.name"},
        )
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.content, b"Max join depth exceeded")

        # Test 2 - should work as `max_joins` is set:
        client = TestClient(
            PiccoloCRUD(table=Role, read_only=False, max_joins=1)
        )

        response = client.get(
            f"/{role.id}/", params={"__visible_fields": "name,movie.name"}
        )
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            response.json(),
            {
                "name": "Luke Skywalker",
                "movie": {
                    "name": "Star Wars",
                },
            },
        )