diff --git a/.ciignore b/.ciignore index cc6f2219b6f4a..3f0dbdc09e812 100644 --- a/.ciignore +++ b/.ciignore @@ -5,6 +5,5 @@ assets/* docs/* community/* install-manifests/* -.circleci/* .ciignore .gitignore diff --git a/.circleci/config.yml b/.circleci/config.yml index 79d39ca39045b..cb0bfb45aa0eb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -63,6 +63,40 @@ refs: command: | DATABASE_URL="postgres://gql_test:@localhost:5432/gql_test" make ci-test + # ref pytest server job + pytest_server: &pytest_server + working_directory: ~/graphql-engine + steps: + - checkout + - restore_cache: + keys: + - server-deps-cache-{{ checksum "server/graphql-engine.cabal" }}-{{ checksum "server/stack.yaml" }} + - attach_workspace: + at: /build + - *wait_for_postgres + - run: + command: /build/_server_output/graphql-engine serve + background: true + environment: + HASURA_GRAPHQL_DATABASE_URL: postgres://gql_test:@localhost:5432/gql_test + - run: + name: create test output dir + command: | + mkdir -p /build/_server_test_output/$PG_VERSION + - run: + name: pytest the server + working_directory: ./server/tests-py + environment: + DATABASE_URL: postgres://gql_test:@localhost:5432/gql_test + HGE_URL: http://localhost:8080 + command: | + pip3 install -r requirements.txt + pytest -vv --hge-url="$HGE_URL" --pg-url="$DATABASE_URL" + ## commented for the timesake + # stack --system-ghc hpc report /build/_server_output/graphql-engine.tix --destdir /build/_server_test_output/$PG_VERSION + - store_artifacts: + path: /build/_server_test_output + destination: server_test version: 2 jobs: @@ -155,6 +189,34 @@ jobs: - image: circleci/postgres:9.5-alpine <<: *test_pg_env + # pytest the server with postgres versions >= 9.5 + pytest_server_pg_10.4: + <<: *pytest_server + environment: + PG_VERSION: "10_4" + docker: + - image: hasura/graphql-engine-server-builder:v0.3.2 + - image: circleci/postgres:10.4-alpine + <<: *test_pg_env + + pytest_server_pg_9.6: + <<: *pytest_server + environment: + PG_VERSION: "9_6" + docker: + - image: hasura/graphql-engine-server-builder:v0.3.2 + - image: circleci/postgres:9.6-alpine + <<: *test_pg_env + + pytest_server_pg_9.5: + <<: *pytest_server + environment: + PG_VERSION: "9_5" + docker: + - image: hasura/graphql-engine-server-builder:v0.3.2 + - image: circleci/postgres:9.5-alpine + <<: *test_pg_env + # test and build cli test_and_build_cli: docker: @@ -280,12 +342,27 @@ workflows: <<: *filter_only_vtags requires: - build_server + - pytest_server_pg_10.4: + <<: *filter_only_vtags + requires: + - build_server + - pytest_server_pg_9.6: + <<: *filter_only_vtags + requires: + - build_server + - pytest_server_pg_9.5: + <<: *filter_only_vtags + requires: + - build_server - all_server_tests_pass: <<: *filter_only_vtags requires: - test_server_pg_10.4 - test_server_pg_9.6 - test_server_pg_9.5 + - pytest_server_pg_10.4 + - pytest_server_pg_9.6 + - pytest_server_pg_9.5 - test_and_build_cli: <<: *filter_only_vtags requires: diff --git a/.circleci/server-builder.dockerfile b/.circleci/server-builder.dockerfile index 347022499e38a..a8e6b6c4be67b 100644 --- a/.circleci/server-builder.dockerfile +++ b/.circleci/server-builder.dockerfile @@ -7,7 +7,7 @@ ARG stack_ver="1.7.1" # Install GNU make, curl, git and docker client. Required to build the server RUN apt-get -y update \ && apt-get -y upgrade \ - && apt-get install -y curl g++ gcc libc6-dev libpq-dev libffi-dev libgmp-dev make xz-utils zlib1g-dev git gnupg upx netcat \ + && apt-get install -y curl g++ gcc libc6-dev libpq-dev libffi-dev libgmp-dev make xz-utils zlib1g-dev git gnupg upx netcat python3 python3-pip \ && curl -Lo /tmp/docker-${docker_ver}.tgz https://download.docker.com/linux/static/stable/x86_64/docker-${docker_ver}.tgz \ && tar -xz -C /tmp -f /tmp/docker-${docker_ver}.tgz \ && mv /tmp/docker/* /usr/bin \ @@ -20,4 +20,4 @@ RUN apt-get -y update \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /usr/share/doc/ \ && rm -rf /usr/share/man/ \ - && rm -rf /usr/share/locale/ \ No newline at end of file + && rm -rf /usr/share/locale/ diff --git a/server/Makefile b/server/Makefile index 38ea92706bb53..4ccbf9a7afd9f 100644 --- a/server/Makefile +++ b/server/Makefile @@ -34,6 +34,8 @@ ci-binary: mkdir -p $(build_output) cp $(build_dir)/$(project)/$(project) $(build_output) cp "$(build_dir)/$(project)-test/$(project)-test" $(build_output) + ## commented for now + #cp $(project_dir)/$(project).tix $(build_output) echo "$(version)" > $(build_output)/version.txt ci-test: diff --git a/server/testcases/add_column.json b/server/testcases/add_column.json deleted file mode 100644 index cf86de7a38281..0000000000000 --- a/server/testcases/add_column.json +++ /dev/null @@ -1,49 +0,0 @@ - -{ - "description": "add column test", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "add column", - "url": "/api/1/query", - "user_id": "1", - "role": "admin", - "status_code": 200, - "method": "POST", - "sql_check": [ - "SELECT 1 where EXISTS (select * from information_schema.columns where table_name = 'author' AND column_name='age')" - ], - "request": { - "kind": "add_column", - "body" : { - "table": "author", - "column": { - "name": "age", - "type": "integer" - } - } - } - }, - { - "name": "add column", - "url": "/api/1/query", - "user_id": "1", - "role": "admin", - "status_code": 400, - "method": "POST", - "request": { - "kind": "add_column", - "body" : { - "table": "author", - "column": { - "name": "id", - "type": "integer" - } - } - } - } - - ] -} \ No newline at end of file diff --git a/server/testcases/add_existing_table.json b/server/testcases/add_existing_table.json deleted file mode 100644 index b1bfcb8c0dc73..0000000000000 --- a/server/testcases/add_existing_table.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "description": "schema test", - "depends": [], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "pre_sql": [ - "CREATE TABLE test(id serial);" - ], - - "post_sql": [ - "DROP TABLE test;" - ], - - "request": { - "kind": "add_existing_table", - "body": { - "table": "test" - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "request": { - "kind": "add_existing_table", - "body": { - "table": "test" - } - } - } - ] -} diff --git a/server/testcases/add_existing_view.json b/server/testcases/add_existing_view.json deleted file mode 100644 index 2f2f3ae5b5812..0000000000000 --- a/server/testcases/add_existing_view.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "description": "add existing view", - "depends": [], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "pre_sql": [ - "CREATE TABLE test(id serial)", - "CREATE VIEW test_view AS (SELECT id FROM test WHERE id > 10)" - ], - "request": { - "kind": "add_existing_view", - "body": { - "view": "test_view" - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "response": { - "path": "$", - "error": "view already tracked" - }, - "user_id": "1", - "request": { - "kind": "add_existing_view", - "body": { - "view": "test_view" - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/alter_col_nullable.json b/server/testcases/alter_col_nullable.json deleted file mode 100644 index c47d2747ad6ad..0000000000000 --- a/server/testcases/alter_col_nullable.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "description": "alter column nullable test", - "depends": [], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "__type": "create_table", - "name": "a", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "integer", - "name": "b", - "nullable": false - } - ] - } - } - }, - { - "name": "insert with null", - "url": "/api/1/table/a/insert", - "role": "admin", - "user_id": "1", - "status_code": 400, - "request": { - "objects": [ - {} - ] - }, - "response": { - "path": "$", - "error": "Not-NULL violation. null value in column \"b\" violates not-null constraint" - }, - "method": "POST" - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "alter_column_nullable", - "body": { - "table": "a", - "nullable": true, - "column": "b" - } - } - }, - { - "name": "insert with null (should fail)", - "url": "/api/1/table/a/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [ - {} - ] - }, - "response": { - "affected_rows": 1 - }, - "method": "POST" - } - ] -} \ No newline at end of file diff --git a/server/testcases/alter_column_default.json b/server/testcases/alter_column_default.json deleted file mode 100644 index 303944c64727a..0000000000000 --- a/server/testcases/alter_column_default.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "description": "alter defaults test", - "depends": [], - "items": [ - { - "name": "alter_column_default", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": - { - "primary_key": [ - "id" - ], - "name": "a", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "timetz", - "name": "ts_sql", - "default_sql": "now()" - } - ] - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "response": {"path":"$","error":"Expecting ISO8601 formatted time"}, - "method": "POST", - "user_id": "1", - "request": { - "kind": "alter_column_default", - "body": - { - "table": "a", - "new_default": "now()", - "column": "ts_sql" - } - } - } - ] - } \ No newline at end of file diff --git a/server/testcases/alter_column_type.json b/server/testcases/alter_column_type.json deleted file mode 100644 index be5fe5866f96e..0000000000000 --- a/server/testcases/alter_column_type.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "description": "alter column type test", - "depends": [], - "items": [ - { - "name": "alter_column_default", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": - { - "primary_key": [ - "id" - ], - "name": "a", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "integer", - "name": "ts_sql", - "default_sql": "now()" - } - ] - } - } - }, - { - "name": "alter_column_type", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "request": { - "kind": "alter_column_type", - "body": - { - "table": "a", - "new_type": "text", - "column": "ts_sql" - } - } - }, - { - "name": "alter_column_type nonexistent", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "request": { - "kind": "alter_column_type", - "body": - { - "table": "a", - "new_type": "text", - "column": "blah" - } - } - } - ] - } \ No newline at end of file diff --git a/server/testcases/author_article_category.json b/server/testcases/author_article_category.json deleted file mode 100644 index 3358160868451..0000000000000 --- a/server/testcases/author_article_category.json +++ /dev/null @@ -1,199 +0,0 @@ -{ - "description": "author article category schema", - "depends": [], - "items": [ - { - "name": "create author table", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "name": "author", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "varchar", - "name": "email" - }, - { - "type": "varchar", - "name": "name" - }, - { - "type": "integer", - "name": "auth_id" - } - ] - } - } - }, - { - "name": "create category table", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "__type": "create_table", - "name": "category", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "text", - "name": "description" - }, - { - "type": "varchar", - "name": "name" - } - ] - } - } - }, - { - "name": "create article table", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "__type": "create_table", - "name": "article", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "numeric", - "name": "rating" - }, - { - "type": "text", - "name": "title" - }, - { - "type": "text", - "name": "content" - }, - { - "type": "integer", - "references": { - "column": "id", - "table": "author" - }, - "name": "author_id" - }, - { - "type": "integer", - "references": { - "column": "id", - "table": "category" - }, - "name": "category_id" - }, - { - "type": "boolean", - "name": "is_published" - } - ] - } - } - }, - { - "name": "create author->article", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_object_relationship", - "body": { - "using": "author_id", - "name": "author", - "table": "article" - } - } - }, - { - "name": "create article->category", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_object_relationship", - "body": { - "using": "category_id", - "name": "category", - "table": "article" - } - } - }, - { - "name": "create author->articles", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_array_relationship", - "body": { - "using": { - "column": "author_id", - "table": "article" - }, - "name": "articles", - "table": "author" - } - } - }, - { - "name": "create category->articles", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_array_relationship", - "body": { - "using": { - "column": "category_id", - "table": "article" - }, - "name": "articles", - "table": "category" - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/changeset_qerr.json b/server/testcases/changeset_qerr.json deleted file mode 100644 index decc71d53cd6e..0000000000000 --- a/server/testcases/changeset_qerr.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "description": "changeset qerr test", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "add column 1", - "url": "/api/1/query", - "user_id": "1", - "role": "admin", - "status_code": 400, - "method": "POST", - "request": { - "kind": "add_column", - "body": { - "__type": "add_column", - "table": "author", - "column": "age" - } - } - }, - { - "name": "add column 2 (check for lockup)", - "url": "/api/1/query", - "user_id": "1", - "role": "admin", - "status_code": 400, - "method": "POST", - "request": { - "kind": "add_column", - "body": { - "__type": "add_column", - "table": "author", - "column": "age" - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/check_author_table_permissions.json b/server/testcases/check_author_table_permissions.json deleted file mode 100644 index 95cb99b4824a7..0000000000000 --- a/server/testcases/check_author_table_permissions.json +++ /dev/null @@ -1,220 +0,0 @@ -{ - "description": "check author table permissions", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "create author as user", - "url": "/api/1/query", - "role": "user", - "user_id": "1", - "response": {"path":"$","error":"insert on \"author\" for role \"user\" is not allowed. "}, - "status_code": 400, - "request": { - "kind": "insert", - "body": { - "table": "author", - "objects": [ - { - "name": "Balaji", - "auth_id": 1, - "email": "google@balaji.com" - } - ], - "returning": [ - "id" - ] - } - }, - "method": "POST" - }, - { - "name": "create author B1 as admin", - "url": "/api/1/table/author/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [ - { - "name": "B1", - "auth_id": 1, - "email": "google@gmail.com" - } - ], - "returning": [ - "id" - ] - }, - "response": { - "affected_rows": 1, - "returning": [ - { - "id": 1 - } - ] - }, - "method": "POST" - }, - { - "name": "create author B2 as admin", - "url": "/api/1/table/author/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [ - { - "name": "B2", - "auth_id": 2, - "email": "google@balaji.com" - } - ], - "returning": [ - "id" - ] - }, - "response": { - "affected_rows": 1, - "returning": [ - { - "id": 2 - } - ] - }, - "method": "POST" - }, - { - "name": "get author as admin", - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "kind": "select", - "body": { - "table": "author", - "columns": [ - "name" - ] - } - }, - "response": [ - { - "name": "B1" - }, - { - "name": "B2" - } - ], - "method": "POST" - }, - { - "name": "select as user id 1", - "url": "/api/1/query", - "role": "user", - "user_id": "1", - "status_code": 200, - "request": { - "kind": "select", - "body": { - "table": "author", - "columns": [ - "name" - ] - } - }, - "response": [ - { - "name": "B1" - } - ], - "method": "POST" - }, - { - "name": "select as user id 2", - "url": "/api/1/query", - "role": "user", - "user_id": "2", - "status_code": 200, - "request": { - "kind": "select", - "body": { - "table": "author", - "columns": [ - "name" - ] - } - }, - "response": [ - { - "name": "B2" - } - ], - "method": "POST" - }, - { - "name": "update B1 as user 1", - "url": "/api/1/table/author/update", - "role": "user", - "user_id": "1", - "status_code": 200, - "method": "POST", - "response": { - "affected_rows": 1 - }, - "request": { - "where": { - "name": "B1" - }, - "$set": { - "name": "B1 (new)" - } - } - }, - { - "name": "update B1 as user 2", - "url": "/api/1/table/author/update", - "role": "user", - "user_id": "2", - "status_code": 200, - "method": "POST", - "response": { - "affected_rows": 0 - }, - "request": { - "where": { - "name": "B1" - }, - "$set": { - "name": "B1 sucks" - } - } - }, - { - "name": "update email as user", - "url": "/api/1/query", - "role": "user", - "user_id": "1", - "status_code": 400, - "response": { - "path": "$.$set", - "error": "role \"user\" does not have permission to update column \"email\"" - }, - "method": "POST", - "request": { - "kind": "update", - "body": { - "table": "author", - "where": { - "name": "B1" - }, - "$set": { - "email": "B1@gmail.com" - } - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/check_constraint.json b/server/testcases/check_constraint.json deleted file mode 100644 index df98984fd0980..0000000000000 --- a/server/testcases/check_constraint.json +++ /dev/null @@ -1,269 +0,0 @@ -{ - "description": "check constraint test", - "depends": [], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "status_code": 200, - "method": "POST", - "request": { - "kind": "create_table", - "body": { - "name": "user", - "columns": [ - { - "type": "varchar", - "name": "name" - }, - { - "type": "serial", - "name": "id" - } - ], - "primary_key": [ - "id" - ], - "unique_constraints": [ - { - "columns": [ - "id", - "name" - ] - } - ] - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "status_code": 200, - "method": "POST", - "request": { - "kind": "create_table", - "body": { - "__type": "create_table", - "name": "author", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "varchar", - "name": "email" - }, - { - "type": "varchar", - "name": "name" - }, - { - "type": "integer", - "name": "auth_id" - } - ], - "primary_key": [ - "id" - ], - "foreign_key_constraints": [ - { - "mapping": { - "auth_id": "id", - "name": "name" - }, - "columns": [ - "auth_id", - "name" - ], - "ref_table": "user", - "ref_columns": [ - "id", - "name" - ] - } - ], - "check_constraints": [ - { - "check": { - "$or": [ - { - "email": { - "$like": "%@gmail.com" - } - } - ] - } - } - ], - "unique_constraints": [ - { - "columns": [ - "name", - "email" - ] - } - ] - } - } - }, - { - "name": "create user Spock as admin", - "url": "/api/1/table/user/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [ - { - "name": "Spock", - "id": 1 - } - ], - "returning": [ - "id" - ] - }, - "response": { - "affected_rows": 1, - "returning": [ - { - "id": 1 - } - ] - }, - "method": "POST" - }, - { - "name": "create user Vader as admin", - "url": "/api/1/table/user/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [ - { - "name": "Vader", - "id": 2 - } - ], - "returning": [ - "id" - ] - }, - "response": { - "affected_rows": 1, - "returning": [ - { - "id": 2 - } - ] - }, - "method": "POST" - }, - { - "name": "create author Spock as admin", - "url": "/api/1/table/author/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [ - { - "name": "Spock", - "auth_id": 1, - "email": "spock@gmail.com" - } - ], - "returning": [ - "id" - ] - }, - "response": { - "affected_rows": 1, - "returning": [ - { - "id": 1 - } - ] - }, - "method": "POST" - }, - { - "name": "create author Vader as admin", - "url": "/api/1/table/author/insert", - "role": "admin", - "user_id": "1", - "status_code": 400, - "request": { - "objects": [ - { - "name": "Vader", - "auth_id": 1, - "email": "vader@b56.com" - } - ], - "returning": [ - "id" - ] - }, - "method": "POST", - "response": { - "path": "$", - "error": "Check constraint violation. new row for relation \"author\" violates check constraint \"author_email_check\"" - } - }, - { - "name": "create Spock as admin with diff auth id", - "url": "/api/1/table/author/insert", - "role": "admin", - "user_id": "1", - "status_code": 400, - "request": { - "objects": [ - { - "name": "Spock", - "auth_id": 1, - "email": "spock@gmail.com" - } - ], - "returning": [ - "id" - ] - }, - "response": { - "path": "$", - "error": "Uniqueness violation. duplicate key value violates unique constraint \"author_name_email_key\"" - }, - "method": "POST" - }, - { - "name": "create Jack", - "url": "/api/1/table/author/insert", - "role": "admin", - "user_id": "1", - "status_code": 400, - "request": { - "objects": [ - { - "name": "Jack", - "auth_id": 1, - "email": "jack@gmail.com" - } - ], - "returning": [ - "id" - ] - }, - "response": { - "path": "$", - "error": "Foreign key violation. insert or update on table \"author\" violates foreign key constraint \"author_auth_id_fkey\"" - }, - "method": "POST" - } - ] -} \ No newline at end of file diff --git a/server/testcases/count.json b/server/testcases/count.json deleted file mode 100644 index ad96bb1d4b167..0000000000000 --- a/server/testcases/count.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "description": "check author table permissions", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "create author B1 as admin", - "url": "/api/1/table/author/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [ - { - "name": "B1", - "auth_id": 1, - "email": "google@gmail.com" - }, - { - "name": "B2", - "auth_id": 1, - "email": "google@pmail.com" - } - ], - "returning": [ - "id" - ] - }, - "response": { - "affected_rows": 2, - "returning": [ - { - "id": 1 - }, - { - "id": 2 - } - ] - }, - "method": "POST" - }, - { - "name": "create author B1 as admin", - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "response": { - "count": 2 - }, - "status_code": 200, - "request": { - "kind": "count", - "body": { - "table": "author" - } - }, - "method": "POST" - } - ] -} \ No newline at end of file diff --git a/server/testcases/create_array_relationship.json b/server/testcases/create_array_relationship.json deleted file mode 100644 index 63cf437adb5e2..0000000000000 --- a/server/testcases/create_array_relationship.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "description": "alter column type test", - "depends": [], - "items": [ - { - "name": "create table", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "name": "b", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "integer", - "name": "c" - } - ] - } - } - }, - { - "name": "create table", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "name": "a", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "integer", - "name": "b", - "references": { - "column": "id", - "table": "b" - } - } - ] - } - } - }, - { - "name": "create arr rel", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_array_relationship", - "body": { - "name": "a_rel", - "table": "b", - "using": { - "table": "a", - "column": "b" - } - } - } - }, - { - "name": "create arr rel", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_array_relationship", - "body": { - "name": "a_rel", - "table": "b", - "using": { - "table": "a", - "column": "b" - } - } - } - }, - { - "name": "add column", - "url": "/api/1/query", - "user_id": "1", - "role": "admin", - "status_code": 400, - "method": "POST", - "request": { - "kind": "add_column", - "body" : { - "table": "b", - "column": { - "name": "a_rel", - "type": "integer" - } - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/create_object_relationship.json b/server/testcases/create_object_relationship.json deleted file mode 100644 index 5278447495b22..0000000000000 --- a/server/testcases/create_object_relationship.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "description": "alter column type test", - "depends": [], - "items": [ - { - "name": "create table", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "name": "b", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "integer", - "name": "c" - } - ] - } - } - }, - { - "name": "create table", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "name": "a", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "integer", - "name": "b", - "references": { - "column": "id", - "table": "b" - } - } - ] - } - } - }, - { - "name": "create obj rel", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_object_relationship", - "body": { - "name": "b_rel", - "table": "a", - "using": "b" - } - } - }, - { - "name": "add column", - "url": "/api/1/query", - "user_id": "1", - "role": "admin", - "status_code": 400, - "method": "POST", - "request": { - "kind": "add_column", - "body" : { - "table": "a", - "column": { - "name": "b_rel", - "type": "integer" - } - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/create_table.json b/server/testcases/create_table.json deleted file mode 100644 index 13ee367aeed3e..0000000000000 --- a/server/testcases/create_table.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "description": "schema test", - "depends": [], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "name": "author", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "varchar", - "name": "email" - }, - { - "type": "varchar", - "name": "name" - }, - { - "type": "integer", - "name": "auth_id" - } - ] - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "name": "article", - "columns": [{ - "type": "serial", - "name": "id" - }] - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "name": "article", - "columns": [{ - "type": "serial", - "name": "id" - }] - } - } - } - ] -} diff --git a/server/testcases/defaults.json b/server/testcases/defaults.json deleted file mode 100644 index ef071e9e5ddb6..0000000000000 --- a/server/testcases/defaults.json +++ /dev/null @@ -1,163 +0,0 @@ -{ - "description": "defaults test", - "depends": [], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "sql_check": [ - "SELECT 1 WHERE EXISTS(SELECT * from information_schema.columns where column_name='ts_sql' AND column_default='now()')" - ], - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "name": "a", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "timetz", - "name": "ts_sql", - "default": { - "__type": "expression", - "expression": "now()" - } - } - ] - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": { - "path": "$.columns", - "error": "Expecting ISO8601 formatted time" - }, - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "__type": "create_table", - "name": "b", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "timetz", - "name": "ts", - "default": { - "__type": "value", - "value": "now()" - } - } - ] - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": { - "path": "$.columns", - "error": "expected Int32, encountered String" - }, - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "__type": "create_table", - "name": "c", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "integer", - "name": "ts", - "default": "5" - } - ] - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "sql_check": [ - "SELECT 1 WHERE EXISTS(SELECT * from information_schema.columns where column_name='ts' AND column_default :: integer=5)" - ], - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "__type": "create_table", - "name": "c", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "integer", - "name": "ts", - "default": 5 - } - ] - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "sql_check": [ - "SELECT 1 WHERE EXISTS(SELECT * from information_schema.columns where column_name='kk' AND column_default :: integer=100)" - ], - "request": { - "kind": "add_column", - "body": { - "table": "c", - "column": { - "type": "integer", - "default": 100, - "name": "kk" - } - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/drop_column.json b/server/testcases/drop_column.json deleted file mode 100644 index 081c2961947c3..0000000000000 --- a/server/testcases/drop_column.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "description": "drop column test", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_column", - "body":{ - "table": "article", - "column": "author_id", - "cascade": true - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/drop_column_manual_delete.json b/server/testcases/drop_column_manual_delete.json deleted file mode 100644 index e1872fb6bde8f..0000000000000 --- a/server/testcases/drop_column_manual_delete.json +++ /dev/null @@ -1,206 +0,0 @@ -{ - "description": "drop column test", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "drop col", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": {"path":"$","error":"can not delete due to the following dependent objects - [(\"article\",foreign_key_constraint,\"article_author_id_fkey\"),(\"article\",relationship,\"author\"),(\"author\",relationship,\"articles\"),(\"article\",permission,\"user (insert)\"),(\"article\",permission,\"user (select)\"),(\"article\",permission,\"user (update)\"),(\"article\",permission,\"user (delete)\")]"}, - "request": { - "kind": "drop_column", - "body": { - "table": "article", - "column": "author_id", - "cascade": false - } - } - }, - { - "name": "drop perm", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_insert_permission", - "body": { - "table": "article", - "role": "user" - } - } - }, - { - "name": "drop perm", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_select_permission", - "body": { - "table": "article", - "role": "user" - } - } - }, - { - "name": "drop perm", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_update_permission", - "body": { - "table": "article", - "role": "user" - } - } - }, - { - "name": "drop perm", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_delete_permission", - "body": { - "table": "article", - "role": "user" - } - } - }, - { - "name": "drop col", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": { - "path": "$", - "error": "can not delete due to the following dependent objects - [(\"article\",foreign_key_constraint,\"article_author_id_fkey\"),(\"article\",relationship,\"author\"),(\"author\",relationship,\"articles\")]" - }, - "request": { - "kind": "drop_column", - "body": { - "table": "article", - "column": "author_id", - "cascade": false - } - } - }, - { - "name": "drop article.author", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_relationship", - "body": { - "table": "article", - "relationship": "author" - } - } - }, - { - "name": "drop col", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": { - "path": "$", - "error": "can not delete due to the following dependent objects - [(\"article\",foreign_key_constraint,\"article_author_id_fkey\"),(\"author\",relationship,\"articles\")]" - }, - "request": { - "kind": "drop_column", - "body": { - "table": "article", - "column": "author_id", - "cascade": false - } - } - }, - { - "name": "drop author.articles", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_relationship", - "body": { - "table": "author", - "relationship": "articles" - } - } - }, - { - "name": "drop col", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": { - "path": "$", - "error": "can not delete due to the following dependent objects - [(\"article\",foreign_key_constraint,\"article_author_id_fkey\")]" - }, - "request": { - "kind": "drop_column", - "body": { - "table": "article", - "column": "author_id", - "cascade": false - } - } - }, - { - "name": "drop article_author_id_fkey", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_constraint", - "body": { - "table": "article", - "constraint": "article_author_id_fkey" - } - } - }, - { - "name": "drop col", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_column", - "body": { - "table": "article", - "column": "author_id", - "cascade": false - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/drop_constraint.json b/server/testcases/drop_constraint.json deleted file mode 100644 index 6fb1314d3d335..0000000000000 --- a/server/testcases/drop_constraint.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "description": "drop constraint test", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_constraint", - "body": { - "table": "article", - "constraint": "article_author_id_fkey", - "cascade": true - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/drop_fkey_cons_manual.json b/server/testcases/drop_fkey_cons_manual.json deleted file mode 100644 index 7a3903da7b621..0000000000000 --- a/server/testcases/drop_fkey_cons_manual.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "description": "drop fkey constraint test - manual", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_insert_permission", - "body": { - "table": "article", - "role": "user" - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_select_permission", - "body": { - "table": "article", - "role": "user" - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_delete_permission", - "body": { - "table": "article", - "role": "user" - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_update_permission", - "body": { - "table": "article", - "role": "user" - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_relationship", - "body": { - "table": "article", - "relationship": "author" - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_relationship", - "body": { - "table": "author", - "relationship": "articles" - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_constraint", - "body": { - "table": "article", - "constraint": "article_author_id_fkey" - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/drop_pkey.json b/server/testcases/drop_pkey.json deleted file mode 100644 index 9af365a2e6653..0000000000000 --- a/server/testcases/drop_pkey.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "description": "drop primary_key", - "depends": [], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "name": "a", - "columns": [ - { - "type": "serial", - "name": "id" - } - ] - } - } - }, - { - "name": "drop primary_key", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_constraint", - "body": { - "table": "a", - "constraint": "a_pkey" - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/drop_rel.json b/server/testcases/drop_rel.json deleted file mode 100644 index c55bdbde77881..0000000000000 --- a/server/testcases/drop_rel.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "description": "drop rel test", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_relationship", - "body": { - "__type": "drop_relationship", - "table": "article", - "relationship": "author", - "cascade": true - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/drop_rel_manual.json b/server/testcases/drop_rel_manual.json deleted file mode 100644 index a2ea7e259907e..0000000000000 --- a/server/testcases/drop_rel_manual.json +++ /dev/null @@ -1,165 +0,0 @@ -{ - "description": "drop rel manual test", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": { - "path": "$", - "error": "can not delete due to the following dependent objects - [(\"article\",permission,\"user (delete)\"),(\"article\",permission,\"user (insert)\"),(\"article\",permission,\"user (select)\"),(\"article\",permission,\"user (update)\")]" - }, - "request": { - "kind": "drop_relationship", - "body": { - "table": "article", - "relationship": "author", - "cascade": false - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_select_permission", - "body": { - "table": "article", - "role": "user" - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": { - "path": "$", - "error": "can not delete due to the following dependent objects - [(\"article\",permission,\"user (delete)\"),(\"article\",permission,\"user (insert)\"),(\"article\",permission,\"user (update)\")]" - }, - "request": { - "kind": "drop_relationship", - "body": { - "table": "article", - "relationship": "author", - "cascade": false - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_insert_permission", - "body": { - "table": "article", - "role": "user" - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": { - "path": "$", - "error": "can not delete due to the following dependent objects - [(\"article\",permission,\"user (delete)\"),(\"article\",permission,\"user (update)\")]" - }, - "request": { - "kind": "drop_relationship", - "body": { - "table": "article", - "relationship": "author", - "cascade": false - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_update_permission", - "body": { - "table": "article", - "role": "user" - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": { - "path": "$", - "error": "can not delete due to the following dependent objects - [(\"article\",permission,\"user (delete)\")]" - }, - "request": { - "kind": "drop_relationship", - "body": { - "table": "article", - "relationship": "author", - "cascade": false - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_delete_permission", - "body": { - "table": "article", - "role": "user" - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_relationship", - "body": { - "table": "article", - "relationship": "author", - "cascade": false - } - } - } - - ] -} \ No newline at end of file diff --git a/server/testcases/drop_table.json b/server/testcases/drop_table.json deleted file mode 100644 index bafe800c9ca29..0000000000000 --- a/server/testcases/drop_table.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "description": "drop test", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "drop article no cascade", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": { - "path": "$", - "error": "can not delete due to the following dependent objects - [(\"author\",relationship,\"articles\"),(\"category\",relationship,\"articles\")]" - }, - "request": { - "kind": "drop_table", - "body": { - "table": "article", - "cascade": false - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/drop_table_manual_delete.json b/server/testcases/drop_table_manual_delete.json deleted file mode 100644 index a7f5cbfc21eae..0000000000000 --- a/server/testcases/drop_table_manual_delete.json +++ /dev/null @@ -1,96 +0,0 @@ -{ - "description": "drop test", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "drop article no cascade", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": { - "path": "$", - "error": "can not delete due to the following dependent objects - [(\"author\",relationship,\"articles\"),(\"category\",relationship,\"articles\")]" - }, - "request": { - "kind": "drop_table", - "body": { - "__type": "drop_table", - "table": "article", - "cascade": false - } - } - }, - { - "name": "drop articles rel on author", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_relationship", - "body": { - "__type": "drop_relationship", - "table": "author", - "relationship": "articles" - } - } - }, - { - "name": "drop article no cascade", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": { - "path": "$", - "error": "can not delete due to the following dependent objects - [(\"category\",relationship,\"articles\")]" - }, - "request": { - "kind": "drop_table", - "body": { - "__type": "drop_table", - "table": "article", - "cascade": false - } - } - }, - { - "name": "drop articles rel on category", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_relationship", - "body": { - "__type": "drop_relationship", - "table": "category", - "relationship": "articles" - } - } - }, - { - "name": "drop article no cascade", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "drop_table", - "body": { - "__type": "drop_table", - "table": "article", - "cascade": false - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/drop_view.json b/server/testcases/drop_view.json deleted file mode 100644 index 1c6d7118ace54..0000000000000 --- a/server/testcases/drop_view.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "description": "drop view", - "depends": [], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "pre_sql": [ - "CREATE TABLE test(id serial)", - "CREATE VIEW test_view AS (SELECT id FROM test WHERE id > 10)" - ], - "request": { - "kind": "add_existing_view", - "body": { - "view": "test_view" - } - } - }, - { - "name": "drop view", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - - "request": { - "kind": "drop_view", - "body": { - "view": "test_view", - "cascade": true - } - } - } - ] -} diff --git a/server/testcases/errors.json b/server/testcases/errors.json deleted file mode 100644 index 208b7cd9a1079..0000000000000 --- a/server/testcases/errors.json +++ /dev/null @@ -1,218 +0,0 @@ -{ - "description": "error messages test", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "create author 1 as admin", - "url": "/api/1/table/author/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [ - { - "name": "Balaji", - "auth_id": 1, - "email": "google@balaji.com", - "id": 1 - } - ], - "returning": [ - "id" - ] - }, - "method": "POST" - }, - { - "name": "create author 1 as admin", - "url": "/api/1/table/author/insert", - "role": "admin", - "user_id": "1", - "status_code": 400, - "request": { - "objects": [ - { - "name": "Balaji", - "auth_id": 1, - "email": "google@balaji.com", - "id": 1 - } - ], - "returning": [ - "id" - ] - }, - "response": { - "path": "$", - "error": "Uniqueness violation. duplicate key value violates unique constraint \"author_pkey\"" - }, - "method": "POST" - }, - { - "name": "create article with missing author_id", - "url": "/api/1/table/article/insert", - "role": "admin", - "user_id": "1", - "status_code": 400, - "request": { - "objects": [ - { - "title": "LISP", - "rating": 1, - "category_id": 2, - "content": "Nothing here", - "is_published": false - } - ], - "returning": [ - "id" - ] - }, - "response": { - "path": "$", - "error": "Not-NULL violation. null value in column \"author_id\" violates not-null constraint" - }, - "method": "POST" - }, - { - "name": "create article with invalid author_id", - "url": "/api/1/table/article/insert", - "role": "admin", - "user_id": "1", - "status_code": 400, - "request": { - "objects": [ - { - "title": "LISP", - "rating": 1, - "category_id": 2, - "content": "Nothing here", - "is_published": false, - "author_id": 2 - } - ], - "returning": [ - "id" - ] - }, - "response": { - "path": "$", - "error": "Foreign key violation. insert or update on table \"article\" violates foreign key constraint \"article_author_id_fkey\"" - }, - "method": "POST" - }, - { - "name": "create category", - "url": "/api/1/table/category/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [ - { - "name": "Timepass", - "description": "Timepass stuff", - "id": 1 - } - ], - "returning": [ - "id" - ] - }, - "method": "POST" - }, - { - "name": "create valid article", - "url": "/api/1/table/article/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [ - { - "title": "LISP", - "rating": 1, - "category_id": 1, - "content": "Nothing here", - "is_published": false, - "author_id": 1, - "id": 1 - } - ], - "returning": [ - "id" - ] - }, - "method": "POST" - }, - { - "name": "delete the author", - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "response": { - "path": "$", - "error": "Foreign key violation. update or delete on table \"author\" violates foreign key constraint \"article_author_id_fkey\" on table \"article\"" - }, - "status_code": 400, - "request": { - "kind": "delete", - "body": { - "table": "author", - "where": { - "id": 1 - } - } - }, - "method": "POST" - }, - { - "name": "update the author", - "url": "/api/1/table/author/update", - "role": "admin", - "user_id": "1", - "status_code": 400, - "request": { - "where": { - "id": 1 - }, - "$set": { - "id": 20 - }, - "returning": [ - "id" - ] - }, - "response": { - "path": "$", - "error": "Foreign key violation. update or delete on table \"author\" violates foreign key constraint \"article_author_id_fkey\" on table \"article\"" - }, - "method": "POST" - }, - { - "name": "update the article", - "url": "/api/1/table/article/update", - "role": "admin", - "user_id": "1", - "status_code": 400, - "request": { - "where": { - "id": 1 - }, - "$set": { - "author_id": 2 - }, - "returning": [ - "id" - ] - }, - "response": { - "path": "$", - "error": "Foreign key violation. insert or update on table \"article\" violates foreign key constraint \"article_author_id_fkey\"" - }, - "method": "POST" - } - ] -} \ No newline at end of file diff --git a/server/testcases/indexes.json b/server/testcases/indexes.json deleted file mode 100644 index ca500ca266d28..0000000000000 --- a/server/testcases/indexes.json +++ /dev/null @@ -1,204 +0,0 @@ -{ - "description": "indexes test", - "depends": [], - "items": [ - { - "name": "create_body", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": { - "primary_key": [ - "id" - ], - "name": "a", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "integer", - "name": "a" - }, - { - "type": "integer", - "name": "b" - }, - { - "type": "integer", - "name": "c" - }, - { - "type": "varchar", - "name": "d" - } - ] - } - } - }, - { - "name": "create index only cols", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "sql_check": [ - "select * from pg_catalog.pg_indexes where indexdef = 'CREATE INDEX a_a_b_c_d_idx ON a USING btree (a, b, c NULLS FIRST, d DESC)'" - ], - "request": { - "kind": "create_index", - "body": { - "table": "a", - "columns": [ - "a", - "+b", - { - "column": "c", - "nulls": "first" - }, - { - "column": "d", - "nulls": "first", - "order": "desc" - } - ] - } - } - }, - { - "name": "create index only cols + using", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "sql_check": [ - "select * from pg_catalog.pg_indexes where indexdef = 'CREATE INDEX a_a_idx ON a USING btree (a)'" - ], - "request": { - "kind": "create_index", - "body": { - "table": "a", - "using": "btree", - "columns": [ - "a" - ] - } - } - }, - { - "name": "create index only cols + using + with", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "sql_check": [ - "select * from pg_catalog.pg_indexes where indexdef = 'CREATE INDEX a_b_idx ON a USING btree (b) WITH (fillfactor=50)'" - ], - "request": { - "kind": "create_index", - "body": { - "table": "a", - "using": "btree", - "with": { - "fillfactor": 50 - }, - "columns": [ - "b" - ] - } - } - }, - { - "name": "create index only cols + name", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "sql_check": [ - "select * from pg_catalog.pg_indexes where indexdef = 'CREATE INDEX myindex ON a USING btree (c)'" - ], - "request": { - "kind": "create_index", - "body": { - "name": "myindex", - "table": "a", - "columns": [ - "c" - ] - } - } - }, - { - "name": "create index only cols + unique", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "sql_check": [ - "select * from pg_catalog.pg_indexes where indexdef = 'CREATE UNIQUE INDEX a_b_idx1 ON a USING btree (b)'" - ], - "request": { - "kind": "create_index", - "body": { - "unique": true, - "table": "a", - "columns": [ - "b" - ] - } - } - }, - { - "name": "create index only cols + where", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "sql_check": [ - "select * from pg_catalog.pg_indexes where indexdef = 'CREATE INDEX a_b_idx2 ON a USING btree (b) WHERE (((id > 1000) AND true) AND true)'" - ], - "request": { - "kind": "create_index", - "body": { - "table": "a", - "where": { - "id": { - "$gt": 1000 - } - }, - "columns": [ - "b" - ] - } - } - }, - { - "name": "create index only cols + where", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "sql_check": [ - "select 1 where not exists (select * from pg_catalog.pg_indexes where indexname = 'myindex')" - ], - "request": { - "kind": "drop_index", - "body": { - "index": "myindex" - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/json_jsonb.json b/server/testcases/json_jsonb.json deleted file mode 100644 index 6d90694980f47..0000000000000 --- a/server/testcases/json_jsonb.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "description": "json and jsonb column type test", - "depends": [], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "sql_check": [ - "select * from information_schema.columns where data_type = 'jsonb' and table_name = 'a' AND table_schema='public'", - "select * from information_schema.columns where data_type = 'json' and table_name = 'a' AND table_schema = 'public'" - ], - "request": { - "kind": "create_table", - "body": - { - "primary_key": [ - "id" - ], - "name": "a", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "json", - "name": "a" - }, - { - "type": "jsonb", - "name": "b" - } - ] - } - } - }, - { - "name": "set permission with filter on json column", - "url": "/api/1/query", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": {"path":"$.perm.filter","error":"JSON column can not be part of where clause"}, - "request": { - "kind": "create_select_permission", - "body": - { - "role": "user", - "perm": { - "columns": ["id"], - "filter": { - "a": {"x" : 1} - } - }, - "table": "a" - } - - } - }, - { - "name": "insert object", - "url": "/api/1/table/a/insert", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "objects": [{ - "a": {"a" : "b", "c": "d"}, - "b": {"a" : "b", "c": "d"} - }], - "returning": [ - "id", "a" - ] - } - }, - { - "name": "select with 'where' on JSONB column", - "url": "/api/1/table/a/select", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": {"path":"$.where","error":"JSONB column can not be part of where clause"}, - "request": { - "columns": ["id"], - "where" : { - "b": { "$eq": {"a": "b", "c" : "d"}} - } - } - }, - { - "name": "select with 'where' on JSON column", - "url": "/api/1/table/a/select", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": {"path":"$.where","error":"JSON column can not be part of where clause"}, - "request": { - "columns": ["id"], - "where" : { - "a": { "$eq": {"a": "b", "c" : "d"}} - } - } - } - ] - } \ No newline at end of file diff --git a/server/testcases/no_permission_category.json b/server/testcases/no_permission_category.json deleted file mode 100644 index e29b86ba81f53..0000000000000 --- a/server/testcases/no_permission_category.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "description": "basic permissions check", - "depends": [ - "author_article_category.json" - ], - "items": [ - { - "name": "declare select permissions on author", - "status_code": 200, - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_select_permission", - "body": { - "role": "user", - "table": "author", - "perm": { - "columns": [ - "id", - "name", - "auth_id" - ], - "filter": { - "auth_id": "REQ_USER_ID" - } - } - } - } - }, - { - "name": "declare update permissions on author", - "status_code": 200, - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_update_permission", - "body": { - "role": "user", - "table": "author", - "perm": { - "columns": [ - "name" - ], - "filter": { - "auth_id": "REQ_USER_ID" - } - } - } - } - }, - { - "name": "declare insert permissions on article", - "status_code": 200, - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_insert_permission", - "body": { - "role": "user", - "table": "article", - "perm": { - "check": { - "author": { - "auth_id": "REQ_USER_ID" - } - } - } - } - } - }, - { - "name": "declare select permissions on article", - "status_code": 200, - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_select_permission", - "body": { - "role": "user", - "table": "article", - "perm": { - "override": { - "author": { - "columns": [ - "id", - "name" - ] - } - }, - "columns": [ - "id", - "title", - "content", - "is_published", - "rating", - "author_id" - ], - "filter": { - "$or": [ - { - "author": { - "auth_id": "REQ_USER_ID" - } - }, - { - "is_published": true - } - ] - } - } - } - } - }, - { - "name": "declare update permissions on article", - "status_code": 200, - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_update_permission", - "body": { - "role": "user", - "table": "article", - "perm": { - "columns": [ - "title", - "content", - "is_published", - "rating" - ], - "filter": { - "author": { - "auth_id": "REQ_USER_ID" - } - } - } - } - } - }, - { - "name": "declare delete permissions on article", - "status_code": 200, - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_delete_permission", - "body": { - "role": "user", - "table": "article", - "perm": { - "filter": { - "author": { - "auth_id": "REQ_USER_ID" - } - } - } - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/not_working/alter_foreign_key.json b/server/testcases/not_working/alter_foreign_key.json deleted file mode 100644 index 43db67c164177..0000000000000 --- a/server/testcases/not_working/alter_foreign_key.json +++ /dev/null @@ -1,166 +0,0 @@ -{ - "description": "alter foreign key", - "depends": [], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "status_code": 200, - "method": "POST", - "request": { - "kind": "create_table", - "body": { - "name": "a", - "primary_key": [ - "x" - ], - "columns": [ - { - "name": "x", - "type": "integer" - }, - { - "name": "y", - "type": "integer" - } - ] - } - } - }, - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "status_code": 200, - "method": "POST", - "request": { - "kind": "create_table", - "body": { - "name": "b", - "primary_key": [ - "x" - ], - "columns": [ - { - "name": "x", - "type": "integer", - "references": { - "column": "x", - "table": "a" - } - }, - { - "name": "y", - "type": "integer" - } - ] - } - } - }, - { - "name": "add unique constraint on table a", - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "status_code": 200, - "method": "POST", - "request": { - "kind": "add_unique_constraint", - "body": { - "table": "a", - "constraint": { - "__type": "unique_constraint", - "columns": [ - "x", - "y" - ] - } - } - } - }, - { - "name": "alter foreign key constraint on table b", - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "status_code": 200, - "method": "POST", - "request": { - "kind": "alter_foreign_key_constraint", - "body": { - "table": "b", - "constraint": { - "name": "b_x_fkey", - "mapping": { - "x": "x", - "y": "y" - }, - "ref_table": "a" - } - } - } - }, - { - "name": "alter foreign key constraint on table b", - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "status_code": 400, - "method": "POST", - "sql_check": [ - "select 1 where exists (select sum(ordinal_position) from information_schema.key_column_usage where constraint_name = 'b_x_fkey' GROUP BY constraint_schema, constraint_name);" - ], - "request": { - "kind": "add_foreign_key_constraint", - "body": { - "table": "b", - "constraint": { - "name": "b_x_fkey", - "mapping": { - "x": "x", - "y": "y" - }, - "ref_table": "a" - } - } - } - }, - { - "name": "can't create relationship on b_x_fkey", - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "status_code": 400, - "method": "POST", - "request": { - "kind": "create_object_relationship", - "body": { - "using": "b_x_fkey", - "name": "xx", - "table": "b" - } - } - }, - { - "name": "drop foreign key on non existing table", - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "status_code": 400, - "method": "POST", - "sql_check": [ - "select 1 where exists (select sum(ordinal_position) from information_schema.key_column_usage where constraint_name = 'b_x_fkey' GROUP BY constraint_schema, constraint_name);" - ], - "request": { - "kind": "drop_constraint", - "body": { - "constraint": "b_x_fkey", - "table": "z" - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/permission.json b/server/testcases/permission.json deleted file mode 100644 index 0601d000518f3..0000000000000 --- a/server/testcases/permission.json +++ /dev/null @@ -1,196 +0,0 @@ -{ - "description": "basic permissions check", - "depends": [ - "author_article_category.json" - ], - "items": [ - { - "name": "declare select permissions on category", - "status_code": 200, - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_select_permission", - "body": { - "role": "user", - "table": "category", - "perm": { - "columns": [ - "id", - "name", - "description" - ], - "filter": {} - } - } - } - }, - { - "name": "declare select permissions on author", - "status_code": 200, - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_select_permission", - "body": { - "role": "user", - "table": "author", - "perm": { - "columns": [ - "id", - "name", - "auth_id" - ], - "filter": { - "auth_id": "REQ_USER_ID" - } - } - } - } - }, - { - "name": "declare update permissions on author", - "status_code": 200, - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_update_permission", - "body": { - "role": "user", - "table": "author", - "perm": { - "columns": [ - "name" - ], - "filter": { - "auth_id": "REQ_USER_ID" - } - } - } - } - }, - { - "name": "declare insert permissions on article", - "status_code": 200, - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_insert_permission", - "body": { - "role": "user", - "table": "article", - "perm": { - "check": { - "author": { - "auth_id": "REQ_USER_ID" - } - } - } - } - } - }, - { - "name": "declare select permissions on article", - "status_code": 200, - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_select_permission", - "body": { - "role": "user", - "table": "article", - "perm": { - "override": { - "author": { - "columns": [ - "id", - "name" - ] - } - }, - "columns": [ - "id", - "title", - "content", - "is_published", - "rating", - "author_id" - ], - "filter": { - "$or": [ - { - "author": { - "auth_id": "REQ_USER_ID" - } - }, - { - "is_published": true - } - ] - } - } - } - } - }, - { - "name": "declare update permissions on article", - "status_code": 200, - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_update_permission", - "body": { - "role": "user", - "table": "article", - "perm": { - "columns": [ - "title", - "content", - "is_published", - "rating" - ], - "filter": { - "author": { - "auth_id": "REQ_USER_ID" - } - } - } - } - } - }, - { - "name": "declare delete permissions on article", - "status_code": 200, - "url": "/api/1/query", - "role": "admin", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_delete_permission", - "body": { - "role": "user", - "table": "article", - "perm": { - "filter": { - "author": { - "auth_id": "REQ_USER_ID" - } - } - } - } - } - } - ] -} \ No newline at end of file diff --git a/server/testcases/update_ops.json b/server/testcases/update_ops.json deleted file mode 100644 index 37536bc7afb74..0000000000000 --- a/server/testcases/update_ops.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "description": "json and jsonb column type test", - "depends": [], - "items": [ - { - "name": "create_schema", - "url": "/api/1/query", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "kind": "create_table", - "body": - { - "primary_key": [ - "id" - ], - "name": "a", - "columns": [ - { - "type": "serial", - "name": "id" - }, - { - "type": "integer", - "name": "a" - }, - { - "type": "timetz", - "name": "b", - "default": "03:21:55+00:00" - }, - { - "type": "varchar", - "name": "c" - } - ] - } - - } - }, - { - "name": "create entry", - "url": "/api/1/table/a/insert", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "request": { - "objects": [ - { - "a": 1, - "b": "04:21:55+00:00", - "c": "World" - } - ] - } - }, - { - "name": "inc and default update", - "url": "/api/1/table/a/update", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "response": {"returning":[{"a":21,"b":"03:21:55+00"}],"affected_rows":1}, - "request": { - "where": {}, - "$set": {"c": "Hello"}, - "$inc": { - "a" : 20 - }, - "$default": ["b"], - "returning": ["a", "b"] - - } - }, - { - "name": "mul update", - "url": "/api/1/table/a/update", - "role": "admin", - "status_code": 200, - "method": "POST", - "user_id": "1", - "response": {"returning":[{"a":420,"b":"03:21:55+00"}],"affected_rows":1}, - "request": { - "where": {}, - "$mul": { - "a" : 20 - }, - "returning": ["a", "b"] - - } - }, - { - "name": "multiple column appearences", - "url": "/api/1/table/a/update", - "role": "admin", - "status_code": 400, - "method": "POST", - "user_id": "1", - "response": {"path":"$","error":"syntax error. \"multiple assignments to same column \\\"a\\\"\""}, - "request": { - "where": {}, - "$inc": { - "a" : 20 - }, - "$mul": { - "a" : 20 - }, - "returning": ["a", "b"] - - } - } - - ] - } \ No newline at end of file diff --git a/server/testcases/user_permission_non_admin.json b/server/testcases/user_permission_non_admin.json deleted file mode 100644 index 6f887f54f3815..0000000000000 --- a/server/testcases/user_permission_non_admin.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "description": "basic permissions check", - "depends": [ - "author_article_category.json" - ], - "items": [ - { - "name": "declare select permissions on category", - "status_code": 400, - "url": "/api/1/query", - "role": "user", - "user_id": "1", - "method": "POST", - "request": { - "kind": "create_select_permission", - "body": { - "role": "user", - "table": "category", - "perm": { - "columns": [ - "id", - "name", - "description" - ], - "filter": {} - } - } - } - } - ] - } \ No newline at end of file diff --git a/server/testcases/wildcard.json b/server/testcases/wildcard.json deleted file mode 100644 index e9afe524119bb..0000000000000 --- a/server/testcases/wildcard.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "description": "check wildcards", - "depends": [ - "permission.json" - ], - "items": [ - { - "name": "create author B1 as admin", - "url": "/api/1/table/author/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [{ - "name": "James Bond", - "auth_id": 1, - "email": "google@gmail.com" - }], - "returning": [ - "id" - ] - }, - "response": { - "affected_rows": 1, - "returning": [ - { - "id": 1 - } - ] - }, - "method": "POST" - }, - { - "name": "create category", - "url": "/api/1/table/category/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [{ - "name": "Haskell", - "description": "Haskell Haskell Haskell" - }], - "returning": [ - "id" - ] - }, - "response": { - "affected_rows": 1, - "returning": [ - { - "id": 1 - } - ] - }, - "method": "POST" - }, - { - "name": "create article under B1", - "url": "/api/1/table/article/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [{ - "title": "Dependent Haskell", - "author_id": 1, - "content": "Heloo world", - "is_published": false, - "rating": 3, - "category_id": 1 - }], - "returning": [ - "id" - ] - }, - "response": { - "affected_rows": 1, - "returning": [ - { - "id": 1 - } - ] - }, - "method": "POST" - }, - { - "name": "selct * as admin", - "url": "/api/1/table/author/select", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "columns": [ - "*" - ] - }, - "response": [ - { - "name": "James Bond", - "id": 1, - "auth_id": 1, - "email": "google@gmail.com" - } - ], - "method": "POST" - }, - { - "name": "selct *.* as admin", - "url": "/api/1/table/author/select", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "columns": [ - "*.*" - ] - }, - "response": [ - { - "email": "google@gmail.com", - "auth_id": 1, - "name": "James Bond", - "articles": [ - { - "rating": 3, - "author_id": 1, - "category_id": 1, - "content": "Heloo world", - "is_published": false, - "id": 1, - "title": "Dependent Haskell" - } - ], - "id": 1 - } - ], - "method": "POST" - }, - { - "name": "selct *.* as admin", - "url": "/api/1/table/author/select", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "columns": [ - "*.*", - "name" - ] - }, - "response": [ - { - "email": "google@gmail.com", - "auth_id": 1, - "name": "James Bond", - "articles": [ - { - "rating": 3, - "author_id": 1, - "category_id": 1, - "content": "Heloo world", - "is_published": false, - "id": 1, - "title": "Dependent Haskell" - } - ], - "id": 1 - } - ], - "method": "POST" - }, - { - "name": "selct *.* as admin", - "url": "/api/1/table/author/select", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "columns": [ - "*.*", - { - "name": "articles", - "columns": [ - "title" - ] - } - ] - }, - "response": [ - { - "name": "James Bond", - "id": 1, - "auth_id": 1, - "email": "google@gmail.com", - "articles": [ - { - "title": "Dependent Haskell" - } - ] - } - ], - "method": "POST" - }, - { - "name": "selct *.*.* as admin", - "url": "/api/1/table/author/select", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "columns": [ - "*.*.*" - ] - }, - "response": [ - { - "email": "google@gmail.com", - "auth_id": 1, - "name": "James Bond", - "articles": [ - { - "rating": 3, - "author_id": 1, - "category_id": 1, - "category": { - "name": "Haskell", - "id": 1, - "description": "Haskell Haskell Haskell" - }, - "content": "Heloo world", - "is_published": false, - "author": { - "email": "google@gmail.com", - "auth_id": 1, - "name": "James Bond", - "id": 1 - }, - "id": 1, - "title": "Dependent Haskell" - } - ], - "id": 1 - } - ], - "method": "POST" - }, - { - "name": "selct *.*.* as admin", - "url": "/api/1/table/author/select", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "columns": [ - "*.*.*", - "*.*" - ] - }, - "response": [ - { - "email": "google@gmail.com", - "auth_id": 1, - "name": "James Bond", - "articles": [ - { - "rating": 3, - "author_id": 1, - "category_id": 1, - "category": { - "name": "Haskell", - "id": 1, - "description": "Haskell Haskell Haskell" - }, - "content": "Heloo world", - "is_published": false, - "author": { - "email": "google@gmail.com", - "auth_id": 1, - "name": "James Bond", - "id": 1 - }, - "id": 1, - "title": "Dependent Haskell" - } - ], - "id": 1 - } - ], - "method": "POST" - }, - { - "name": "select * (articles *) as admin", - "url": "/api/1/table/author/select", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "columns": [ - "*", - { - "name": "articles", - "columns": [ - "*" - ] - } - ] - }, - "response": [ - { - "email": "google@gmail.com", - "auth_id": 1, - "name": "James Bond", - "articles": [ - { - "rating": 3, - "author_id": 1, - "category_id": 1, - "content": "Heloo world", - "is_published": false, - "id": 1, - "title": "Dependent Haskell" - } - ], - "id": 1 - } - ], - "method": "POST" - } - ] -} diff --git a/server/testcases/wildcard_user.json b/server/testcases/wildcard_user.json deleted file mode 100644 index 10aeb1e2a6354..0000000000000 --- a/server/testcases/wildcard_user.json +++ /dev/null @@ -1,286 +0,0 @@ -{ - "description": "check wildcards for user role", - "depends": [ - "no_permission_category.json" - ], - "items": [ - { - "name": "create author B1 as admin", - "url": "/api/1/table/author/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [{ - "name": "James Bond", - "auth_id": 1, - "email": "google@gmail.com" - }], - "returning": [ - "id" - ] - }, - "response": { - "affected_rows": 1, - "returning": [ - { - "id": 1 - } - ] - }, - "method": "POST" - }, - { - "name": "create category", - "url": "/api/1/table/category/insert", - "role": "admin", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [{ - "name": "Haskell", - "description": "Haskell Haskell Haskell" - }], - "returning": [ - "id" - ] - }, - "response": { - "affected_rows": 1, - "returning": [ - { - "id": 1 - } - ] - }, - "method": "POST" - }, - { - "name": "create article under B1", - "url": "/api/1/table/article/insert", - "role": "user", - "user_id": "1", - "status_code": 200, - "request": { - "objects": [{ - "title": "Dependent Haskell", - "author_id": 1, - "content": "Heloo world", - "is_published": false, - "rating": 3, - "category_id": 1 - }], - "returning": [ - "id" - ] - }, - "response": { - "affected_rows": 1, - "returning": [ - { - "id": 1 - } - ] - }, - "method": "POST" - }, - - { - "name": "selct *.* as user", - "url": "/api/1/table/author/select", - "role": "user", - "user_id": "1", - "status_code": 200, - "request": { - "columns": [ - "*.*" - ] - }, - "response": [ - { - "name": "James Bond", - "id": 1, - "auth_id": 1, - "articles": [ - { - "title": "Dependent Haskell", - "author_id": 1, - "content": "Heloo world", - "is_published": false, - "rating": 3, - "id": 1 - } - ] - } - ], - "method": "POST" - }, - { - "name": "selct *.* as user", - "url": "/api/1/table/author/select", - "role": "user", - "user_id": "1", - "status_code": 200, - "request": { - "columns": [ - "*.*", - "name" - ] - }, - "response": [ - { - "name": "James Bond", - "id": 1, - "auth_id": 1, - "articles": [ - { - "title": "Dependent Haskell", - "author_id": 1, - "content": "Heloo world", - "is_published": false, - "rating": 3, - "id": 1 - } - ] - } - ], - "method": "POST" - }, - { - "name": "selct *.* as user", - "url": "/api/1/table/author/select", - "role": "user", - "user_id": "1", - "status_code": 200, - "request": { - "columns": [ - "*.*", - { - "name": "articles", - "columns": [ - "title" - ] - } - ] - }, - "response": [ - { - "name": "James Bond", - "id": 1, - "auth_id": 1, - "articles": [ - { - "title": "Dependent Haskell" - } - ] - } - ], - "method": "POST" - }, - { - "name": "selct *.*.* as user", - "url": "/api/1/table/author/select", - "role": "user", - "user_id": "1", - "status_code": 200, - "request": { - "columns": [ - "*.*.*" - ] - }, - "response": [ - { - "name": "James Bond", - "id": 1, - "auth_id": 1, - "articles": [ - { - "title": "Dependent Haskell", - "author_id": 1, - "content": "Heloo world", - "is_published": false, - "rating": 3, - "id": 1, - "author": { - "name": "James Bond", - "id": 1 - } - } - ] - } - ], - "method": "POST" - }, - { - "name": "selct *.*.* as user", - "url": "/api/1/table/author/select", - "role": "user", - "user_id": "1", - "status_code": 200, - "request": { - "columns": [ - "*.*.*", - "*.*" - ] - }, - "response": [ - { - "name": "James Bond", - "id": 1, - "auth_id": 1, - "articles": [ - { - "title": "Dependent Haskell", - "author_id": 1, - "content": "Heloo world", - "is_published": false, - "rating": 3, - "id": 1, - "author": { - "name": "James Bond", - "id": 1 - } - } - ] - } - ], - "method": "POST" - }, - { - "name": "select * (articles *) as user", - "url": "/api/1/table/author/select", - "role": "user", - "user_id": "1", - "status_code": 200, - "request": { - "columns": [ - "*", - { - "name": "articles", - "columns": [ - "*" - ] - } - ] - }, - "response": [ - { - "name": "James Bond", - "id": 1, - "auth_id": 1, - "articles": [ - { - "title": "Dependent Haskell", - "content": "Heloo world", - "is_published": false, - "rating": 3, - "id": 1, - "author_id": 1 - } - ] - } - ], - "method": "POST" - } - ] -} diff --git a/server/tests-py/.gitignore b/server/tests-py/.gitignore new file mode 100644 index 0000000000000..216e9087c9e43 --- /dev/null +++ b/server/tests-py/.gitignore @@ -0,0 +1,132 @@ + +# Created by https://www.gitignore.io/api/python + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +### Python Patch ### +.venv/ + +### Python.VirtualEnv Stack ### +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +pip-selfcheck.json + + +# End of https://www.gitignore.io/api/python diff --git a/server/tests-py/README.md b/server/tests-py/README.md new file mode 100644 index 0000000000000..cefc5e0f80a40 --- /dev/null +++ b/server/tests-py/README.md @@ -0,0 +1,4 @@ +```bash +pip install -r requirements.txt +pytest -vv --hge-url="http://127.0.0.1:8080" --pg-url="postgresql://admin@127.0.0.1:5432/hge_tests" +``` diff --git a/server/tests-py/conftest.py b/server/tests-py/conftest.py new file mode 100644 index 0000000000000..b50bf2304112c --- /dev/null +++ b/server/tests-py/conftest.py @@ -0,0 +1,23 @@ +import pytest +from context import HGECtx, HGECtxError + +def pytest_addoption(parser): + parser.addoption( + "--hge-url", metavar="HGE_URL", help="url for graphql-engine", required=True + ) + parser.addoption( + "--pg-url", metavar="PG_URL", help="url for connecting to Postgres directly", required=True + ) + +@pytest.fixture(scope='session') +def hge_ctx(request): + print ("create hge_ctx") + hge_url = request.config.getoption('--hge-url') + pg_url = request.config.getoption('--pg-url') + try: + hge_ctx = HGECtx(hge_url=hge_url, pg_url=pg_url) + except HGECtxError as e: + pytest.exit(str(e)) + yield hge_ctx # provide the fixture value + print("teardown hge_ctx") + hge_ctx.teardown() diff --git a/server/tests-py/context.py b/server/tests-py/context.py new file mode 100644 index 0000000000000..de0dd28c3ffe2 --- /dev/null +++ b/server/tests-py/context.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 + +import socketserver +import threading +import http.server +import json +import yaml +import queue +import requests +import socket +import websocket +import subprocess + +from http import HTTPStatus +from urllib.parse import urlparse + +from sqlalchemy import create_engine +from sqlalchemy.schema import MetaData + +class HGECtxError(Exception): + pass + +class WebhookHandler(http.server.BaseHTTPRequestHandler): + def do_GET(self): + self.send_response(HTTPStatus.OK) + self.end_headers() + + def do_POST(self): + contentLen = self.headers.get('Content-Length') + reqBody = self.rfile.read(int(contentLen)).decode("utf-8") + reqJson = json.loads(reqBody) + self.log_message(json.dumps(reqJson)) + self.send_response(HTTPStatus.NO_CONTENT) + self.end_headers() + self.server.resp_queue.put(reqJson) + +class WebhookServer(http.server.HTTPServer): + def __init__(self, resp_queue, server_address): + self.resp_queue = resp_queue + super().__init__(server_address, WebhookHandler) + +class HGECtx: + def __init__(self, hge_url, pg_url): + server_address = ('0.0.0.0', 5592) + + self.resp_queue = queue.Queue(maxsize=1) + self.ws_queue = queue.Queue(maxsize=1) + self.httpd = WebhookServer(self.resp_queue, server_address) + self.web_server = threading.Thread(target=self.httpd.serve_forever) + self.web_server.start() + + self.pg_url = pg_url + self.engine = create_engine(self.pg_url) + self.meta = MetaData() + + self.http = requests.Session() + self.hge_url = hge_url + + self.ws_url = urlparse(hge_url) + self.ws_url = self.ws_url._replace(scheme='ws') + self.ws_url = self.ws_url._replace(path='/v1alpha1/graphql') + self.ws = websocket.WebSocketApp(self.ws_url.geturl(), on_message=self._on_message) + self.wst = threading.Thread(target=self.ws.run_forever) + self.wst.daemon = True + self.wst.start() + + result = subprocess.run(['../../scripts/get-version.sh'], shell=True, stdout=subprocess.PIPE, check=True) + self.version = result.stdout.decode('utf-8').strip() + try: + st_code, resp = self.v1q_f('queries/clear_db.yaml') + except requests.exceptions.RequestException as e: + self.teardown() + raise HGECtxError(repr(e)) + assert st_code == 200, resp + + def _on_message(self, message): + my_json = json.loads(message) + if my_json['type'] != 'ka': + self.ws_queue.put(message) + + def get_event(self, timeout): + return self.resp_queue.get(timeout=timeout) + + def get_ws_event(self, timeout): + return json.loads(self.ws_queue.get(timeout=timeout)) + + def reflect_tables(self): + self.meta.reflect(bind=self.engine) + + def anyq(self, u, q, h): + resp = self.http.post( + self.hge_url + u, + json=q, + headers=h + ) + return resp.status_code, resp.json() + + def v1q(self, q): + resp = self.http.post( + self.hge_url + "/v1/query", + json=q + ) + return resp.status_code, resp.json() + + def v1q_f(self, fn): + with open(fn) as f: + return self.v1q(yaml.load(f)) + + def teardown(self): + self.http.close() + self.engine.dispose() + self.httpd.shutdown() + self.web_server.join() + self.wst.join() diff --git a/server/tests-py/queries/basic/setup.yaml b/server/tests-py/queries/basic/setup.yaml new file mode 100644 index 0000000000000..200e42aa40ab7 --- /dev/null +++ b/server/tests-py/queries/basic/setup.yaml @@ -0,0 +1,26 @@ +type: bulk +args: +- type: run_sql + args: + sql: | + create table hge_tests.test_t1( + c1 int, + c2 text + ); +- type: track_table + args: + schema: hge_tests + name: test_t1 +- type: create_event_trigger + args: + name: t1_all + table: + schema: hge_tests + name: test_t1 + insert: + columns: "*" + update: + columns: "*" + delete: + columns: "*" + webhook: http://127.0.0.1:5592 diff --git a/server/tests-py/queries/basic/teardown.yaml b/server/tests-py/queries/basic/teardown.yaml new file mode 100644 index 0000000000000..a0766f4d43ca0 --- /dev/null +++ b/server/tests-py/queries/basic/teardown.yaml @@ -0,0 +1,9 @@ +type: bulk +args: +- type: delete_event_trigger + args: + name: t1_all +- type: run_sql + args: + sql: | + drop table hge_tests.test_t1 diff --git a/server/tests-py/queries/clear_db.yaml b/server/tests-py/queries/clear_db.yaml new file mode 100644 index 0000000000000..71dc7a469f5ee --- /dev/null +++ b/server/tests-py/queries/clear_db.yaml @@ -0,0 +1,4 @@ +type: run_sql +args: + sql: | + drop schema if exists hge_tests cascade; create schema hge_tests; diff --git a/server/tests-py/queries/empty_cols/setup.yaml b/server/tests-py/queries/empty_cols/setup.yaml new file mode 100644 index 0000000000000..24c326743bcd6 --- /dev/null +++ b/server/tests-py/queries/empty_cols/setup.yaml @@ -0,0 +1,30 @@ +type: bulk +args: +- type: run_sql + args: + sql: | + create table hge_tests.test_t1( + c1 int, + c2 text, + c3 text + ); +- type: track_table + args: + schema: hge_tests + name: test_t1 +- type: create_event_trigger + args: + name: t1_all + table: + schema: hge_tests + name: test_t1 + insert: + columns: [] + update: + columns: [] + delete: + columns: [] + webhook: http://127.0.0.1:5592 + retry_conf: + num_retries: 10 + interval_sec: 100 diff --git a/server/tests-py/queries/empty_cols/teardown.yaml b/server/tests-py/queries/empty_cols/teardown.yaml new file mode 100644 index 0000000000000..a0766f4d43ca0 --- /dev/null +++ b/server/tests-py/queries/empty_cols/teardown.yaml @@ -0,0 +1,9 @@ +type: bulk +args: +- type: delete_event_trigger + args: + name: t1_all +- type: run_sql + args: + sql: | + drop table hge_tests.test_t1 diff --git a/server/tests-py/queries/graphql_introspection/introspection.yaml b/server/tests-py/queries/graphql_introspection/introspection.yaml new file mode 100644 index 0000000000000..7a45310e5709c --- /dev/null +++ b/server/tests-py/queries/graphql_introspection/introspection.yaml @@ -0,0 +1,104 @@ +description: GraphQL introspection query +url: /v1alpha1/graphql +status: 200 +query: + query: | + query IntrospectionQuery { + __schema { + queryType { + name + } + mutationType { + name + } + subscriptionType { + name + } + types { + ...FullType + } + directives { + name + description + locations + args { + ...InputValue + } + } + } + } + + fragment FullType on __Type { + kind + name + description + fields(includeDeprecated: true) { + name + description + args { + ...InputValue + } + type { + ...TypeRef + } + isDeprecated + deprecationReason + } + inputFields { + ...InputValue + } + interfaces { + ...TypeRef + } + enumValues(includeDeprecated: true) { + name + description + isDeprecated + deprecationReason + } + possibleTypes { + ...TypeRef + } + } + + fragment InputValue on __InputValue { + name + description + type { + ...TypeRef + } + defaultValue + } + + fragment TypeRef on __Type { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + } + } + } + } + } + } + } + } diff --git a/server/tests-py/queries/graphql_introspection/introspection_user_role.yaml b/server/tests-py/queries/graphql_introspection/introspection_user_role.yaml new file mode 100644 index 0000000000000..daa5580a1d65a --- /dev/null +++ b/server/tests-py/queries/graphql_introspection/introspection_user_role.yaml @@ -0,0 +1,106 @@ +description: GraphQL introspection query as user role +url: /v1alpha1/graphql +status: 200 +headers: + X-Hasura-Role: user +query: + query: | + query IntrospectionQuery { + __schema { + queryType { + name + } + mutationType { + name + } + subscriptionType { + name + } + types { + ...FullType + } + directives { + name + description + locations + args { + ...InputValue + } + } + } + } + + fragment FullType on __Type { + kind + name + description + fields(includeDeprecated: true) { + name + description + args { + ...InputValue + } + type { + ...TypeRef + } + isDeprecated + deprecationReason + } + inputFields { + ...InputValue + } + interfaces { + ...TypeRef + } + enumValues(includeDeprecated: true) { + name + description + isDeprecated + deprecationReason + } + possibleTypes { + ...TypeRef + } + } + + fragment InputValue on __InputValue { + name + description + type { + ...TypeRef + } + defaultValue + } + + fragment TypeRef on __Type { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + } + } + } + } + } + } + } + } diff --git a/server/tests-py/queries/graphql_introspection/setup.yaml b/server/tests-py/queries/graphql_introspection/setup.yaml new file mode 100644 index 0000000000000..2ccac03c3c790 --- /dev/null +++ b/server/tests-py/queries/graphql_introspection/setup.yaml @@ -0,0 +1,92 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL PRIMARY KEY, + title TEXT, + content TEXT, + author_id INTEGER REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP + ) +- type: track_table + args: + schema: public + name: article + +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Array relationship +- type: create_array_relationship + args: + table: author + name: articles + using: + foreign_key_constraint_on: + table: article + column: author_id + +#Article select permission for user +- type: create_select_permission + args: + table: article + role: user + permission: + columns: '*' + filter: + $or: + - author_id: X-HASURA-USER-ID + - is_published: true + +#Article insert permission for user +- type: create_insert_permission + args: + table: article + role: user + permission: + check: + author_id: X-Hasura-User-Id + +#Author select permission for user +- type: create_select_permission + args: + table: author + role: user + permission: + columns: '*' + filter: + id: X-HASURA-USER-ID + +#Author insert permission for user +- type: create_insert_permission + args: + table: author + role: user + permission: + check: + id: X-HASURA-USER-ID + allow_upsert: true + diff --git a/server/tests-py/queries/graphql_introspection/teardown.yaml b/server/tests-py/queries/graphql_introspection/teardown.yaml new file mode 100644 index 0000000000000..6703514daa39d --- /dev/null +++ b/server/tests-py/queries/graphql_introspection/teardown.yaml @@ -0,0 +1,19 @@ +type: bulk +args: +#Drop relationship first +- type: drop_relationship + args: + table: + name: author + schema: public + relationship: articles + +- type: run_sql + args: + sql: | + drop table article + +- type: run_sql + args: + sql: | + drop table author diff --git a/server/tests-py/queries/graphql_mutation/delete/article.yaml b/server/tests-py/queries/graphql_mutation/delete/article.yaml new file mode 100644 index 0000000000000..c7134d3111777 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/delete/article.yaml @@ -0,0 +1,16 @@ +description: Delete mutation on article +url: /v1alpha1/graphql +status: 200 +response: + data: + delete_article: + affected_rows: 1 +query: + query: | + mutation delete_article { + delete_article ( + where: {id: {_eq: 5}} + ) { + affected_rows + } + } diff --git a/server/tests-py/queries/graphql_mutation/delete/article_returning.yaml b/server/tests-py/queries/graphql_mutation/delete/article_returning.yaml new file mode 100644 index 0000000000000..53ad3b48396c9 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/delete/article_returning.yaml @@ -0,0 +1,23 @@ +description: Delete mutation on article with returning +url: /v1alpha1/graphql +status: 200 +response: + data: + delete_article: + affected_rows: 1 + returning: + - id: 5 + content: Sample article content 5 +query: + query: | + mutation delete_article { + delete_article ( + where: {id: {_eq: 5}} + ) { + affected_rows + returning{ + id + content + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/delete/author_foreign_key_violation.yaml b/server/tests-py/queries/graphql_mutation/delete/author_foreign_key_violation.yaml new file mode 100644 index 0000000000000..5dc046bf6dd52 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/delete/author_foreign_key_violation.yaml @@ -0,0 +1,15 @@ +description: delete from author table (Foreign Key Violation Error) +url: /v1alpha1/graphql +status: 400 +query: + query: | + mutation { + delete_author(where: {id: {_eq: 2}}){ + affected_rows + } + } +response: + errors: + - path: $ + error: "Foreign key violation. update or delete on table \"author\" violates foreign key constraint \"article_author_id_fkey\" on table \"article\"" + code: constraint-violation diff --git a/server/tests-py/queries/graphql_mutation/delete/setup.yaml b/server/tests-py/queries/graphql_mutation/delete/setup.yaml new file mode 100644 index 0000000000000..c62eb1b4111cd --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/delete/setup.yaml @@ -0,0 +1,79 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL PRIMARY KEY, + title TEXT, + content TEXT, + author_id INTEGER NOT NULL REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP + ) +- type: track_table + args: + schema: public + name: article + +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Array relationship +- type: create_array_relationship + args: + table: author + name: articles + using: + foreign_key_constraint_on: + table: article + column: author_id + +#Insert Author table data +- type: insert + args: + table: author + objects: + - name: Author 1 + - name: Author 2 + +#Insert aticle table data +- type: insert + args: + table: article + objects: + - content: Sample article content 1 + title: Article 1 + author_id: 1 + - content: Sample article content 2 + title: Article 2 + author_id: 1 + - content: Sample article content 3 + author_id: 1 + title: Article 3 + - content: Sample article content 4 + author_id: 2 + title: Article 4 + - content: Sample article content 5 + author_id: 2 + title: Article 5 diff --git a/server/tests-py/queries/graphql_mutation/delete/teardown.yaml b/server/tests-py/queries/graphql_mutation/delete/teardown.yaml new file mode 100644 index 0000000000000..416f8c1998504 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/delete/teardown.yaml @@ -0,0 +1,18 @@ +type: bulk +args: +#Drop relationship first +- type: drop_relationship + args: + relationship: articles + table: + schema: public + name: author + +- type: run_sql + args: + sql: | + drop table article +- type: run_sql + args: + sql: | + drop table author diff --git a/server/tests-py/queries/graphql_mutation/insert/basic/author_article.yaml b/server/tests-py/queries/graphql_mutation/insert/basic/author_article.yaml new file mode 100644 index 0000000000000..6721b6d2a73fb --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/basic/author_article.yaml @@ -0,0 +1,78 @@ +#Inserting author data +- description: Inserts author data via GraphQL mutation + url: /v1alpha1/graphql + response: + data: + insert_author: + returning: + - id: 1 + name: Author 1 + - id: 2 + name: Author 2 + status: 200 + query: + query: | + mutation insert_author { + insert_author( + objects: [ + { + name: "Author 1" + }, + { + name: "Author 2" + } + ] + ) { + returning { + id + name + } + } + } + +#Inserting article data +- description: Inserts article data via GraphQL mutation + url: /v1alpha1/graphql + response: + data: + insert_article: + returning: + - content: Sample article content + id: 1 + title: Article 1 + - content: Sample article content + id: 2 + title: Article 2 + - content: Sample article content + id: 3 + title: Article 3 + status: 200 + query: + query: | + mutation insert_article { + insert_article ( + objects: [ + { + title: "Article 1", + content: "Sample article content", + author_id: 1 + }, + { + title: "Article 2", + content: "Sample article content", + author_id: 1 + }, + { + title: "Article 3", + content: "Sample article content", + author_id: 2 + } + ] + ) { + returning { + id + title + content + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/basic/author_unique_constraint_error.yaml b/server/tests-py/queries/graphql_mutation/insert/basic/author_unique_constraint_error.yaml new file mode 100644 index 0000000000000..189fa06091ebe --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/basic/author_unique_constraint_error.yaml @@ -0,0 +1,27 @@ +description: Insert into author table as user role (Unique Constraint Error) +url: /v1alpha1/graphql +status: 400 +query: + query: | + mutation insert_author { + insert_author( + objects: [ + { + name: "Author 1" + }, + { + name: "Author 1" + } + ] + ) { + returning { + id + name + } + } + } +response: + errors: + - path: $ + error: "Uniqueness violation. duplicate key value violates unique constraint \"author_name_key\"" + code: constraint-violation diff --git a/server/tests-py/queries/graphql_mutation/insert/basic/order_col_shipped_null.yaml b/server/tests-py/queries/graphql_mutation/insert/basic/order_col_shipped_null.yaml new file mode 100644 index 0000000000000..64ec76093501b --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/basic/order_col_shipped_null.yaml @@ -0,0 +1,20 @@ +description: Insert into order table with a null value +url: /v1alpha1/graphql +status: 200 +query: + query: | + mutation insert_orders{ + insert_orders( + objects: [ + { + placed: "2017-08-19 14:22:11.802755+02", + shipped: null + } + ] + ) { + returning { + id + } + affected_rows + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/basic/person_jsonb_variable.yaml b/server/tests-py/queries/graphql_mutation/insert/basic/person_jsonb_variable.yaml new file mode 100644 index 0000000000000..19333d2b709ad --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/basic/person_jsonb_variable.yaml @@ -0,0 +1,24 @@ +description: Inserts person data via GraphQL mutation +url: /v1alpha1/graphql +status: 200 +query: + variables: + value: + name: + first: john + last: murphy + query: | + mutation insert_person($value: jsonb) { + insert_person( + objects: [ + { + details: $value + } + ] + ) { + returning { + id + details + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/basic/person_jsonb_variable_array.yaml b/server/tests-py/queries/graphql_mutation/insert/basic/person_jsonb_variable_array.yaml new file mode 100644 index 0000000000000..ad84a17e3ea42 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/basic/person_jsonb_variable_array.yaml @@ -0,0 +1,27 @@ +description: Inserts persons data via GraphQL mutation +url: /v1alpha1/graphql +status: 200 +query: + variables: + value: + - name: + first: thelonious + last: jaha + - name: + first: clarke + last: griffin + query: | + mutation insert_person($value: jsonb) { + insert_person( + objects: [ + { + details: $value + } + ] + ) { + returning { + id + details + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/basic/setup.yaml b/server/tests-py/queries/graphql_mutation/insert/basic/setup.yaml new file mode 100644 index 0000000000000..27e5bdcff597d --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/basic/setup.yaml @@ -0,0 +1,79 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL PRIMARY KEY, + title TEXT, + content TEXT, + author_id INTEGER REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP + ) +- type: track_table + args: + schema: public + name: article + +#Person table +- type: run_sql + args: + sql: | + CREATE TABLE person ( + id SERIAL PRIMARY KEY, + details JSONB NOT NULL + ) +- type: track_table + args: + schema: public + name: person + +#Order table +- type: run_sql + args: + sql: | + CREATE TABLE orders ( + id SERIAL PRIMARY KEY, + placed TIMESTAMPTZ NOT NULL, + shipped TIMESTAMPTZ + ) +- type: track_table + args: + schema: public + name: orders + + +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Array relationship +- type: create_array_relationship + args: + table: author + name: articles + using: + foreign_key_constraint_on: + table: article + column: author_id + diff --git a/server/tests-py/queries/graphql_mutation/insert/basic/teardown.yaml b/server/tests-py/queries/graphql_mutation/insert/basic/teardown.yaml new file mode 100644 index 0000000000000..eb80d35dcc6f5 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/basic/teardown.yaml @@ -0,0 +1,26 @@ +type: bulk +args: +#Drop relationship first +- type: drop_relationship + args: + relationship: articles + table: + schema: public + name: author + +- type: run_sql + args: + sql: | + drop table person +- type: run_sql + args: + sql: | + drop table orders +- type: run_sql + args: + sql: | + drop table article +- type: run_sql + args: + sql: | + drop table author diff --git a/server/tests-py/queries/graphql_mutation/insert/constraints/address_not_null_constraint_error.yaml b/server/tests-py/queries/graphql_mutation/insert/constraints/address_not_null_constraint_error.yaml new file mode 100644 index 0000000000000..4f1e7dc3e9bbf --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/constraints/address_not_null_constraint_error.yaml @@ -0,0 +1,19 @@ +description: Insert into order table as user role (Not Null Constraint Error) +url: /v1alpha1/graphql +status: 400 +query: + query: | + mutation { + insert_address(objects: [{street: "koramangala"}]){ + returning{ + id + street + } + affected_rows + } + } +response: + errors: + - path: $ + error: "Not-NULL violation. null value in column \"door_no\" violates not-null constraint" + code: constraint-violation diff --git a/server/tests-py/queries/graphql_mutation/insert/constraints/setup.yaml b/server/tests-py/queries/graphql_mutation/insert/constraints/setup.yaml new file mode 100644 index 0000000000000..2e451af14296c --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/constraints/setup.yaml @@ -0,0 +1,33 @@ +type: bulk +args: + +#Create resident table +- type: run_sql + args: + sql: | + CREATE TABLE resident ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + age INTEGER NOT NULL + ) +- type: track_table + args: + schema: public + name: resident + +#Create address table +- type: run_sql + args: + sql: | + CREATE TABLE address ( + id SERIAL PRIMARY KEY, + door_no TEXT NOT NULL, + street TEXT NOT NULL, + city TEXT NOT NULL, + resident_id INTEGER REFERENCES resident(id) + ) +- type: track_table + args: + schema: public + name: address + diff --git a/server/tests-py/queries/graphql_mutation/insert/constraints/teardown.yaml b/server/tests-py/queries/graphql_mutation/insert/constraints/teardown.yaml new file mode 100644 index 0000000000000..38987bf568878 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/constraints/teardown.yaml @@ -0,0 +1,12 @@ +type: bulk +args: + +- type: run_sql + args: + sql: | + drop table address + +- type: run_sql + args: + sql: | + drop table resident diff --git a/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_empty_update_columns.yaml b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_empty_update_columns.yaml new file mode 100644 index 0000000000000..ebdd85a292b58 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_empty_update_columns.yaml @@ -0,0 +1,32 @@ +description: Upserts article data via GraphQL mutation with empty update columns +url: /v1alpha1/graphql +status: 200 +response: + data: + insert_article: + returning: [] +query: + query: | + mutation insert_article { + insert_article ( + objects: [ + { + content: "Updated Article 1 content", + id: 1 + }, + { + content: "Updated Article 2 content", + id: 2 + } + ], + on_conflict: { + constraint: article_pkey, + update_columns: [] + } + ) { + returning { + title + content + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_error_missing_article_constraint.yaml b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_error_missing_article_constraint.yaml new file mode 100644 index 0000000000000..af057ab6372c8 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_error_missing_article_constraint.yaml @@ -0,0 +1,27 @@ +description: Upserts article data via GraphQL mutation (Error 01) +url: /v1alpha1/graphql +status: 400 +query: + query: | + mutation insert_article { + insert_article ( + objects: [ + { + content: "Updated Article 1 content", + id: 1 + }, + { + content: "Updated Article 2 content", + id: 2 + } + ], + on_conflict: { + action: update + } + ) { + returning { + title + content + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_ignore_constraint.yaml b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_ignore_constraint.yaml new file mode 100644 index 0000000000000..b0a16f355ee89 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_ignore_constraint.yaml @@ -0,0 +1,33 @@ +# The inserts are ignored on conflict +description: Upserts article data via GraphQL mutation +url: /v1alpha1/graphql +status: 200 +response: + data: + insert_article: + returning: [] +query: + query: | + mutation insert_article { + insert_article ( + objects: [ + { + content: "Updated Article 1 content", + id: 1 + }, + { + content: "Updated Article 2 content", + id: 2 + } + ], + on_conflict: { + constraint: article_pkey, + action: ignore + } + ) { + returning { + title + content + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_no_action_specified.yaml b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_no_action_specified.yaml new file mode 100644 index 0000000000000..d6a51a10a0ec1 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_no_action_specified.yaml @@ -0,0 +1,35 @@ +description: Upserts article data via GraphQL mutation with only constraint +url: /v1alpha1/graphql +response: + data: + insert_article: + returning: + - content: Updated Article 1 content + title: Article 1 + - content: Updated Article 2 content + title: Article 2 +status: 200 +query: + query: | + mutation insert_article { + insert_article ( + objects: [ + { + content: "Updated Article 1 content", + id: 1 + }, + { + content: "Updated Article 2 content", + id: 2 + } + ], + on_conflict: { + constraint: article_pkey + } + ) { + returning { + title + content + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_update.yaml b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_update.yaml new file mode 100644 index 0000000000000..0a423a939e347 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_on_conflict_update.yaml @@ -0,0 +1,36 @@ +description: Upserts article data via GraphQL mutation +url: /v1alpha1/graphql +response: + data: + insert_article: + returning: + - content: Updated Article 1 content + title: Article 1 + - content: Updated Article 2 content + title: Article 2 +status: 200 +query: + query: | + mutation insert_article { + insert_article ( + objects: [ + { + content: "Updated Article 1 content", + id: 1 + }, + { + content: "Updated Article 2 content", + id: 2 + } + ], + on_conflict: { + constraint: article_pkey, + action: update + } + ) { + returning { + title + content + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/onconflict/article_unexpected_on_conflict_action.yaml b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_unexpected_on_conflict_action.yaml new file mode 100644 index 0000000000000..316f23059dbd9 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_unexpected_on_conflict_action.yaml @@ -0,0 +1,27 @@ +description: Upserts article data via GraphQL mutation (Error 02) +url: /v1alpha1/graphql +status: 400 +query: + query: | + mutation insert_article { + insert_article ( + objects: [ + { + content: "Updated Article 1 content", + id: 1 + }, + { + content: "Updated Article 2 content", + id: 2 + } + ], + on_conflict: { + action: random + } + ) { + returning { + title + content + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/onconflict/article_unexpected_on_conflict_constraint_error.yaml b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_unexpected_on_conflict_constraint_error.yaml new file mode 100644 index 0000000000000..14bbc2fd598ee --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/onconflict/article_unexpected_on_conflict_constraint_error.yaml @@ -0,0 +1,28 @@ +description: Upserts article data via GraphQL mutation (Error 03) +url: /v1alpha1/graphql +status: 400 +query: + query: | + mutation insert_article { + insert_article ( + objects: [ + { + content: "Updated Article 1 content", + id: 1 + }, + { + content: "Updated Article 2 content", + id: 2 + } + ], + on_conflict: { + action: update, + constraint: random_constraint + } + ) { + returning { + title + content + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/onconflict/setup.yaml b/server/tests-py/queries/graphql_mutation/insert/onconflict/setup.yaml new file mode 100644 index 0000000000000..105f9332e0815 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/onconflict/setup.yaml @@ -0,0 +1,99 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL PRIMARY KEY, + title TEXT, + content TEXT, + author_id INTEGER REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP + ) +- type: track_table + args: + schema: public + name: article + +#Person table +- type: run_sql + args: + sql: | + CREATE TABLE person ( + id SERIAL PRIMARY KEY, + details JSONB NOT NULL + ) +- type: track_table + args: + schema: public + name: person + +#Order table +- type: run_sql + args: + sql: | + CREATE TABLE orders ( + id SERIAL PRIMARY KEY, + placed TIMESTAMPTZ NOT NULL, + shipped TIMESTAMPTZ + ) +- type: track_table + args: + schema: public + name: orders + + +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Array relationship +- type: create_array_relationship + args: + table: author + name: articles + using: + foreign_key_constraint_on: + table: article + column: author_id + +#Insert Author table data +- type: insert + args: + table: author + objects: + - name: Author 1 + - name: Author 2 + +#Insert aticle table data +- type: insert + args: + table: article + objects: + - content: Sample article content + title: Article 1 + - content: Sample article content + title: Article 2 + - content: Sample article content + title: Article 3 + diff --git a/server/tests-py/queries/graphql_mutation/insert/onconflict/teardown.yaml b/server/tests-py/queries/graphql_mutation/insert/onconflict/teardown.yaml new file mode 100644 index 0000000000000..eb80d35dcc6f5 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/onconflict/teardown.yaml @@ -0,0 +1,26 @@ +type: bulk +args: +#Drop relationship first +- type: drop_relationship + args: + relationship: articles + table: + schema: public + name: author + +- type: run_sql + args: + sql: | + drop table person +- type: run_sql + args: + sql: | + drop table orders +- type: run_sql + args: + sql: | + drop table article +- type: run_sql + args: + sql: | + drop table author diff --git a/server/tests-py/queries/graphql_mutation/insert/permissions/address_permission_error.yaml b/server/tests-py/queries/graphql_mutation/insert/permissions/address_permission_error.yaml new file mode 100644 index 0000000000000..960d49e53da29 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/permissions/address_permission_error.yaml @@ -0,0 +1,17 @@ +description: Insert into order table as user role (Check Constraint Error) +url: /v1alpha1/graphql +status: 400 +headers: + X-Hasura-Role: merchant +query: + query: | + mutation { + insert_address(objects: [{door_no: "12-21", street: "Madhapur", city: "Hyderabad", resident_id: 1}]){ + affected_rows + } + } +response: + errors: + - code: validation-failed + error: no mutations exist + path: $ diff --git a/server/tests-py/queries/graphql_mutation/insert/permissions/article_on_conflict_user_role.yaml b/server/tests-py/queries/graphql_mutation/insert/permissions/article_on_conflict_user_role.yaml new file mode 100644 index 0000000000000..3fcd6cb77551d --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/permissions/article_on_conflict_user_role.yaml @@ -0,0 +1,26 @@ +description: Upserts article data via GraphQL mutation as User role +url: /v1alpha1/graphql +status: 200 +header: + X-Hasura-Role: user + X-Hasura-User-Id: 1 +query: + query: | + mutation insert_article { + insert_article ( + objects: [ + { + content: "Updated Article 1 content", + id: 1 + } + ], + on_conflict: { + constraint: article_pkey + } + ) { + returning { + title + content + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/permissions/author_on_conflict_ignore_user_role.yaml b/server/tests-py/queries/graphql_mutation/insert/permissions/author_on_conflict_ignore_user_role.yaml new file mode 100644 index 0000000000000..f190d52cea27a --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/permissions/author_on_conflict_ignore_user_role.yaml @@ -0,0 +1,28 @@ +description: Upserts author with id 1 as a user (Error) +url: /v1alpha1/graphql +status: 200 +headers: + X-Hasura-Role: user + X-Hasura-User-Id: '1' +query: + query: | + mutation insert_author { + insert_author ( + objects: [ + { + id: 1 + name: "Author 1 Updated" + } + ], + on_conflict: { + constraint: author_pkey, + action: ignore + } + ) { + affected_rows + returning { + id + name + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/permissions/author_user_role_insert_check_is_registered_fail.yaml b/server/tests-py/queries/graphql_mutation/insert/permissions/author_user_role_insert_check_is_registered_fail.yaml new file mode 100644 index 0000000000000..3c0f4bc8cddfe --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/permissions/author_user_role_insert_check_is_registered_fail.yaml @@ -0,0 +1,30 @@ +description: Upserts author with id 1 as a user (Error) +url: /v1alpha1/graphql +status: 400 +headers: + X-Hasura-Role: user + X-Hasura-User-Id: '5' +query: + query: | + mutation insert_author { + insert_author ( + objects: [ + { + id: 5 + name: "Author 5" + is_registered: true + } + ], + on_conflict: { + constraint: author_pkey, + action: ignore + } + ) { + affected_rows + returning { + id + name + is_registered + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/permissions/author_user_role_insert_check_perm_success.yaml b/server/tests-py/queries/graphql_mutation/insert/permissions/author_user_role_insert_check_perm_success.yaml new file mode 100644 index 0000000000000..977d283a6448a --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/permissions/author_user_role_insert_check_perm_success.yaml @@ -0,0 +1,38 @@ +description: Upserts author with id 1 as a user (Error) +url: /v1alpha1/graphql +status: 200 +response: + data: + insert_author: + affected_rows: 1 + returning: + - id: 5 + is_registered: false + name: Author 5 +headers: + X-Hasura-Role: user + X-Hasura-User-Id: '5' +query: + query: | + mutation insert_author { + insert_author ( + objects: [ + { + id: 5 + name: "Author 5" + is_registered: false + } + ], + on_conflict: { + constraint: author_pkey, + action: ignore + } + ) { + affected_rows + returning { + id + name + is_registered + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/permissions/author_user_role_insert_check_user_id_fail.yaml b/server/tests-py/queries/graphql_mutation/insert/permissions/author_user_role_insert_check_user_id_fail.yaml new file mode 100644 index 0000000000000..8c7b588ee46ee --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/permissions/author_user_role_insert_check_user_id_fail.yaml @@ -0,0 +1,30 @@ +description: Upserts author with id 1 as a user (Error) +url: /v1alpha1/graphql +status: 400 +headers: + X-Hasura-Role: user + X-Hasura-User-Id: '5' +query: + query: | + mutation insert_author { + insert_author ( + objects: [ + { + id: 10 + name: "Author 5" + is_registered: false + } + ], + on_conflict: { + constraint: author_pkey, + action: ignore + } + ) { + affected_rows + returning { + id + name + is_registered + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/insert/permissions/setup.yaml b/server/tests-py/queries/graphql_mutation/insert/permissions/setup.yaml new file mode 100644 index 0000000000000..3bc665dadca05 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/permissions/setup.yaml @@ -0,0 +1,129 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique, + is_registered boolean not null default false + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL PRIMARY KEY, + title TEXT, + content TEXT, + author_id INTEGER REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP + ) +- type: track_table + args: + schema: public + name: article + +#Create resident table +- type: run_sql + args: + sql: | + CREATE TABLE resident ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + age INTEGER NOT NULL + ) +- type: track_table + args: + schema: public + name: resident + +#Create address table +- type: run_sql + args: + sql: | + CREATE TABLE address ( + id SERIAL PRIMARY KEY, + door_no TEXT NOT NULL, + street TEXT NOT NULL, + city TEXT NOT NULL, + resident_id INTEGER REFERENCES resident(id) + ) +- type: track_table + args: + schema: public + name: address + +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Array relationship +- type: create_array_relationship + args: + table: author + name: articles + using: + foreign_key_constraint_on: + table: article + column: author_id + +#Article select permission for user +- type: create_select_permission + args: + table: article + role: user + permission: + columns: '*' + filter: + $or: + - author_id: X-HASURA-USER-ID + - is_published: true + +#Article insert permission for user +- type: create_insert_permission + args: + table: article + role: user + permission: + check: + author_id: X-Hasura-User-Id + +#Author select permission for user +- type: create_select_permission + args: + table: author + role: user + permission: + columns: + - id + - name + - is_registered + filter: + id: X-HASURA-USER-ID + +#Author insert permission for user +#Only admin can set is_registered to true +- type: create_insert_permission + args: + table: author + role: user + permission: + check: + $and: + - id: X-HASURA-USER-ID + - is_registered: false + allow_upsert: true + diff --git a/server/tests-py/queries/graphql_mutation/insert/permissions/teardown.yaml b/server/tests-py/queries/graphql_mutation/insert/permissions/teardown.yaml new file mode 100644 index 0000000000000..21d74658682fe --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/insert/permissions/teardown.yaml @@ -0,0 +1,29 @@ +type: bulk +args: +#Drop relationship first +- type: drop_relationship + args: + table: + name: author + schema: public + relationship: articles + +- type: run_sql + args: + sql: | + drop table address + +- type: run_sql + args: + sql: | + drop table resident + +- type: run_sql + args: + sql: | + drop table article + +- type: run_sql + args: + sql: | + drop table author diff --git a/server/tests-py/queries/graphql_mutation/update/basic/author_set_name.yaml b/server/tests-py/queries/graphql_mutation/update/basic/author_set_name.yaml new file mode 100644 index 0000000000000..86ae2d7760a7e --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/basic/author_set_name.yaml @@ -0,0 +1,31 @@ +description: Update mutation on author +url: /v1alpha1/graphql +response: + data: + update_author: + affected_rows: 1 + returning: + - articles: [] + id: 1 + name: Jane +status: 200 +query: + query: | + mutation update_author { + update_author( + where: {id: {_eq: 1}}, + _set: {name: "Jane"} + ) { + affected_rows + returning{ + id + name + articles{ + id + title + content + is_published + } + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/update/basic/person_error_no_operator.yaml b/server/tests-py/queries/graphql_mutation/update/basic/person_error_no_operator.yaml new file mode 100644 index 0000000000000..d7e35befa9da9 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/basic/person_error_no_operator.yaml @@ -0,0 +1,16 @@ +description: Updated person data without any operator +url: /v1alpha1/graphql +status: 400 +query: + query: | + mutation update_person($value: jsonb) { + update_person( + where: {id: {_eq: 2}} + ){ + affected_rows + returning{ + id + details + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/update/basic/person_inc.yaml b/server/tests-py/queries/graphql_mutation/update/basic/person_inc.yaml new file mode 100644 index 0000000000000..b6962458ebd32 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/basic/person_inc.yaml @@ -0,0 +1,19 @@ +description: Updated person data using _inc operator +url: /v1alpha1/graphql +status: 200 +query: + query: | + mutation update_person($value: jsonb) { + update_person( + where: {id: {_eq: 2}}, + _inc: { + id: 1 + } + ){ + affected_rows + returning{ + id + details + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/update/basic/person_set_details.yaml b/server/tests-py/queries/graphql_mutation/update/basic/person_set_details.yaml new file mode 100644 index 0000000000000..4ebde9c9e5bbb --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/basic/person_set_details.yaml @@ -0,0 +1,35 @@ +description: Updated person data using _set operator +url: /v1alpha1/graphql +status: 200 +response: + data: + update_person: + affected_rows: 1 + returning: + - id: 1 + details: + name: + first: john + last: taylor + +query: + variables: + value: + name: + first: john + last: taylor + query: | + mutation update_person($value: jsonb) { + update_person( + where: {id: {_eq: 1}}, + _set: { + details: $value + } + ){ + affected_rows + returning{ + id + details + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/update/basic/setup.yaml b/server/tests-py/queries/graphql_mutation/update/basic/setup.yaml new file mode 100644 index 0000000000000..664c36b3b9bb1 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/basic/setup.yaml @@ -0,0 +1,84 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL PRIMARY KEY, + title TEXT, + content TEXT, + author_id INTEGER REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP + ) +- type: track_table + args: + schema: public + name: article + + +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Array relationship +- type: create_array_relationship + args: + table: author + name: articles + using: + foreign_key_constraint_on: + table: article + column: author_id + +#Person table + +- type: run_sql + args: + sql: | + CREATE TABLE person ( + id SERIAL PRIMARY KEY, + details JSONB NOT NULL + ) +- type: track_table + args: + schema: public + name: person + +#Insert Author table data +- type: insert + args: + table: author + objects: + - name: Author 1 + - name: Author 2 + +#Insert Person table data +- type: insert + args: + table: person + objects: + - details: + name: + first: foo + last: bar + address: foobar diff --git a/server/tests-py/queries/graphql_mutation/update/basic/teardown.yaml b/server/tests-py/queries/graphql_mutation/update/basic/teardown.yaml new file mode 100644 index 0000000000000..6d12696f5057f --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/basic/teardown.yaml @@ -0,0 +1,24 @@ +type: bulk +args: +#Drop relationship first +- type: drop_relationship + args: + table: + name: author + schema: public + relationship: articles + +- type: run_sql + args: + sql: | + drop table article + +- type: run_sql + args: + sql: | + drop table author + +- type: run_sql + args: + sql: | + drop table person diff --git a/server/tests-py/queries/graphql_mutation/update/jsonb/person_append_array.yaml b/server/tests-py/queries/graphql_mutation/update/jsonb/person_append_array.yaml new file mode 100644 index 0000000000000..2283c1fb62938 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/jsonb/person_append_array.yaml @@ -0,0 +1,40 @@ +description: Updated person data using _append operator +url: /v1alpha1/graphql +status: 200 +response: + data: + update_person: + returning: + - details: + - address: + country: Denmark + city: Copenhagen + - address: + country: United Kingdom + city: Canterbury + - address: + country: Australia + city: Sydney + id: 2 + affected_rows: 1 +query: + variables: + value: + address: + country: Australia + city: Sydney + query: | + mutation update_person($value: jsonb) { + update_person( + where: {id: {_eq: 2}}, + _append: { + details: $value + } + ){ + affected_rows + returning{ + id + details + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/update/jsonb/person_append_object.yaml b/server/tests-py/queries/graphql_mutation/update/jsonb/person_append_object.yaml new file mode 100644 index 0000000000000..f566e1329cca9 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/jsonb/person_append_object.yaml @@ -0,0 +1,38 @@ +description: Updated person data using _append operator +url: /v1alpha1/graphql +status: 200 +response: + data: + update_person: + affected_rows: 1 + returning: + - details: + address: + city: Sydney + country: Australia + name: + first: John + last: Taylor + id: 1 + +query: + variables: + value: + address: + country: Australia + city: Sydney + query: | + mutation update_person($value: jsonb) { + update_person( + where: {id: {_eq: 1}}, + _append: { + details: $value + } + ){ + affected_rows + returning{ + id + details + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/update/jsonb/person_delete_array_element.yaml b/server/tests-py/queries/graphql_mutation/update/jsonb/person_delete_array_element.yaml new file mode 100644 index 0000000000000..b29512581c8a7 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/jsonb/person_delete_array_element.yaml @@ -0,0 +1,29 @@ +description: Updated person data using _delete_elem operator +url: /v1alpha1/graphql +response: + data: + update_person: + returning: + - details: + - address: + country: United Kingdom + city: Canterbury + id: 2 + affected_rows: 1 +status: 200 +query: + query: | + mutation update_person($value: jsonb) { + update_person( + where: {id: {_eq: 2}}, + _delete_elem: { + details: 0 + } + ){ + affected_rows + returning{ + id + details + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/update/jsonb/person_delete_at_path.yaml b/server/tests-py/queries/graphql_mutation/update/jsonb/person_delete_at_path.yaml new file mode 100644 index 0000000000000..5567a82555c40 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/jsonb/person_delete_at_path.yaml @@ -0,0 +1,28 @@ +description: Updated person data using _delete_at_path operator +url: /v1alpha1/graphql +status: 200 +response: + data: + update_person: + returning: + - details: + name: + first: John + id: 1 + affected_rows: 1 +query: + query: | + mutation update_person($value: jsonb) { + update_person( + where: {id: {_eq: 1}}, + _delete_at_path: { + details: ["name", "last"] + } + ){ + affected_rows + returning{ + id + details + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/update/jsonb/person_delete_key.yaml b/server/tests-py/queries/graphql_mutation/update/jsonb/person_delete_key.yaml new file mode 100644 index 0000000000000..50536a446d8cd --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/jsonb/person_delete_key.yaml @@ -0,0 +1,29 @@ +description: Updated person data using _delete_key operator +url: /v1alpha1/graphql +response: + data: + update_person: + returning: + - details: + name: + first: Robert + last: Wilson + id: 3 + affected_rows: 1 +status: 200 +query: + query: | + mutation update_person($value: jsonb) { + update_person( + where: {id: {_eq: 3}}, + _delete_key: { + details: "address" + } + ){ + affected_rows + returning{ + id + details + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/update/jsonb/person_inc.yaml b/server/tests-py/queries/graphql_mutation/update/jsonb/person_inc.yaml new file mode 100644 index 0000000000000..b6962458ebd32 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/jsonb/person_inc.yaml @@ -0,0 +1,19 @@ +description: Updated person data using _inc operator +url: /v1alpha1/graphql +status: 200 +query: + query: | + mutation update_person($value: jsonb) { + update_person( + where: {id: {_eq: 2}}, + _inc: { + id: 1 + } + ){ + affected_rows + returning{ + id + details + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/update/jsonb/person_prepend_array.yaml b/server/tests-py/queries/graphql_mutation/update/jsonb/person_prepend_array.yaml new file mode 100644 index 0000000000000..6de621c333685 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/jsonb/person_prepend_array.yaml @@ -0,0 +1,38 @@ +description: Updated person data using _prepend operator +url: /v1alpha1/graphql +response: + data: + update_person: + returning: + - details: + - university: + name: Sydney university + - address: + country: Denmark + city: Copenhagen + - address: + country: United Kingdom + city: Canterbury + id: 2 + affected_rows: 1 +status: 200 +query: + variables: + value: + - university: + name: Sydney university + query: | + mutation update_person($value: jsonb) { + update_person( + where: {id: {_eq: 2}}, + _prepend: { + details: $value + } + ){ + affected_rows + returning{ + id + details + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/update/jsonb/setup.yaml b/server/tests-py/queries/graphql_mutation/update/jsonb/setup.yaml new file mode 100644 index 0000000000000..3e7022be4b99c --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/jsonb/setup.yaml @@ -0,0 +1,39 @@ +type: bulk +args: + +#Person table +- type: run_sql + args: + sql: | + CREATE TABLE person ( + id SERIAL PRIMARY KEY, + details JSONB NOT NULL + ) +- type: track_table + args: + schema: public + name: person + +#Insert Person table data +- type: insert + args: + table: person + objects: + - details: + name: + first: John + last: Taylor + - details: + - address: + city: Copenhagen + country: Denmark + - address: + city: Canterbury + country: United Kingdom + - details: + address: + city: Copenhagen + country: Denmark + name: + first: Robert + last: Wilson diff --git a/server/tests-py/queries/graphql_mutation/update/jsonb/teardown.yaml b/server/tests-py/queries/graphql_mutation/update/jsonb/teardown.yaml new file mode 100644 index 0000000000000..f7330beee995f --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/jsonb/teardown.yaml @@ -0,0 +1,6 @@ +type: bulk +args: +- type: run_sql + args: + sql: | + drop table person diff --git a/server/tests-py/queries/graphql_mutation/update/permissions/setup.yaml b/server/tests-py/queries/graphql_mutation/update/permissions/setup.yaml new file mode 100644 index 0000000000000..92fecfa8c717b --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/permissions/setup.yaml @@ -0,0 +1,145 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL, + title TEXT, + version TEXT, + content TEXT, + author_id INTEGER REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP, + PRIMARY KEY (id,version) + ) +- type: track_table + args: + schema: public + name: article + + +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Array relationship +- type: create_array_relationship + args: + table: author + name: articles + using: + foreign_key_constraint_on: + table: article + column: author_id + +#Person table + +- type: run_sql + args: + sql: | + CREATE TABLE person ( + id SERIAL PRIMARY KEY, + details JSONB NOT NULL + ) +- type: track_table + args: + schema: public + name: person + +#Insert Author table data +- type: insert + args: + table: author + objects: + - id: 1 + name: Author 1 + - id: 2 + name: Author 2 + +#Insert aticle table data +- type: insert + args: + table: article + objects: + - id: 1 + version: 1.0.0 + content: Sample article 1, content version 1.0.0 + title: Article 1 + author_id: 1 + is_published: true + - id: 2 + content: Sample article 1, content version 1.0.1 + version: 1.0.1 + title: Article 1 + author_id: 1 + is_published: false + - id: 3 + content: Sample article 2, content version 1.0.2 + version: 1.0.0 + title: Article 2 + author_id: 2 + is_published: false + + + +#Author select permission for user +- type: create_select_permission + args: + table: author + role: user + permission: + columns: '*' + filter: + id: X-HASURA-USER-ID + +#Article select permission for user +- type: create_select_permission + args: + table: article + role: user + permission: + columns: '*' + filter: + $or: + - author_id: X-HASURA-USER-ID + - is_published: true + + +#Article update permission for user +#Allow modifications only on unpublished articles +- type: create_update_permission + args: + table: article + role: user + permission: + columns: + - title + - content + - is_published + - published_on + - version + filter: + $and: + - author_id: X-HASURA-USER-ID + - is_published: false + diff --git a/server/tests-py/queries/graphql_mutation/update/permissions/teardown.yaml b/server/tests-py/queries/graphql_mutation/update/permissions/teardown.yaml new file mode 100644 index 0000000000000..6d12696f5057f --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/permissions/teardown.yaml @@ -0,0 +1,24 @@ +type: bulk +args: +#Drop relationship first +- type: drop_relationship + args: + table: + name: author + schema: public + relationship: articles + +- type: run_sql + args: + sql: | + drop table article + +- type: run_sql + args: + sql: | + drop table author + +- type: run_sql + args: + sql: | + drop table person diff --git a/server/tests-py/queries/graphql_mutation/update/permissions/user_can_update_unpublished_article.yaml b/server/tests-py/queries/graphql_mutation/update/permissions/user_can_update_unpublished_article.yaml new file mode 100644 index 0000000000000..a37012a02c84e --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/permissions/user_can_update_unpublished_article.yaml @@ -0,0 +1,43 @@ +description: Update mutation on author +url: /v1alpha1/graphql +response: + data: + update_article: + returning: + - content: Article content version 1.0.2 + version: '1.0.2' + is_published: false + author: + name: Author 1 + id: 1 + id: 2 + title: Article 1 + affected_rows: 1 +headers: + X-Hasura-Role: user + X-Hasura-User-Id: '1' +status: 200 +query: + query: | + mutation update_article { + update_article( + where: {id: {_eq: 2}}, + _set: { + content: "Article content version 1.0.2" + version: "1.0.2" + } + ) { + affected_rows + returning{ + id + version + title + content + author { + id + name + } + is_published + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/update/permissions/user_cannot_update_another_users_article.yaml b/server/tests-py/queries/graphql_mutation/update/permissions/user_cannot_update_another_users_article.yaml new file mode 100644 index 0000000000000..f18b6e187f0ae --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/permissions/user_cannot_update_another_users_article.yaml @@ -0,0 +1,35 @@ +description: Update mutation on author +url: /v1alpha1/graphql +response: + data: + update_article: + affected_rows: 0 + returning: [] +headers: + X-Hasura-Role: user + X-Hasura-User-Id: '2' +status: 200 +query: + query: | + mutation update_article { + update_article( + where: {id: {_eq: 1}}, + _set: { + content: "Article content version 1.0.2" + version: "1.0.2" + } + ) { + affected_rows + returning{ + id + version + title + content + author { + id + name + } + is_published + } + } + } diff --git a/server/tests-py/queries/graphql_mutation/update/permissions/user_cannot_update_published_article_version.yaml b/server/tests-py/queries/graphql_mutation/update/permissions/user_cannot_update_published_article_version.yaml new file mode 100644 index 0000000000000..00e8343000579 --- /dev/null +++ b/server/tests-py/queries/graphql_mutation/update/permissions/user_cannot_update_published_article_version.yaml @@ -0,0 +1,35 @@ +description: Update mutation on author +url: /v1alpha1/graphql +response: + data: + update_article: + affected_rows: 0 + returning: [] +headers: + X-Hasura-Role: user + X-Hasura-User-Id: '1' +status: 200 +query: + query: | + mutation update_article { + update_article( + where: {id: {_eq: 1}}, + _set: { + content: "Article content version 1.0.2" + version: "1.0.2" + } + ) { + affected_rows + returning{ + id + version + title + content + author { + id + name + } + is_published + } + } + } diff --git a/server/tests-py/queries/graphql_query/basic/nested_select_query_article_author.yaml b/server/tests-py/queries/graphql_query/basic/nested_select_query_article_author.yaml new file mode 100644 index 0000000000000..debb838bc2e99 --- /dev/null +++ b/server/tests-py/queries/graphql_query/basic/nested_select_query_article_author.yaml @@ -0,0 +1,37 @@ +description: Nested select on article +url: /v1alpha1/graphql +status: 200 +response: + data: + article: + - id: 1 + title: Article 1 + content: Sample article content 1 + author: + id: 1 + name: Author 1 + - id: 2 + title: Article 2 + content: Sample article content 2 + author: + id: 1 + name: Author 1 + - id: 3 + title: Article 3 + content: Sample article content 3 + author: + id: 2 + name: Author 2 +query: + query: | + query { + article { + id + title + content + author { + id + name + } + } + } diff --git a/server/tests-py/queries/graphql_query/basic/nested_select_where_query_author_article.yaml b/server/tests-py/queries/graphql_query/basic/nested_select_where_query_author_article.yaml new file mode 100644 index 0000000000000..a8ae11fa0ae0d --- /dev/null +++ b/server/tests-py/queries/graphql_query/basic/nested_select_where_query_author_article.yaml @@ -0,0 +1,27 @@ +description: Select author and their articles +url: /v1alpha1/graphql +status: 200 +response: + data: + author: + - id: 1 + name: Author 1 + articles: + - title: Article 2 + content: Sample article content 2 + id: 2 +query: + query: | + query { + author (where: {name: {_eq: "Author 1"}}) { + id + name + articles ( + where: {is_published: {_eq: true}} + ) { + id + title + content + } + } + } diff --git a/server/tests-py/queries/graphql_query/basic/select_query_author.yaml b/server/tests-py/queries/graphql_query/basic/select_query_author.yaml new file mode 100644 index 0000000000000..1a85ed30b89bf --- /dev/null +++ b/server/tests-py/queries/graphql_query/basic/select_query_author.yaml @@ -0,0 +1,18 @@ +description: Simple GraphQL object query on author +url: /v1alpha1/graphql +status: 200 +response: + data: + author: + - name: Author 1 + id: 1 + - name: Author 2 + id: 2 +query: + query: | + query { + author { + id + name + } + } diff --git a/server/tests-py/queries/graphql_query/basic/select_query_author_by_pkey.yaml b/server/tests-py/queries/graphql_query/basic/select_query_author_by_pkey.yaml new file mode 100644 index 0000000000000..3f1e1ef9080dc --- /dev/null +++ b/server/tests-py/queries/graphql_query/basic/select_query_author_by_pkey.yaml @@ -0,0 +1,16 @@ +description: select query on author with id = 1 +url: /v1alpha1/graphql +status: 200 +response: + data: + author_by_pk: + name: Author 1 + id: 1 +query: + query: | + query { + author_by_pk(id: 1){ + id + name + } + } diff --git a/server/tests-py/queries/graphql_query/basic/select_query_author_where.yaml b/server/tests-py/queries/graphql_query/basic/select_query_author_where.yaml new file mode 100644 index 0000000000000..28b973dfad3c8 --- /dev/null +++ b/server/tests-py/queries/graphql_query/basic/select_query_author_where.yaml @@ -0,0 +1,16 @@ +description: Simple GraphQL object query on author +url: /v1alpha1/graphql +status: 200 +response: + data: + author: + - name: Author 2 + id: 2 +query: + query: | + query { + author (where: {name: {_eq: "Author 2"}}) { + id + name + } + } diff --git a/server/tests-py/queries/graphql_query/basic/setup.yaml b/server/tests-py/queries/graphql_query/basic/setup.yaml new file mode 100644 index 0000000000000..8d2446e30fe42 --- /dev/null +++ b/server/tests-py/queries/graphql_query/basic/setup.yaml @@ -0,0 +1,85 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL PRIMARY KEY, + title TEXT, + content TEXT, + author_id INTEGER REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP + ) +- type: track_table + args: + schema: public + name: article + +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Array relationship +- type: create_array_relationship + args: + table: author + name: articles + using: + foreign_key_constraint_on: + table: article + column: author_id + + +#Insert values +- type: run_sql + args: + sql: | + insert into author (name) + values + ('Author 1'), + ('Author 2') + +- type: run_sql + args: + sql: | + insert into article (title,content,author_id,is_published) + values + ( + 'Article 1', + 'Sample article content 1', + 1, + false + ), + ( + 'Article 2', + 'Sample article content 2', + 1, + true + ), + ( + 'Article 3', + 'Sample article content 3', + 2, + true + ) + diff --git a/server/tests-py/queries/graphql_query/basic/teardown.yaml b/server/tests-py/queries/graphql_query/basic/teardown.yaml new file mode 100644 index 0000000000000..c4e61d8e138ec --- /dev/null +++ b/server/tests-py/queries/graphql_query/basic/teardown.yaml @@ -0,0 +1,18 @@ +type: bulk +args: +#Drop relationship first +- type: drop_relationship + args: + relationship: articles + table: + schema: public + name: author + +- type: run_sql + args: + sql: | + drop table article +- type: run_sql + args: + sql: | + drop table author diff --git a/server/tests-py/queries/graphql_query/limits/select_query_article_limit_neg_offset.yaml b/server/tests-py/queries/graphql_query/limits/select_query_article_limit_neg_offset.yaml new file mode 100644 index 0000000000000..2804db017643f --- /dev/null +++ b/server/tests-py/queries/graphql_query/limits/select_query_article_limit_neg_offset.yaml @@ -0,0 +1,16 @@ +description: Nested select on article with limit expecting error +url: /v1alpha1/graphql +status: 400 +query: + query: | + query { + article(limit: -1, offset: 1) { + id + title + content + author { + id + name + } + } + } diff --git a/server/tests-py/queries/graphql_query/limits/select_query_article_limit_offset.yaml b/server/tests-py/queries/graphql_query/limits/select_query_article_limit_offset.yaml new file mode 100644 index 0000000000000..79e0422ecb192 --- /dev/null +++ b/server/tests-py/queries/graphql_query/limits/select_query_article_limit_offset.yaml @@ -0,0 +1,16 @@ +description: Nested select on article with limit +url: /v1alpha1/graphql +status: 200 +query: + query: | + query { + article(limit: 3, offset: 2) { + id + title + content + author { + id + name + } + } + } diff --git a/server/tests-py/queries/graphql_query/limits/select_query_article_limit_string_offset_error.yaml b/server/tests-py/queries/graphql_query/limits/select_query_article_limit_string_offset_error.yaml new file mode 100644 index 0000000000000..da5c155186955 --- /dev/null +++ b/server/tests-py/queries/graphql_query/limits/select_query_article_limit_string_offset_error.yaml @@ -0,0 +1,16 @@ +description: Nested select on article with limit expecting error +url: /v1alpha1/graphql +status: 400 +query: + query: | + query { + article(limit: "3", offset: 1) { + id + title + content + author { + id + name + } + } + } diff --git a/server/tests-py/queries/graphql_query/limits/setup.yaml b/server/tests-py/queries/graphql_query/limits/setup.yaml new file mode 100644 index 0000000000000..395bf5b49c2f6 --- /dev/null +++ b/server/tests-py/queries/graphql_query/limits/setup.yaml @@ -0,0 +1,70 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL PRIMARY KEY, + title TEXT, + content TEXT, + author_id INTEGER REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP + ) +- type: track_table + args: + schema: public + name: article +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Insert values +- type: run_sql + args: + sql: | + insert into author (name) + values + ('Author 1'), + ('Author 2') + +- type: run_sql + args: + sql: | + insert into article (title,content,author_id) + values + ( + 'Article 1', + 'Sample article content 1', + 1 + ), + ( + 'Article 2', + 'Sample article content 2', + 1 + ), + ( + 'Article 3', + 'Sample article content 3', + 2 + ) + diff --git a/server/tests-py/queries/graphql_query/limits/teardown.yaml b/server/tests-py/queries/graphql_query/limits/teardown.yaml new file mode 100644 index 0000000000000..5a09757e417a3 --- /dev/null +++ b/server/tests-py/queries/graphql_query/limits/teardown.yaml @@ -0,0 +1,10 @@ +type: bulk +args: +- type: run_sql + args: + sql: | + drop table article +- type: run_sql + args: + sql: | + drop table author diff --git a/server/tests-py/queries/insert_only/setup.yaml b/server/tests-py/queries/insert_only/setup.yaml new file mode 100644 index 0000000000000..83bd9b833a550 --- /dev/null +++ b/server/tests-py/queries/insert_only/setup.yaml @@ -0,0 +1,22 @@ +type: bulk +args: +- type: run_sql + args: + sql: | + create table hge_tests.test_t1( + c1 int, + c2 text + ); +- type: track_table + args: + schema: hge_tests + name: test_t1 +- type: create_event_trigger + args: + name: t1_all + table: + schema: hge_tests + name: test_t1 + insert: + columns: "*" + webhook: http://127.0.0.1:5592 diff --git a/server/tests-py/queries/insert_only/teardown.yaml b/server/tests-py/queries/insert_only/teardown.yaml new file mode 100644 index 0000000000000..a0766f4d43ca0 --- /dev/null +++ b/server/tests-py/queries/insert_only/teardown.yaml @@ -0,0 +1,9 @@ +type: bulk +args: +- type: delete_event_trigger + args: + name: t1_all +- type: run_sql + args: + sql: | + drop table hge_tests.test_t1 diff --git a/server/tests-py/queries/selected_cols/setup.yaml b/server/tests-py/queries/selected_cols/setup.yaml new file mode 100644 index 0000000000000..0ba0ecdbab643 --- /dev/null +++ b/server/tests-py/queries/selected_cols/setup.yaml @@ -0,0 +1,30 @@ +type: bulk +args: +- type: run_sql + args: + sql: | + create table hge_tests.test_t1( + c1 int, + c2 text, + c3 text + ); +- type: track_table + args: + schema: hge_tests + name: test_t1 +- type: create_event_trigger + args: + name: t1_all + table: + schema: hge_tests + name: test_t1 + insert: + columns: ["c2"] + update: + columns: ["c1"] + delete: + columns: ["c1", "c2"] + webhook: http://127.0.0.1:5592 + retry_conf: + num_retries: 10 + interval_sec: 100 diff --git a/server/tests-py/queries/selected_cols/teardown.yaml b/server/tests-py/queries/selected_cols/teardown.yaml new file mode 100644 index 0000000000000..a0766f4d43ca0 --- /dev/null +++ b/server/tests-py/queries/selected_cols/teardown.yaml @@ -0,0 +1,9 @@ +type: bulk +args: +- type: delete_event_trigger + args: + name: t1_all +- type: run_sql + args: + sql: | + drop table hge_tests.test_t1 diff --git a/server/tests-py/queries/v1/delete/delete_article.yaml b/server/tests-py/queries/v1/delete/delete_article.yaml new file mode 100644 index 0000000000000..73e53e4a258d6 --- /dev/null +++ b/server/tests-py/queries/v1/delete/delete_article.yaml @@ -0,0 +1,19 @@ +url: /v1/query +status: 200 +response: + returning: + - author_id: 1 + content: Sample article content 2 + id: 2 + affected_rows: 1 +query: + type: delete + args: + table: article + where: + id: 2 + returning: + - id + - content + - author_id + diff --git a/server/tests-py/queries/v1/delete/setup.yaml b/server/tests-py/queries/v1/delete/setup.yaml new file mode 100644 index 0000000000000..8d2446e30fe42 --- /dev/null +++ b/server/tests-py/queries/v1/delete/setup.yaml @@ -0,0 +1,85 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL PRIMARY KEY, + title TEXT, + content TEXT, + author_id INTEGER REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP + ) +- type: track_table + args: + schema: public + name: article + +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Array relationship +- type: create_array_relationship + args: + table: author + name: articles + using: + foreign_key_constraint_on: + table: article + column: author_id + + +#Insert values +- type: run_sql + args: + sql: | + insert into author (name) + values + ('Author 1'), + ('Author 2') + +- type: run_sql + args: + sql: | + insert into article (title,content,author_id,is_published) + values + ( + 'Article 1', + 'Sample article content 1', + 1, + false + ), + ( + 'Article 2', + 'Sample article content 2', + 1, + true + ), + ( + 'Article 3', + 'Sample article content 3', + 2, + true + ) + diff --git a/server/tests-py/queries/v1/delete/teardown.yaml b/server/tests-py/queries/v1/delete/teardown.yaml new file mode 100644 index 0000000000000..c4e61d8e138ec --- /dev/null +++ b/server/tests-py/queries/v1/delete/teardown.yaml @@ -0,0 +1,18 @@ +type: bulk +args: +#Drop relationship first +- type: drop_relationship + args: + relationship: articles + table: + schema: public + name: author + +- type: run_sql + args: + sql: | + drop table article +- type: run_sql + args: + sql: | + drop table author diff --git a/server/tests-py/queries/v1/insert/basic/insert_author.yaml b/server/tests-py/queries/v1/insert/basic/insert_author.yaml new file mode 100644 index 0000000000000..2215e02d2ac0f --- /dev/null +++ b/server/tests-py/queries/v1/insert/basic/insert_author.yaml @@ -0,0 +1,19 @@ +url: /v1/query +status: 200 +response: + affected_rows: 2 + returning: + - id: 1 + name: Author 1 + - id: 2 + name: Author 2 +query: + type: insert + args: + table: author + objects: + - name: Author 1 + - name: Author 2 + returning: + - name + - id diff --git a/server/tests-py/queries/v1/insert/basic/insert_author_col_not_present_err.yaml b/server/tests-py/queries/v1/insert/basic/insert_author_col_not_present_err.yaml new file mode 100644 index 0000000000000..683041b6a646a --- /dev/null +++ b/server/tests-py/queries/v1/insert/basic/insert_author_col_not_present_err.yaml @@ -0,0 +1,12 @@ +url: /v1/query +status: 400 +query: + type: insert + args: + table: author + objects: + - name: Author 1 + age: 23 + returning: + - name + - id diff --git a/server/tests-py/queries/v1/insert/basic/setup.yaml b/server/tests-py/queries/v1/insert/basic/setup.yaml new file mode 100644 index 0000000000000..1ca7c48497933 --- /dev/null +++ b/server/tests-py/queries/v1/insert/basic/setup.yaml @@ -0,0 +1,51 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL PRIMARY KEY, + title TEXT, + content TEXT, + author_id INTEGER REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP + ) +- type: track_table + args: + schema: public + name: article + +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Array relationship +- type: create_array_relationship + args: + table: author + name: articles + using: + foreign_key_constraint_on: + table: article + column: author_id + diff --git a/server/tests-py/queries/v1/insert/basic/teardown.yaml b/server/tests-py/queries/v1/insert/basic/teardown.yaml new file mode 100644 index 0000000000000..c4e61d8e138ec --- /dev/null +++ b/server/tests-py/queries/v1/insert/basic/teardown.yaml @@ -0,0 +1,18 @@ +type: bulk +args: +#Drop relationship first +- type: drop_relationship + args: + relationship: articles + table: + schema: public + name: author + +- type: run_sql + args: + sql: | + drop table article +- type: run_sql + args: + sql: | + drop table author diff --git a/server/tests-py/queries/v1/insert/onconflict/setup.yaml b/server/tests-py/queries/v1/insert/onconflict/setup.yaml new file mode 100644 index 0000000000000..1ca7c48497933 --- /dev/null +++ b/server/tests-py/queries/v1/insert/onconflict/setup.yaml @@ -0,0 +1,51 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL PRIMARY KEY, + title TEXT, + content TEXT, + author_id INTEGER REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP + ) +- type: track_table + args: + schema: public + name: article + +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Array relationship +- type: create_array_relationship + args: + table: author + name: articles + using: + foreign_key_constraint_on: + table: article + column: author_id + diff --git a/server/tests-py/queries/v1/insert/onconflict/teardown.yaml b/server/tests-py/queries/v1/insert/onconflict/teardown.yaml new file mode 100644 index 0000000000000..c4e61d8e138ec --- /dev/null +++ b/server/tests-py/queries/v1/insert/onconflict/teardown.yaml @@ -0,0 +1,18 @@ +type: bulk +args: +#Drop relationship first +- type: drop_relationship + args: + relationship: articles + table: + schema: public + name: author + +- type: run_sql + args: + sql: | + drop table article +- type: run_sql + args: + sql: | + drop table author diff --git a/server/tests-py/queries/v1/insert/onconflict/upsert_author.yaml b/server/tests-py/queries/v1/insert/onconflict/upsert_author.yaml new file mode 100644 index 0000000000000..f7cfd919ad656 --- /dev/null +++ b/server/tests-py/queries/v1/insert/onconflict/upsert_author.yaml @@ -0,0 +1,21 @@ +url: /v1/query +status: 200 +response: + affected_rows: 1 + returning: + - id: 1 + name: Author 1 updated +query: + type: insert + args: + table: author + objects: + - name: Author 1 updated + id : 1 + on_conflict: + constraint_on: + - id + action: update + returning: + - name + - id diff --git a/server/tests-py/queries/v1/metadata/reload_metadata.yaml b/server/tests-py/queries/v1/metadata/reload_metadata.yaml new file mode 100644 index 0000000000000..02485a5f9a9d5 --- /dev/null +++ b/server/tests-py/queries/v1/metadata/reload_metadata.yaml @@ -0,0 +1,6 @@ +description: Reload schema cache (metadata) +url: /v1/query +status: 200 +query: + type: reload_metadata + args: {} diff --git a/server/tests-py/queries/v1/metadata/setup.yaml b/server/tests-py/queries/v1/metadata/setup.yaml new file mode 100644 index 0000000000000..d55bbfcc94b62 --- /dev/null +++ b/server/tests-py/queries/v1/metadata/setup.yaml @@ -0,0 +1,52 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL PRIMARY KEY, + title TEXT, + content TEXT, + author_id INTEGER REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP + ) +- type: track_table + args: + schema: public + name: article + + +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Array relationship +- type: create_array_relationship + args: + table: author + name: articles + using: + foreign_key_constraint_on: + table: article + column: author_id + diff --git a/server/tests-py/queries/v1/metadata/teardown.yaml b/server/tests-py/queries/v1/metadata/teardown.yaml new file mode 100644 index 0000000000000..c4e61d8e138ec --- /dev/null +++ b/server/tests-py/queries/v1/metadata/teardown.yaml @@ -0,0 +1,18 @@ +type: bulk +args: +#Drop relationship first +- type: drop_relationship + args: + relationship: articles + table: + schema: public + name: author + +- type: run_sql + args: + sql: | + drop table article +- type: run_sql + args: + sql: | + drop table author diff --git a/server/tests-py/queries/v1/select/basic/select_article.yaml b/server/tests-py/queries/v1/select/basic/select_article.yaml new file mode 100644 index 0000000000000..92c9b5af79606 --- /dev/null +++ b/server/tests-py/queries/v1/select/basic/select_article.yaml @@ -0,0 +1,14 @@ +url: /v1/query +status: 200 +response: +- id: 1 + name: Author 1 +- id: 2 + name: Author 2 +query: + type: select + args: + table: author + columns: + - id + - name diff --git a/server/tests-py/queries/v1/select/basic/select_article_col_not_present_err.yaml b/server/tests-py/queries/v1/select/basic/select_article_col_not_present_err.yaml new file mode 100644 index 0000000000000..f5152d3bd7d82 --- /dev/null +++ b/server/tests-py/queries/v1/select/basic/select_article_col_not_present_err.yaml @@ -0,0 +1,10 @@ +url: /v1/query +status: 400 +query: + type: select + args: + table: author + columns: + - id + - name + - user diff --git a/server/tests-py/queries/v1/select/basic/setup.yaml b/server/tests-py/queries/v1/select/basic/setup.yaml new file mode 100644 index 0000000000000..8d2446e30fe42 --- /dev/null +++ b/server/tests-py/queries/v1/select/basic/setup.yaml @@ -0,0 +1,85 @@ +type: bulk +args: + +#Author table +- type: run_sql + args: + sql: | + create table author( + id serial primary key, + name text unique + ); +- type: track_table + args: + schema: public + name: author + +#Article table +- type: run_sql + args: + sql: | + CREATE TABLE article ( + id SERIAL PRIMARY KEY, + title TEXT, + content TEXT, + author_id INTEGER REFERENCES author(id), + is_published BOOLEAN, + published_on TIMESTAMP + ) +- type: track_table + args: + schema: public + name: article + +#Object relationship +- type: create_object_relationship + args: + table: article + name: author + using: + foreign_key_constraint_on: author_id + +#Array relationship +- type: create_array_relationship + args: + table: author + name: articles + using: + foreign_key_constraint_on: + table: article + column: author_id + + +#Insert values +- type: run_sql + args: + sql: | + insert into author (name) + values + ('Author 1'), + ('Author 2') + +- type: run_sql + args: + sql: | + insert into article (title,content,author_id,is_published) + values + ( + 'Article 1', + 'Sample article content 1', + 1, + false + ), + ( + 'Article 2', + 'Sample article content 2', + 1, + true + ), + ( + 'Article 3', + 'Sample article content 3', + 2, + true + ) + diff --git a/server/tests-py/queries/v1/select/basic/teardown.yaml b/server/tests-py/queries/v1/select/basic/teardown.yaml new file mode 100644 index 0000000000000..c4e61d8e138ec --- /dev/null +++ b/server/tests-py/queries/v1/select/basic/teardown.yaml @@ -0,0 +1,18 @@ +type: bulk +args: +#Drop relationship first +- type: drop_relationship + args: + relationship: articles + table: + schema: public + name: author + +- type: run_sql + args: + sql: | + drop table article +- type: run_sql + args: + sql: | + drop table author diff --git a/server/tests-py/requirements.txt b/server/tests-py/requirements.txt new file mode 100644 index 0000000000000..2285857ff7b74 --- /dev/null +++ b/server/tests-py/requirements.txt @@ -0,0 +1,6 @@ +psycopg2-binary +sqlalchemy +pytest +requests +pyyaml +websocket-client diff --git a/server/tests-py/test_events.py b/server/tests-py/test_events.py new file mode 100755 index 0000000000000..92e41cbb5ffba --- /dev/null +++ b/server/tests-py/test_events.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python3 + +import pytest +import queue +import yaml +from validate import check_delete, check_update, check_insert + +class TestEvtBasic(object): + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + print ("In setup method") + st_code, resp = hge_ctx.v1q_f('queries/basic/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f('queries/basic/teardown.yaml') + assert st_code == 200, resp + + + def test_basic(self,hge_ctx): + + table = {"schema" : "hge_tests", "name": "test_t1"} + + init_row = {"c1" : 1, "c2" : "hello"} + exp_ev_data = { + "old": None, + "new": init_row + } + check_insert(hge_ctx, "t1_all", table, init_row, exp_ev_data) + + where_exp = {"c1": 1} + set_exp = {"c2" : "world"} + exp_ev_data = { + "old": init_row, + "new": {"c1" : 1, "c2" : "world"} + } + check_update(hge_ctx, "t1_all", table, init_row, where_exp, set_exp, exp_ev_data) + + exp_ev_data = { + "old": {"c1" : 1, "c2" : "world"}, + "new": None + } + check_delete(hge_ctx, "t1_all", table, where_exp, exp_ev_data) + + + def test_basic_dep(self,hge_ctx): + + st_code, resp = hge_ctx.v1q({ + "type": "run_sql", + "args": { + "sql": "alter table hge_tests.test_t1 drop column c1" + } + }) + assert st_code == 400, resp + assert resp['code'] == "dependency-error", resp + + + +@pytest.mark.usefixtures('hge_ctx') +class TestEvtSelCols: + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + print ("In setup method") + st_code, resp = hge_ctx.v1q_f('queries/selected_cols/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f('queries/selected_cols/teardown.yaml') + assert st_code == 200, resp + + def test_selected_cols(self, hge_ctx): + + table = {"schema" : "hge_tests", "name": "test_t1"} + + init_row = {"c1" : 1, "c2" : "hello"} + exp_ev_data = { + "old": None, + "new": {"c2": "hello"} + } + check_insert(hge_ctx, "t1_all", table, init_row, exp_ev_data) + + where_exp = {"c1": 1} + set_exp = {"c2" : "world"} + exp_ev_data = { + "old": {"c1" : 1}, + "new": {"c1" : 1} + } + check_update(hge_ctx, "t1_all", table, init_row, where_exp, set_exp, exp_ev_data) + + exp_ev_data = { + "old": {"c1" : 1, "c2" : "world"}, + "new": None + } + check_delete(hge_ctx, "t1_all", table, where_exp, exp_ev_data) + + + def test_selected_cols_dep(self, hge_ctx): + + st_code, resp = hge_ctx.v1q({ + "type": "run_sql", + "args": { + "sql": "alter table hge_tests.test_t1 drop column c1" + } + }) + assert st_code == 400, resp + assert resp['code'] == "dependency-error", resp + + st_code, resp = hge_ctx.v1q({ + "type": "run_sql", + "args": { + "sql": "alter table hge_tests.test_t1 drop column c2" + } + }) + assert st_code == 400, resp + assert resp['code'] == "dependency-error", resp + + st_code, resp = hge_ctx.v1q({ + "type": "run_sql", + "args": { + "sql": "alter table hge_tests.test_t1 drop column c3" + } + }) + assert st_code == 200, resp + + + + + +class TestEvtEmptyCols: + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + print ("In setup method") + st_code, resp = hge_ctx.v1q_f('queries/empty_cols/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f('queries/empty_cols/teardown.yaml') + assert st_code == 200, resp + + + def test_empty_cols(self, hge_ctx): + + table = {"schema" : "hge_tests", "name": "test_t1"} + + init_row = {"c1" : 1, "c2" : "hello"} + exp_ev_data = { + "old": None, + "new": {} + } + check_insert(hge_ctx, "t1_all", table, init_row, exp_ev_data) + + where_exp = {"c1": 1} + set_exp = {"c2" : "world"} + exp_ev_data = { + "old": {}, + "new": {} + } + check_update(hge_ctx, "t1_all", table, init_row, where_exp, set_exp, exp_ev_data) + + exp_ev_data = { + "old": {}, + "new": None + } + check_delete(hge_ctx, "t1_all", table, where_exp, exp_ev_data) + + +class TestEvtInsertOnly: + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + print ("In setup method") + st_code, resp = hge_ctx.v1q_f('queries/insert_only/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f('queries/insert_only/teardown.yaml') + assert st_code == 200, resp + + + def test_insert_only(self, hge_ctx): + + table = {"schema" : "hge_tests", "name": "test_t1"} + + init_row = {"c1" : 1, "c2" : "hello"} + exp_ev_data = { + "old": None, + "new": init_row + } + check_insert(hge_ctx, "t1_all", table, init_row, exp_ev_data) + + where_exp = {"c1": 1} + set_exp = {"c2" : "world"} + exp_ev_data = { + "old": init_row, + "new": {"c1" : 1, "c2" : "world"} + } + with pytest.raises(queue.Empty): + check_update(hge_ctx, "t1_all", table, init_row, where_exp, set_exp, exp_ev_data) + + exp_ev_data = { + "old": {"c1" : 1, "c2" : "world"}, + "new": None + } + with pytest.raises(queue.Empty): + check_delete(hge_ctx, "t1_all", table, where_exp, exp_ev_data) + diff --git a/server/tests-py/test_graphql_mutations.py b/server/tests-py/test_graphql_mutations.py new file mode 100644 index 0000000000000..d06ee183b2cf9 --- /dev/null +++ b/server/tests-py/test_graphql_mutations.py @@ -0,0 +1,228 @@ + +import pytest +import yaml +from validate import check_query_f + +class TestGraphQLInsert(object): + + def test_inserts_author_article(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/author_article.yaml") + + def test_insert_using_variable(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/person_jsonb_variable.yaml") + + def test_insert_using_array_variable(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/person_jsonb_variable_array.yaml") + + def test_insert_null_col_value(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/order_col_shipped_null.yaml") + + def test_insert_unique_constraint_err(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/author_unique_constraint_error.yaml") + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/graphql_mutation/insert/basic" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp + + +class TestGraphqlInsertOnConflict(object): + + def test_on_conflict_update(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/article_on_conflict_update.yaml") + + def test_on_conflict_no_action_specified(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/article_on_conflict_no_action_specified.yaml") + + def test_on_conflict_ignore(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/article_on_conflict_ignore_constraint.yaml") + + def test_on_conflict_update_empty_cols(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/article_on_conflict_empty_update_columns.yaml") + + def test_err_missing_article_constraint(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/article_on_conflict_error_missing_article_constraint.yaml") + + def test_err_unexpected_action(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/article_unexpected_on_conflict_action.yaml") + + def test_err_unexpected_constraint(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/article_unexpected_on_conflict_constraint_error.yaml") + + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/graphql_mutation/insert/onconflict" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp + + + +class TestGraphqlInsertPermission(object): + + def test_user_role_on_conflict_update(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/article_on_conflict_user_role.yaml") + + def test_user_role_on_conflict_ignore(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/author_on_conflict_ignore_user_role.yaml") + + def test_role_has_no_permissions_err(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/address_permission_error.yaml") + + def test_author_user_role_insert_check_perm_success(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/author_user_role_insert_check_perm_success.yaml") + + def test_user_role_insert_check_is_registered_fail(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/author_user_role_insert_check_is_registered_fail.yaml") + + def test_user_role_insert_check_user_id_fail(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/author_user_role_insert_check_user_id_fail.yaml") + + + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/graphql_mutation/insert/permissions" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp + + + +class TestGraphqlInsertConstraints(object): + + def test_address_not_null_constraint_err(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/address_not_null_constraint_error.yaml") + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/graphql_mutation/insert/constraints" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp + + + +class TestGraphqlUpdateBasic: + + def test_set_author_name(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/author_set_name.yaml") + + def test_set_person_details(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/person_set_details.yaml") + + def test_person_id_inc(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/person_inc.yaml") + + + def test_no_operator_err(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/person_error_no_operator.yaml") + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/graphql_mutation/update/basic" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp + + +class TestGraphqlUpdateJsonB: + + def test_jsonb_append_object(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/person_append_object.yaml") + + def test_jsonb_append_array(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/person_append_array.yaml") + + def test_jsonb_prepend_array(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/person_prepend_array.yaml") + + def test_jsonb_delete_at_path(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/person_delete_at_path.yaml") + + def test_jsonb_delete_array_element(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/person_delete_array_element.yaml") + + def test_jsonb_delete_key(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/person_delete_key.yaml") + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/graphql_mutation/update/jsonb" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp + +class TestGraphqlUpdatePermissions: + + def test_user_can_update_unpublished_article(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/user_can_update_unpublished_article.yaml") + + def test_user_cannot_modify_published_version_article(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/user_cannot_update_published_article_version.yaml") + + def test_user_cannot_update_another_users_article(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/user_cannot_update_another_users_article.yaml") + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/graphql_mutation/update/permissions" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp + + +class TestGraphqlDelete: + + def test_article_delete(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/article.yaml") + + def test_article_delete_returning(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/article_returning.yaml") + + def test_author_delete_foreign_key_violation(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/author_foreign_key_violation.yaml") + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/graphql_mutation/delete" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp + + +class TestGraphqlIntrospection: + + def test_introspection(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/introspection.yaml") + + def test_introspection_user(self, hge_ctx): + check_query_f(hge_ctx, self.dir + "/introspection_user_role.yaml") + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/graphql_introspection" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp diff --git a/server/tests-py/test_graphql_queries.py b/server/tests-py/test_graphql_queries.py new file mode 100644 index 0000000000000..a035556456946 --- /dev/null +++ b/server/tests-py/test_graphql_queries.py @@ -0,0 +1,48 @@ +import pytest +import yaml +from validate import check_query_f + +class TestGraphQLQueryBasic(object): + + def test_select_query_author(self, hge_ctx): + check_query_f(hge_ctx, 'queries/graphql_query/basic/select_query_author.yaml') + + def test_select_query_author_pk(self, hge_ctx): + check_query_f(hge_ctx, "queries/graphql_query/basic/select_query_author_by_pkey.yaml") + + def test_select_query_where(self, hge_ctx): + check_query_f(hge_ctx, "queries/graphql_query/basic/select_query_author_where.yaml") + + def test_nested_select_query_article_author(self, hge_ctx): + check_query_f(hge_ctx, "queries/graphql_query/basic/nested_select_query_article_author.yaml") + + def test_nested_select_query_where(self, hge_ctx): + check_query_f(hge_ctx, "queries/graphql_query/basic/nested_select_where_query_author_article.yaml") + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + st_code, resp = hge_ctx.v1q_f('queries/graphql_query/basic/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f('queries/graphql_query/basic/teardown.yaml') + assert st_code == 200, resp + +class TestGraphQLQueryLimits(object): + + def test_limit_offset(self, hge_ctx): + check_query_f(hge_ctx, "queries/graphql_query/limits/select_query_article_limit_offset.yaml") + + def test_err_str_offset(self, hge_ctx): + check_query_f(hge_ctx, "queries/graphql_query/limits/select_query_article_limit_string_offset_error.yaml") + + def test_err_neg_offset(self, hge_ctx): + check_query_f(hge_ctx, "queries/graphql_query/limits/select_query_article_limit_neg_offset.yaml") + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + st_code, resp = hge_ctx.v1q_f('queries/graphql_query/limits/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f('queries/graphql_query/limits/teardown.yaml') + assert st_code == 200, resp + diff --git a/server/tests-py/test_subscriptions.py b/server/tests-py/test_subscriptions.py new file mode 100644 index 0000000000000..ffb0317a21993 --- /dev/null +++ b/server/tests-py/test_subscriptions.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 + +import pytest +import json +import queue + +class TestSubscriptionBasic(object): + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + print ("In setup method") + st_code, resp = hge_ctx.v1q_f('queries/basic/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f('queries/basic/teardown.yaml') + assert st_code == 200, resp + + ''' + Refer: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init + ''' + def test_init(self, hge_ctx): + obj = { + 'type': 'connection_init', + 'payload': {}, + } + hge_ctx.ws.send(json.dumps(obj)) + ev = hge_ctx.get_ws_event(3) + assert ev['type'] == 'connection_ack', ev + + ''' + Refer: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_error + ''' + def test_connection_error(self, hge_ctx): + hge_ctx.ws.send("test") + ev = hge_ctx.get_ws_event(3) + assert ev['type'] == 'connection_error', ev + + ''' + Refer: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_start + ''' + def test_start(self, hge_ctx): + query = """ + subscription { + hge_tests_test_t1(order_by: c1_desc, limit: 1) { + c1, + c2 + } + } + """ + obj = { + 'id': '1', + 'payload': { + 'query': query + }, + 'type': 'start' + } + hge_ctx.ws.send(json.dumps(obj)) + ''' + Refer: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_data + ''' + ev = hge_ctx.get_ws_event(3) + assert ev['type'] == 'data' and ev['id'] == '1', ev + + ''' + Refer https://github.com/apollographql/subscriptions-transport-ws/blob/01e0b2b65df07c52f5831cce5c858966ba095993/src/server.ts#L306 + ''' + @pytest.mark.skip(reason="refer https://github.com/hasura/graphql-engine/pull/387#issuecomment-421343098") + def test_start_duplicate(self, hge_ctx): + self.test_start(hge_ctx) + + def test_stop_without_id(self, hge_ctx): + obj = { + 'type': 'stop' + } + hge_ctx.ws.send(json.dumps(obj)) + ev = hge_ctx.get_ws_event(3) + assert ev['type'] == 'connection_error', ev + + ''' + Refer https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_stop + ''' + def test_stop(self, hge_ctx): + obj = { + 'type': 'stop', + 'id': '1' + } + hge_ctx.ws.send(json.dumps(obj)) + + def test_start_after_stop(self, hge_ctx): + self.test_start(hge_ctx) + + ''' + Refer: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_complete + ''' + def test_complete(self, hge_ctx): + query = """ + query { + hge_tests_test_t1(order_by: c1_desc, limit: 1) { + c1, + c2 + } + } + """ + obj = { + 'id': '2', + 'payload': { + 'query': query + }, + 'type': 'start' + } + hge_ctx.ws.send(json.dumps(obj)) + ev = hge_ctx.get_ws_event(3) + assert ev['type'] == 'data' and ev['id'] == '2', ev + # Check for complete type + ev = hge_ctx.get_ws_event(3) + assert ev['type'] == 'complete' and ev['id'] == '2', ev + + ''' + Refer: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_terminate + ''' + def test_connection_terminate(self, hge_ctx): + obj = { + 'type': 'connection_terminate' + } + hge_ctx.ws.send(json.dumps(obj)) + with pytest.raises(queue.Empty): + ev = hge_ctx.get_ws_event(3) diff --git a/server/tests-py/test_v1_queries.py b/server/tests-py/test_v1_queries.py new file mode 100644 index 0000000000000..6439d3c396d1b --- /dev/null +++ b/server/tests-py/test_v1_queries.py @@ -0,0 +1,80 @@ + +import pytest +import yaml +from validate import check_query_f + +class TestV1Select: + + def test_select_query_author(self, hge_ctx): + check_query_f(hge_ctx, self.dir + '/select_article.yaml') + + def test_select_col_not_present(self, hge_ctx): + check_query_f(hge_ctx, self.dir + '/select_article_col_not_present_err.yaml') + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/v1/select/basic" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp + +class TestV1Insert: + + def test_insert_author(self, hge_ctx): + check_query_f(hge_ctx, self.dir + '/insert_author.yaml') + + def test_insert_author_col_not_present_err(self, hge_ctx): + check_query_f(hge_ctx, self.dir + '/insert_author_col_not_present_err.yaml') + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/v1/insert/basic" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp + +class TestV1InsertOnConflict: + + def test_upsert_author(self, hge_ctx): + check_query_f(hge_ctx, self.dir + '/upsert_author.yaml') + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/v1/insert/onconflict" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp + +class TestV1Delete: + + def test_delete_author(self, hge_ctx): + check_query_f(hge_ctx, self.dir + '/delete_article.yaml') + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/v1/delete" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp + +class TestMetadata: + + def test_reload_metadata(self, hge_ctx): + check_query_f(hge_ctx, self.dir + '/reload_metadata.yaml') + + @pytest.fixture(autouse=True) + def transact(self, request, hge_ctx): + self.dir = "queries/v1/metadata" + st_code, resp = hge_ctx.v1q_f(self.dir + '/setup.yaml') + assert st_code == 200, resp + yield + st_code, resp = hge_ctx.v1q_f(self.dir + '/teardown.yaml') + assert st_code == 200, resp diff --git a/server/tests-py/test_version.py b/server/tests-py/test_version.py new file mode 100644 index 0000000000000..b4e55b23f26fb --- /dev/null +++ b/server/tests-py/test_version.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 + +import pytest + +class TestServerVersion(object): + + def test_version(self, hge_ctx): + resp = hge_ctx.http.get( + hge_ctx.hge_url + '/v1/version' + ) + my_json = resp.json() + assert my_json['version'] == hge_ctx.version, my_json diff --git a/server/tests-py/validate.py b/server/tests-py/validate.py new file mode 100644 index 0000000000000..d117343b835d0 --- /dev/null +++ b/server/tests-py/validate.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 + +import yaml + +def check_keys(keys, obj): + for k in keys: + assert k in obj, obj + +def check_ev_payload_shape(ev_payload): + + top_level_keys = [ "created_at", "event", "id", "table", "trigger"] + check_keys(top_level_keys, ev_payload) + + event_keys = ["data", "op"] + check_keys(event_keys, ev_payload['event']) + + trigger_keys = ["id", "name"] + check_keys(trigger_keys, ev_payload['trigger']) + +def get_event_of_query(hge_ctx, q): + st_code, resp = hge_ctx.v1q(q) + assert st_code == 200, resp + return hge_ctx.get_event(3) + +def validate_event_payload(ev_payload, trig_name, table): + check_ev_payload_shape(ev_payload) + assert ev_payload['table'] == table, ev_payload + assert ev_payload['trigger']['name'] == trig_name, ev_payload + + return ev_payload['event'] + +def check_insert(hge_ctx, trig_name, table, row, exp_ev_data): + query = { + "type": "insert", + "args": { + "table": table, + "objects": [row] + } + } + + ev_payload = get_event_of_query(hge_ctx,query) + ev = validate_event_payload(ev_payload, trig_name, table) + + # insert specific assertions + assert ev['op'] == "INSERT", ev_payload + assert ev['data'] == exp_ev_data, ev_payload + +def check_update(hge_ctx, trig_name, table, old_row, where, set_exp, exp_ev_data): + query = { + "type": "update", + "args": { + "table": table, + "where": where, + "$set": set_exp + } + } + + ev_payload = get_event_of_query(hge_ctx,query) + ev = validate_event_payload(ev_payload, trig_name, table) + + # update specific assertions + assert ev['op'] == "UPDATE", ev_payload + assert ev['data'] == exp_ev_data, ev_payload + +def check_delete(hge_ctx, trig_name, table, where_exp, exp_ev_data): + query = { + "type": "delete", + "args": { + "table": table, + "where": where_exp + } + } + + ev_payload = get_event_of_query(hge_ctx,query) + ev = validate_event_payload(ev_payload, trig_name, table) + + assert ev['op'] == "DELETE", ev_payload + assert ev['data'] == exp_ev_data, ev_payload + +def check_query(hge_ctx, conf): + headers={} + if 'headers' in conf: + headers = conf['headers'] + code, resp = hge_ctx.anyq( conf['url'], conf['query'], headers) + assert code == conf['status'], resp + if 'response' in conf: + print ('response\n', yaml.dump(resp)) + print ('expected\n', yaml.dump(conf['response'])) + assert json_ordered(resp) == json_ordered(conf['response']) + +def check_query_f(hge_ctx, f): + with open(f) as c: + conf = yaml.load(c) + if isinstance(conf, list): + for sconf in conf: + check_query( hge_ctx, sconf) + else: + check_query( hge_ctx, conf ) + +def json_ordered(obj): + if isinstance(obj, dict): + return sorted((k, json_ordered(v)) for k, v in obj.items()) + if isinstance(obj, list): + return list(json_ordered(x) for x in obj) + else: + return obj