{-# OPTIONS_GHC -Wno-deprecations #-}

{- HLINT ignore -}

-- | GENERATED BY 'server/tests-py/PortToHaskell.py'.
-- Please avoid editing this file manually.
module Test.PortedFromPytest.TestGraphQLQueryFunctions (spec) where

import Data.Aeson qualified as J
import Data.List.NonEmpty qualified as NE
import Harness.Backend.Postgres qualified as Postgres
import Harness.GraphqlEngine qualified as GraphqlEngine
import Harness.PytestPortedCompat (compatSetup)
import Harness.Quoter.Graphql (graphql)
import Harness.Quoter.Yaml
import Harness.Test.Fixture qualified as Fixture
import Harness.TestEnvironment (GlobalTestEnvironment, TestEnvironment (..))
import Harness.Yaml (shouldReturnYaml)
import Hasura.Prelude
import Test.Hspec hiding (shouldBe)

-- original file: queries/graphql_query/functions/setup.yaml
setup_Postgres :: J.Value
setup_Postgres =
  [interpolateYaml|
    type: bulk
    args:

    #Article table

    - type: run_sql
      args:
        sql: |
          create table post (
            id serial PRIMARY KEY,
            title TEXT,
            content TEXT
          );
          create function search_posts(search text)
          returns setof post as $$
              select *
              from post
              where
              title ilike ('%' || search || '%') or
              content ilike ('%' || search || '%')
          $$ language sql stable;
          insert into post (title, content)
          values
          ('post by hasura', 'content for post'),
          ('post by another', 'content for another post');
          create table test(
            id serial primary key,
            name text not null,
            uuid_col uuid not null
          );

          insert into test (name, uuid_col) values
           ('clarke', '8e3e4a14-c831-45a2-9e78-8e86028d1ee5')
          ,('michael', '8e3e4a14-c831-45a2-9e78-8e86028d1ee5')
          ,('fitch', '8e3e4a14-c831-45a2-9e78-8e86028d1ee6') ;

          create function get_test(uuid_arg uuid, name_arg text)
          returns setof test as $$
          select * from test where uuid_col = uuid_arg and name = name_arg
          $$ language sql stable;

          create function get_test_session_id(hasura_session json)
          returns test as $$
          select * from test where id = (hasura_session ->> 'x-hasura-user-id')::Int
          $$ language sql stable;
          CREATE TABLE integer_column
          (
            result integer
          );

          CREATE FUNCTION my_add (first integer, second integer DEFAULT 10)
          RETURNS SETOF integer_column as $$
            SELECT q.* FROM (VALUES (first + second)) as q
          $$ LANGUAGE SQL STABLE;
           CREATE TABLE "user" (
             id SERIAL PRIMARY KEY,
             name TEXT NOT NULL,
             is_admin BOOLEAN DEFAULT FALSE
           );
           INSERT INTO "user" (name, is_admin) VALUES
             ('Starke Blake', true)
           , ('Bellamy Blake', true)
           , ('Dora Blake', true)
           ;
          CREATE FUNCTION get_users(search text, integer default 10, boolean default false)
          RETURNS SETOF "user" AS $$
              SELECT *
              FROM "user"
              WHERE
                name ilike ('%' || search || '%')
                AND is_admin = $3
              LIMIT $2
          $$ LANGUAGE sql STABLE;
          CREATE TABLE text_result(
            result text
          );

          CREATE FUNCTION get_session_var(hasura_session json, session_var text)
          RETURNS SETOF text_result AS $$
              SELECT q.* FROM (VALUES (hasura_session ->> session_var)) q
          $$ LANGUAGE sql STABLE;
          CREATE TABLE author(
            id SERIAL PRIMARY KEY,
            first_name TEXT,
            last_name TEXT
          );

          INSERT INTO author(first_name, last_name) VALUES
            ('enid', 'blyton'),
            ('ruskin', 'bond'),
            ('franz', 'kafka');

          CREATE MATERIALIZED VIEW author_mat_view AS
            SELECT * FROM author;

          CREATE FUNCTION search_author_mview(query text)
          RETURNS SETOF author_mat_view AS $FUNCTION$
              SELECT * FROM author_mat_view WHERE
                first_name = query OR
                last_name = query
          $FUNCTION$ LANGUAGE sql STABLE;

    - type: track_table
      args:
        schema: public
        name: post

    #Search post function
    - type: track_function
      args:
        name: search_posts
        schema: public

    #Insert values
    - type: track_table
      args:
        name: test
        schema: public


    - type: track_function
      args:
        name: get_test
        schema: public
    - type: track_function
      version: 2
      args:
        function:
          name: get_test_session_id
          schema: public
        configuration:
          session_argument: hasura_session

    # custom add sql function
    - type: track_table
      args:
        name: integer_column
        schema: public

    - type: track_function
      args:
        name: my_add
        schema: public

    # test functions having multiple defaults
    - type: track_table
      args:
        name: user
        schema: public

    - type: track_function
      args:
        name: get_users
        schema: public

    # V2 Functions
    - type: track_table
      args:
        name: text_result
        schema: public

    - type: track_function
      version: 2
      args:
        function:
          schema: public
          name: get_session_var
        configuration:
          session_argument: hasura_session

    # track & query functions that return SETOF materialized views
    - type: track_table
      args:
        name: author
        schema: public

    - type: track_table
      args:
        name: author_mat_view
        schema: public

    - type: track_function
      version: 2
      args:
        function:
          schema: public
          name: search_author_mview

  |]

fixture_Postgres :: Fixture.Fixture ()
fixture_Postgres =
  (Fixture.fixture $ Fixture.Backend Postgres.backendTypeMetadata)
    { Fixture.setupTeardown = \(testEnvironment, _) ->
        [ Fixture.SetupAction
            { Fixture.setupAction = do
                compatSetup testEnvironment Fixture.Postgres
                GraphqlEngine.postV1Query 200 testEnvironment setup_Postgres,
              Fixture.teardownAction = \_ -> return ()
            }
        ]
    }

spec :: SpecWith GlobalTestEnvironment
spec = Fixture.runSingleSetup (NE.fromList [fixture_Postgres]) tests

tests :: SpecWith TestEnvironment
tests = do
  describe "test_search_posts" do
    -- from: queries/graphql_query/functions/query_search_posts.yaml [0]
    it "Custom GraphQL query using search_posts function" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                search_posts:
                - title: post by hasura
                  content: content for post

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  search_posts(
                    args: {search: "hasura"}
                  ) {
                    title
                    content
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/query_search_posts.yaml [1]
    it "...and make sure this didn't somehow end up under the mutation root" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              errors:
              - extensions:
                  path: $.selectionSet.search_posts
                  code: validation-failed
                message: "field 'search_posts' not found in type: 'mutation_root'"

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                mutation {
                  search_posts(
                    args: {search: "hasura"}
                  ) {
                    title
                    content
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/query_search_posts_aggregate.yaml
    it "Custom GraphQL aggregate query using search_posts function" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                search_posts_aggregate:
                  aggregate:
                    count: 2

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  search_posts_aggregate(
                    args: {search: "post"}
                  ) {
                    aggregate{
                      count
                    }
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/query_get_users.yaml
    it "Query from users table using get_users function" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                get_users:
                - id: 1
                  name: Starke Blake
                  is_admin: true
                - id: 2
                  name: Bellamy Blake
                  is_admin: true

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  get_users(args: {search: "Blake", arg_1: 2, arg_2: true}){
                    id
                    name
                    is_admin
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/query_get_users_arguments_error.yaml
    it "Query from users table using get_users function" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              errors:
              - extensions:
                  path: $.selectionSet.get_users.args.args
                  code: not-supported
                message: Only last set of positional arguments can be omitted

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  get_users(args: {search: "Blake", arg_2: true}){
                    id
                    name
                    is_admin
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/query_get_users_default_arguments_error.yaml
    it "Query from users table using get_users function" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              errors:
              - extensions:
                  path: $.selectionSet.get_users.args.args
                  code: not-supported
                message: Non default arguments cannot be omitted

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  get_users(args: {arg_2: true}) {
                    id
                    name
                    is_admin
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/alter_function_error.yaml
    it "Alter SQL function to type VOLATILE (error)" \testEnvironment -> do
      let actual :: IO J.Value
          actual =
            GraphqlEngine.postV1Query
              400
              testEnvironment
              [interpolateYaml|
                type: run_sql
                args:
                  sql: |
                    create or replace function search_posts(search text)
                    returns setof post as $$
                        insert into post (title, content) values (search, search)
                        returning *
                    $$ language sql volatile;

              |]

      void actual

    -- from: queries/graphql_query/functions/overloading_function_error.yaml
    it "Create a new SQL function with same name (error)" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              path: $.args
              error: 'the following tracked function(s) cannot be overloaded: search_posts'
              code: not-supported

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postV1Query
              400
              testEnvironment
              [interpolateYaml|
                type: run_sql
                args:
                  sql: |
                    create function search_posts(search text, id integer)
                    returns setof post as $$
                        select *
                        from post
                        where
                        title ilike ('%' || search || '%') or
                        content ilike ('%' || search || '%') or
                        id = id
                    $$ language sql stable;

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/query_get_test_uuid.yaml
    it "Query using get_test function" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                get_test:
                - id: 1
                  uuid_col: 8e3e4a14-c831-45a2-9e78-8e86028d1ee5
                  name: clarke

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  get_test(
                  args: { uuid_arg: "8e3e4a14-c831-45a2-9e78-8e86028d1ee5"
                        , name_arg: "clarke"
                        }
                 ) {
                    id
                    uuid_col
                    name
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/query_my_add.yaml
    it "Run queries on SQL my_add function with null input values" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                my_add:
                - result: 5
                my_add_null:
                - result:
                my_add_default:
                - result: 12

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  my_add(
                    args: {first: 2 second: 3}
                  ){
                    result
                  }
                  # input null value
                  my_add_null: my_add(
                    args: {first: null second: 2}
                  ){
                    result
                  }
                  # omiting 'second' parameter to consider
                  # it's default value in postgres
                  my_add_default: my_add(
                    args: {first: 2}
                  ){
                    result
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/query_get_session_var.yaml
    it "Query get_session_var custom SQL function" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                get_session_var:
                - result: test value

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphqlWithHeaders
              testEnvironment
              ( ("X-Hasura-Test", "test value")
                  : ("X-Hasura-Role", "admin")
                  : []
              )
              [graphql|
                query a {
                  get_session_var(
                    args: {session_var: "x-hasura-test"}
                  ){
                    result
                  }
                }

                  |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_function_v2_errors.yaml [0]
    it "setup a custom SQL function" \testEnvironment -> do
      let actual :: IO J.Value
          actual =
            GraphqlEngine.postV1Query
              200
              testEnvironment
              [interpolateYaml|
                type: run_sql
                args:
                  sql: |
                    CREATE FUNCTION get_session_var_value(hasura_session json, session_var text)
                    RETURNS SETOF text_result AS $$
                        SELECT q.* FROM (VALUES (hasura_session ->> session_var)) q
                    $$ LANGUAGE sql STABLE;


              |]

      void actual

    -- from: queries/graphql_query/functions/track_function_v2_errors.yaml [1]
    it "Track function v2 with invalid session argument" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              internal:
              - definition:
                  schema: public
                  name: get_session_var_value
                reason: 'Inconsistent object: in function "get_session_var_value": the function
                  "get_session_var_value" cannot be tracked because given session argument "random"
                  not the input argument of the function'
                name: function get_session_var_value in source default
                type: function
              path: $.args
              error: 'Inconsistent object: in function "get_session_var_value": the function "get_session_var_value"
                cannot be tracked because given session argument "random" not the input argument
                of the function'
              code: invalid-configuration

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postV1Query
              400
              testEnvironment
              [interpolateYaml|
                version: 2
                type: track_function
                args:
                  function: get_session_var_value
                  configuration:
                    session_argument: random


              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_function_v2_errors.yaml [2]
    it "Track function v2 with non json session argument" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              internal:
              - definition:
                  schema: public
                  name: get_session_var_value
                reason: 'Inconsistent object: in function "get_session_var_value": the function
                  "get_session_var_value" cannot be tracked because given session argument "session_var"
                  is not of type json'
                name: function get_session_var_value in source default
                type: function
              path: $.args
              error: 'Inconsistent object: in function "get_session_var_value": the function "get_session_var_value"
                cannot be tracked because given session argument "session_var" is not of type json'
              code: invalid-configuration

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postV1Query
              400
              testEnvironment
              [interpolateYaml|
                version: 2
                type: track_function
                args:
                  function: get_session_var_value
                  configuration:
                    session_argument: session_var


              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_function_v2_errors.yaml [3]
    it "teardown function" \testEnvironment -> do
      let actual :: IO J.Value
          actual =
            GraphqlEngine.postV1Query
              200
              testEnvironment
              [interpolateYaml|
                type: run_sql
                args:
                  sql: |
                    DROP FUNCTION get_session_var_value(json, text);
                  cascade: true

              |]

      void actual

    -- from: queries/graphql_query/functions/query_get_test_session_id.yaml
    it "Query get_test_session_id custom SQL function" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                get_test_session_id:
                  id: 1
                  name: clarke

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphqlWithHeaders
              testEnvironment
              ( ("X-Hasura-Role", "admin")
                  : ("X-Hasura-User-Id", "1")
                  : []
              )
              [graphql|
                query {
                  get_test_session_id{
                    id
                    name
                  }
                }

                  |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/query_search_author_mview.yaml
    it "Custom GraphQL query using search_author_mview function which returns results from a materialized view" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                search_author_mview:
                - first_name: franz
                  last_name: kafka

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  search_author_mview(
                    args: {query: "kafka"}
                  ) {
                    first_name
                    last_name
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_non_base_function_arg_type.yaml [0]
    it "setup a custom SQL function" \testEnvironment -> do
      let actual :: IO J.Value
          actual =
            GraphqlEngine.postV1Query
              200
              testEnvironment
              [interpolateYaml|
                type: run_sql
                args:
                  sql: |
                    create function search_post_by_test(t test)
                    returns setof post as $$
                        select *
                        from post
                        where
                        title ilike ('%' || t.name || '%')
                        $$ language sql stable;


              |]

      void actual

    -- from: queries/graphql_query/functions/track_non_base_function_arg_type.yaml [1]
    it "Track function v2 with invalid session argument" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              message: success

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postV1Query
              200
              testEnvironment
              [interpolateYaml|
                version: 2
                type: track_function
                args:
                  function: search_post_by_test


              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_non_base_function_arg_type.yaml [2]
    it "Introspect the new composite table scalar type created" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                __type:
                  kind: SCALAR

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  __type (name: "test_scalar") {
                    kind
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_non_base_function_arg_type.yaml [3]
    it "Execute the tracked function with a composite row type argument" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                search_post_by_test:
                - title: post by hasura
                  content: content for post

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  search_post_by_test (args: {t: "(1, hasura,311cf381-71e7-449b-bac5-86cd6deafd5b)"}) {
                    title
                    content
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [0]
    it "Define the SQL function the tests will be using" \testEnvironment -> do
      let actual :: IO J.Value
          actual =
            GraphqlEngine.postV2Query
              200
              testEnvironment
              [interpolateYaml|
                type: run_sql
                args:
                  sql: |
                    create function unaliased_function(t test)
                    returns setof post as $$
                        select *
                        from post
                        where
                        title ilike ('%' || t.name || '%')
                        $$ language sql stable;

                # Test: We can supply (all) aliases via `pg_track_function`, and the names are applied.


              |]

      void actual

    -- from: queries/graphql_query/functions/track_customised_names.yaml [1]
    it "Test that we supply all custom names to `pg_track_function`." \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              message: success

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postMetadataWithStatus
              200
              testEnvironment
              [interpolateYaml|
                type: pg_track_function
                args:
                  function: unaliased_function
                  configuration:
                    custom_root_fields:
                      function: nameBase
                      function_aggregate: nameAggregate


              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [2]
    it "Execute the function without the alias, which should fail" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              errors:
              - message: "field 'unaliased_function' not found in type: 'query_root'"
                extensions:
                  code: validation-failed
                  path: $.selectionSet.unaliased_function


            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  unaliased_function (args: {t: "(1, hasura,311cf381-71e7-449b-bac5-86cd6deafd5b)"}) {
                    title
                    content
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [3]
    it "Execute the function by its alias, which should succeed" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                nameBase:
                - title: post by hasura
                  content: content for post


            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  nameBase (args: {t: "(1, hasura,311cf381-71e7-449b-bac5-86cd6deafd5b)"}) {
                    title
                    content
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [4]
    it "Execute the function with aggregation by its aggregation-alias, which should succeed" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                nameAggregate:
                  aggregate:
                    count: 1


            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  nameAggregate (args: {t: "(1, hasura,311cf381-71e7-449b-bac5-86cd6deafd5b)"}) {
                    aggregate {
                      count
                    }
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [5]
    it "Teardown the test of fully given aliases" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              message: success

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postMetadataWithStatus
              200
              testEnvironment
              [interpolateYaml|
                type: pg_untrack_function
                args:
                  name: unaliased_function

                # Test: We can supply just the base alias via `pg_track_function`, and the names are applied.


              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [6]
    it "Test that we supply all custom names to `pg_track_function`." \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              message: success

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postMetadataWithStatus
              200
              testEnvironment
              [interpolateYaml|
                type: pg_track_function
                args:
                  function: unaliased_function
                  configuration:
                    custom_name: aliased


              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [7]
    it "Execute the function without the alias, which should fail" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              errors:
              - message: "field 'unaliased_function' not found in type: 'query_root'"
                extensions:
                  code: validation-failed
                  path: $.selectionSet.unaliased_function


            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  unaliased_function (args: {t: "(1, hasura,311cf381-71e7-449b-bac5-86cd6deafd5b)"}) {
                    title
                    content
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [8]
    it "Execute the function by its alias, which should succeed" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                aliased:
                - title: post by hasura
                  content: content for post


            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  aliased (args: {t: "(1, hasura,311cf381-71e7-449b-bac5-86cd6deafd5b)"}) {
                    title
                    content
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [9]
    it "Execute the function with aggregation by its aggregation-alias, which should succeed" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                aliased_aggregate:
                  aggregate:
                    count: 1

              # Test: Using set_function_customization


            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  aliased_aggregate (args: {t: "(1, hasura,311cf381-71e7-449b-bac5-86cd6deafd5b)"}) {
                    aggregate {
                      count
                    }
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [10]
    it "Test that we fail on non-existing functions" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              code: not-exists
              error: 'function "non_existing_function" does not exist in source: default'
              path: $.args

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postMetadataWithStatus
              400
              testEnvironment
              [interpolateYaml|
                type: pg_set_function_customization
                args:
                  function: non_existing_function
                  configuration: {}

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [11]
    it "Test that we fail on duplicate custom root fields" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              code: parse-failed
              error: "Error when parsing command set_function_customization.\nSee our documentation\
                \ at https://hasura.io/docs/latest/graphql/core/api-reference/metadata-api/index.html#metadata-apis.\n\
                Internal error message: the following custom root field names are duplicated: \"\
                duplicate_name\" and \"duplicate_name\""
              path: $.args.configuration.custom_root_fields

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postMetadataWithStatus
              400
              testEnvironment
              [interpolateYaml|
                type: pg_set_function_customization
                args:
                  function: unaliased_function
                  configuration:
                    custom_root_fields:
                      function: duplicate_name
                      function_aggregate: duplicate_name


              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [12]
    it "Test that we can clear the customized names" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              message: success

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postMetadataWithStatus
              200
              testEnvironment
              [interpolateYaml|
                type: pg_set_function_customization
                args:
                  function: unaliased_function
                  configuration: {}

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [13]
    it "None" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                unaliased_function:
                - title: post by hasura
                  content: content for post


            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  unaliased_function (args: {t: "(1, hasura,311cf381-71e7-449b-bac5-86cd6deafd5b)"}) {
                    title
                    content
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [14]
    it "Test that we can set customized names using `set_function_customization`" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              message: success

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postMetadataWithStatus
              200
              testEnvironment
              [interpolateYaml|
                type: pg_set_function_customization
                args:
                  function: unaliased_function
                  configuration:
                    custom_root_fields:
                      function: nameBaseOther


              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [15]
    it "Execute the function by its alias" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                nameBaseOther:
                - title: post by hasura
                  content: content for post


            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  nameBaseOther (args: {t: "(1, hasura,311cf381-71e7-449b-bac5-86cd6deafd5b)"}) {
                    title
                    content
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [16]
    it "Execute the function with aggregation (unaliased), which should succeed." \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              data:
                unaliased_function_aggregate:
                  aggregate:
                    count: 1

              # Test: We reject name clashes: A function is aliased to an existing (unaliased) function.
              # Note: We are not going to go to great lengths to ensure all the different
              # conceivable ways collisions could be introduced are avoided, because there is
              # a general mechanism in the code that builds the schema cache which ensures no
              # collisions appear in the final, generated schema.
              # (issue https://github.com/hasura/graphql-engine-mono/issues/1868 has a bit
              # more info on this subject)


            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postGraphql
              testEnvironment
              [graphql|
                query {
                  unaliased_function_aggregate (args: {t: "(1, hasura,311cf381-71e7-449b-bac5-86cd6deafd5b)"}) {
                    aggregate {
                      count
                    }
                  }
                }

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [17]
    it "Setup: Define a separate function to cause clashes" \testEnvironment -> do
      let actual :: IO J.Value
          actual =
            GraphqlEngine.postV2Query
              200
              testEnvironment
              [interpolateYaml|
                type: run_sql
                args:
                  sql: |
                    create function unaliased_function2(t test)
                    returns setof post as $$
                        select *
                        from post
                        where
                        title ilike ('%' || t.name || '%')
                        $$ language sql stable;


              |]

      void actual

    -- from: queries/graphql_query/functions/track_customised_names.yaml [18]
    it "Setup: Track the new function" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              message: success

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postMetadataWithStatus
              200
              testEnvironment
              [interpolateYaml|
                type: pg_track_function
                args:
                  function: unaliased_function2


              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [19]
    it "Setup: clear up aliases of unaliased_function" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              message: success

            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postMetadataWithStatus
              200
              testEnvironment
              [interpolateYaml|
                type: pg_set_function_customization
                args:
                  function: unaliased_function
                  configuration: {}

              |]

      shouldReturnYaml testEnvironment actual expected

    -- from: queries/graphql_query/functions/track_customised_names.yaml [20]
    it "Test that we cannot alias `unaliased_function2` to `unaliased_function`" \testEnvironment -> do
      let expected :: J.Value
          expected =
            [interpolateYaml|
              code: unexpected
              error: >-
                Encountered conflicting definitions in the selection set for 'subscription_root' for fields: ['unaliased_function_aggregate', 'unaliased_function']. Fields must not be defined more than once across all sources.
              path: $.args


            |]

      let actual :: IO J.Value
          actual =
            GraphqlEngine.postMetadataWithStatus
              500
              testEnvironment
              [interpolateYaml|
                type: pg_set_function_customization
                args:
                  function: unaliased_function2
                  configuration:
                    custom_name: unaliased_function

              |]

      shouldReturnYaml testEnvironment actual expected
