From 268ab00ed9cbbd986a0d9d3b4ae5edcc7af24413 Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Sat, 30 May 2026 17:25:09 +0200 Subject: [PATCH] test(spec): inline config into test suite Previously, information about each test-suite was repeated in 3 separate places: - as a label and as implicit knowledge in the test-suite itself, - as a comment in Main.hs, and - as a configuration in SpecHelper.hs. With this change, there will be a single source of truth in the test suite itself. This will allow a single test-suite to easily test multiple different configurations. --- test/spec/Feature/Auth/AsymmetricJwtSpec.hs | 38 +++- .../Feature/Auth/AudienceJwtSecretSpec.hs | 18 +- test/spec/Feature/Auth/AuthSpec.hs | 6 +- test/spec/Feature/Auth/BinaryJwtSecretSpec.hs | 13 +- test/spec/Feature/Auth/NoAnonSpec.hs | 8 +- test/spec/Feature/Auth/NoJwtSecretSpec.hs | 13 +- test/spec/Feature/ConcurrentSpec.hs | 8 +- test/spec/Feature/CorsSpec.hs | 7 +- test/spec/Feature/ExtraSearchPathSpec.hs | 7 +- test/spec/Feature/NoSuperuserSpec.hs | 7 +- test/spec/Feature/ObservabilitySpec.hs | 11 +- .../Feature/OpenApi/DisabledOpenApiSpec.hs | 10 +- .../Feature/OpenApi/IgnorePrivOpenApiSpec.hs | 13 +- test/spec/Feature/OpenApi/OpenApiSpec.hs | 5 +- test/spec/Feature/OpenApi/ProxySpec.hs | 9 +- test/spec/Feature/OpenApi/RootSpec.hs | 11 +- .../Feature/OpenApi/SecurityOpenApiSpec.hs | 10 +- test/spec/Feature/OptionsSpec.hs | 5 +- .../Feature/Query/AggregateFunctionsSpec.hs | 12 +- test/spec/Feature/Query/AndOrParamsSpec.hs | 6 +- test/spec/Feature/Query/ComputedRelsSpec.hs | 6 +- test/spec/Feature/Query/CustomMediaSpec.hs | 6 +- test/spec/Feature/Query/DeleteSpec.hs | 6 +- .../Feature/Query/EmbedDisambiguationSpec.hs | 6 +- test/spec/Feature/Query/EmbedInnerJoinSpec.hs | 5 +- test/spec/Feature/Query/ErrorSpec.hs | 6 +- test/spec/Feature/Query/InsertSpec.hs | 5 +- test/spec/Feature/Query/JsonOperatorSpec.hs | 6 +- test/spec/Feature/Query/MultipleSchemaSpec.hs | 10 +- test/spec/Feature/Query/NullsStripSpec.hs | 6 +- test/spec/Feature/Query/PgSafeUpdateSpec.hs | 16 +- test/spec/Feature/Query/PlanSpec.hs | 11 +- test/spec/Feature/Query/PostGISSpec.hs | 8 +- .../Feature/Query/Preferences/HandlingSpec.hs | 6 +- .../Query/Preferences/MaxAffectedSpec.hs | 10 +- .../Feature/Query/Preferences/TimezoneSpec.hs | 13 +- test/spec/Feature/Query/QueryLimitedSpec.hs | 8 +- test/spec/Feature/Query/QuerySpec.hs | 5 +- test/spec/Feature/Query/RangeSpec.hs | 5 +- test/spec/Feature/Query/RawOutputTypesSpec.hs | 8 +- test/spec/Feature/Query/RelatedQueriesSpec.hs | 6 +- test/spec/Feature/Query/RpcSpec.hs | 5 +- test/spec/Feature/Query/ServerTimingSpec.hs | 8 +- test/spec/Feature/Query/SingularSpec.hs | 5 +- test/spec/Feature/Query/SpreadQueriesSpec.hs | 6 +- test/spec/Feature/Query/UnicodeSpec.hs | 9 +- test/spec/Feature/Query/UpdateSpec.hs | 7 +- test/spec/Feature/Query/UpsertSpec.hs | 6 +- test/spec/Feature/RollbackSpec.hs | 26 ++- test/spec/Feature/RpcPreRequestGucsSpec.hs | 9 +- test/spec/Main.hs | 164 ++++-------------- test/spec/SpecHelper.hs | 99 +---------- 52 files changed, 280 insertions(+), 439 deletions(-) diff --git a/test/spec/Feature/Auth/AsymmetricJwtSpec.hs b/test/spec/Feature/Auth/AsymmetricJwtSpec.hs index 692f81585..0728e11a4 100644 --- a/test/spec/Feature/Auth/AsymmetricJwtSpec.hs +++ b/test/spec/Feature/Auth/AsymmetricJwtSpec.hs @@ -1,19 +1,39 @@ module Feature.Auth.AsymmetricJwtSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai +import Text.Heredoc + +import PostgREST.Config (AppConfig (..), parseSecret) import Protolude import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "server started with asymmetric JWK" $ +-- these tests will stop working 9999999999s after the UNIX EPOCH +spec :: SpecWithConfig +spec withConfig = + let + auth = authHeaderJWT "eyJhbGciOiJSUzI1NiJ9.eyJyb2xlIjogInBvc3RncmVzdF90ZXN0X2F1dGhvciJ9Cg.CBOYWDvqgAR0YYnZnyDGTQi6AJLc2Pds6_eV3YuBG6I36mj_h05eLhkEKNEDA5ZteMzCiY83P60rC_xtxVd7B6vo3BeF5uoanPS3rrbuHzKPwzsrgrD_CqvEuJ4n7Q9epkQiLsNkcexneENZDRqFjbwZx3DrXiCWwlK3Ytr5NAIGxmy0od-0xNpb2U1nXQyO_Q3mumWFViRt4tmFn_3goDHNKG3Ha_AzImfUNvHnWL78kAc4rbn15vLtWXD8PwtSnZaB4lY4V6RfsaW937srQsmRetvytM1i_bHBnjkjQLAqGbXPyItjtlXPs0uGNBadE8-wgkLtfmSCC4v2DjUthw" + jwk = encodeUtf8 [str|{"alg":"RS256","e":"AQAB","key_ops":["verify"],"kty":"RSA","n":"0etQ2Tg187jb04MWfpuogYGV75IFrQQBxQaGH75eq_FpbkyoLcEpRUEWSbECP2eeFya2yZ9vIO5ScD-lPmovePk4Aa4SzZ8jdjhmAbNykleRPCxMg0481kz6PQhnHRUv3nF5WP479CnObJKqTVdEagVL66oxnX9VhZG9IZA7k0Th5PfKQwrKGyUeTGczpOjaPqbxlunP73j9AfnAt4XCS8epa-n3WGz1j-wfpr_ys57Aq-zBCfqP67UYzNpeI1AoXsJhD9xSDOzvJgFRvc3vm2wjAW4LEMwi48rCplamOpZToIHEPIaPzpveYQwDnB1HFTR1ove9bpKJsHmi-e2uzQ","use":"sig"}|] + jwks = encodeUtf8 [str|{"keys": [{"alg":"RS256","e":"AQAB","key_ops":["verify"],"kty":"RSA","n":"0etQ2Tg187jb04MWfpuogYGV75IFrQQBxQaGH75eq_FpbkyoLcEpRUEWSbECP2eeFya2yZ9vIO5ScD-lPmovePk4Aa4SzZ8jdjhmAbNykleRPCxMg0481kz6PQhnHRUv3nF5WP479CnObJKqTVdEagVL66oxnX9VhZG9IZA7k0Th5PfKQwrKGyUeTGczpOjaPqbxlunP73j9AfnAt4XCS8epa-n3WGz1j-wfpr_ys57Aq-zBCfqP67UYzNpeI1AoXsJhD9xSDOzvJgFRvc3vm2wjAW4LEMwi48rCplamOpZToIHEPIaPzpveYQwDnB1HFTR1ove9bpKJsHmi-e2uzQ","use":"sig"}]}|] + in + describe "server started with asymmetric JWK" $ do - -- this test will stop working 9999999999s after the UNIX EPOCH - it "succeeds with jwt token signed with an asymmetric key" $ do - let auth = authHeaderJWT "eyJhbGciOiJSUzI1NiJ9.eyJyb2xlIjogInBvc3RncmVzdF90ZXN0X2F1dGhvciJ9Cg.CBOYWDvqgAR0YYnZnyDGTQi6AJLc2Pds6_eV3YuBG6I36mj_h05eLhkEKNEDA5ZteMzCiY83P60rC_xtxVd7B6vo3BeF5uoanPS3rrbuHzKPwzsrgrD_CqvEuJ4n7Q9epkQiLsNkcexneENZDRqFjbwZx3DrXiCWwlK3Ytr5NAIGxmy0od-0xNpb2U1nXQyO_Q3mumWFViRt4tmFn_3goDHNKG3Ha_AzImfUNvHnWL78kAc4rbn15vLtWXD8PwtSnZaB4lY4V6RfsaW937srQsmRetvytM1i_bHBnjkjQLAqGbXPyItjtlXPs0uGNBadE8-wgkLtfmSCC4v2DjUthw" - request methodGet "/authors_only" [auth] "" - `shouldRespondWith` 200 + context "secret provided as JWK" $ withConfig ( + baseCfg { + configJwtSecret = Just jwk + , configJWKS = rightToMaybe $ parseSecret jwk + } + ) $ it "succeeds with jwt token signed with an asymmetric key" $ + request methodGet "/authors_only" [auth] "" + `shouldRespondWith` 200 + + context "secret provided as JWKSet" $ withConfig ( + baseCfg { + configJwtSecret = Just jwks + , configJWKS = rightToMaybe $ parseSecret jwks + } + ) $ it "succeeds with jwt token signed with an asymmetric key" $ + request methodGet "/authors_only" [auth] "" + `shouldRespondWith` 200 diff --git a/test/spec/Feature/Auth/AudienceJwtSecretSpec.hs b/test/spec/Feature/Auth/AudienceJwtSecretSpec.hs index d4ad2968a..5891c306b 100644 --- a/test/spec/Feature/Auth/AudienceJwtSecretSpec.hs +++ b/test/spec/Feature/Auth/AudienceJwtSecretSpec.hs @@ -1,7 +1,5 @@ module Feature.Auth.AudienceJwtSecretSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Protolude hiding (get) import SpecHelper @@ -9,8 +7,16 @@ import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON -spec :: SpecWith ((), Application) -spec = describe "test handling of aud claims in JWT when the jwt-aud config is set" $ do +import PostgREST.Config (AppConfig (..), parseSecret) + +spec :: SpecWithConfig +spec withConfig = withConfig ( + baseCfg { + configJwtSecret = Just generateSecret + , configJwtAudience = Just "youraudience" + , configJWKS = rightToMaybe $ parseSecret generateSecret + } + ) $ describe "test handling of aud claims in JWT when the jwt-aud config is set" $ do context "when the audience claim is a string" $ do -- this test will stop working 9999999999s after the UNIX EPOCH @@ -147,8 +153,8 @@ spec = describe "test handling of aud claims in JWT when the jwt-aud config is s it "succeeds without a JWT" $ get "/has_count_column" `shouldRespondWith` 200 -disabledSpec :: SpecWith ((), Application) -disabledSpec = describe "test handling of aud claims in JWT when the jwt-aud config is not set" $ do +disabledSpec :: SpecWithConfig +disabledSpec withConfig = withConfig baseCfg $ describe "test handling of aud claims in JWT when the jwt-aud config is not set" $ do context "when the audience claim is a string" $ do it "ignores the audience claim and suceeds" $ do diff --git a/test/spec/Feature/Auth/AuthSpec.hs b/test/spec/Feature/Auth/AuthSpec.hs index 5538c83ad..a834ef496 100644 --- a/test/spec/Feature/Auth/AuthSpec.hs +++ b/test/spec/Feature/Auth/AuthSpec.hs @@ -1,7 +1,5 @@ module Feature.Auth.AuthSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai @@ -10,8 +8,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "authorization" $ do +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "authorization" $ do let single = ("Accept","application/vnd.pgrst.object+json") it "denies access to tables that anonymous does not own" $ diff --git a/test/spec/Feature/Auth/BinaryJwtSecretSpec.hs b/test/spec/Feature/Auth/BinaryJwtSecretSpec.hs index e7a303587..bb35b0f3f 100644 --- a/test/spec/Feature/Auth/BinaryJwtSecretSpec.hs +++ b/test/spec/Feature/Auth/BinaryJwtSecretSpec.hs @@ -1,16 +1,21 @@ module Feature.Auth.BinaryJwtSecretSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai +import PostgREST.Config (AppConfig (..), parseSecret) + import Protolude import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "server started with binary JWT secret" $ +spec :: SpecWithConfig +spec withConfig = withConfig ( + baseCfg { + configJwtSecret = Just generateSecret + , configJWKS = rightToMaybe $ parseSecret generateSecret + } + ) $ describe "server started with binary JWT secret" $ -- this test will stop working 9999999999s after the UNIX EPOCH it "succeeds with jwt token encoded with a binary secret" $ do diff --git a/test/spec/Feature/Auth/NoAnonSpec.hs b/test/spec/Feature/Auth/NoAnonSpec.hs index e3049fc32..17a111e9e 100644 --- a/test/spec/Feature/Auth/NoAnonSpec.hs +++ b/test/spec/Feature/Auth/NoAnonSpec.hs @@ -1,17 +1,17 @@ module Feature.Auth.NoAnonSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON +import PostgREST.Config (AppConfig (..)) + import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "server started without anonymous role" $ do +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configDbAnonRole = Nothing }) $ describe "server started without anonymous role" $ do it "behaves normally on attempted auth" $ do -- token body: { "role": "postgrest_test_author" } let auth = authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIn0.Xod-F15qsGL0WhdOCr2j3DdKuTw9QJERVgoFD3vGaWA" diff --git a/test/spec/Feature/Auth/NoJwtSecretSpec.hs b/test/spec/Feature/Auth/NoJwtSecretSpec.hs index cafd95564..880136e62 100644 --- a/test/spec/Feature/Auth/NoJwtSecretSpec.hs +++ b/test/spec/Feature/Auth/NoJwtSecretSpec.hs @@ -1,17 +1,22 @@ module Feature.Auth.NoJwtSecretSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON +import PostgREST.Config (AppConfig (..)) + import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "server started without JWT secret" $ do +spec :: SpecWithConfig +spec withConfig = withConfig ( + baseCfg { + configJwtSecret = Nothing + , configJWKS = Nothing + } + ) $ describe "server started without JWT secret" $ do it "responds with error on attempted auth" $ do -- token body: { "role": "postgrest_test_author" } diff --git a/test/spec/Feature/ConcurrentSpec.hs b/test/spec/Feature/ConcurrentSpec.hs index bced6160b..b8fcc446a 100644 --- a/test/spec/Feature/ConcurrentSpec.hs +++ b/test/spec/Feature/ConcurrentSpec.hs @@ -5,7 +5,6 @@ module Feature.ConcurrentSpec where import Control.Concurrent.Async (mapConcurrently) -import Network.Wai (Application) import Control.Monad.Base import Control.Monad.Trans.Control @@ -16,10 +15,11 @@ import Test.Hspec.Wai import Test.Hspec.Wai.Internal import Test.Hspec.Wai.JSON -import Protolude hiding (get) +import Protolude hiding (get) +import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "Querying in parallel" $ it "should not raise 'transaction in progress' error" $ raceTest 10 $ diff --git a/test/spec/Feature/CorsSpec.hs b/test/spec/Feature/CorsSpec.hs index 977c8df36..27e00b8a3 100644 --- a/test/spec/Feature/CorsSpec.hs +++ b/test/spec/Feature/CorsSpec.hs @@ -1,15 +1,14 @@ module Feature.CorsSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai import Protolude +import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "CORS" $ do it "replies naively and permissively to preflight request" $ request methodOptions "/" diff --git a/test/spec/Feature/ExtraSearchPathSpec.hs b/test/spec/Feature/ExtraSearchPathSpec.hs index 1ed7e4f58..b71a94bd5 100644 --- a/test/spec/Feature/ExtraSearchPathSpec.hs +++ b/test/spec/Feature/ExtraSearchPathSpec.hs @@ -1,16 +1,17 @@ module Feature.ExtraSearchPathSpec where import Network.HTTP.Types -import Network.Wai (Application) import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON +import PostgREST.Config (AppConfig (..)) + import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "extra search path" $ do +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configDbExtraSearchPath = ["public", "extensions", "EXTRA \"@/\\#~_-"] }) $ describe "extra search path" $ do it "finds the ltree <@ operator on the public schema" $ request methodGet "/ltree_sample?path=cd.Top.Science.Astronomy" [] "" diff --git a/test/spec/Feature/NoSuperuserSpec.hs b/test/spec/Feature/NoSuperuserSpec.hs index 857386437..555c9210a 100644 --- a/test/spec/Feature/NoSuperuserSpec.hs +++ b/test/spec/Feature/NoSuperuserSpec.hs @@ -1,15 +1,14 @@ module Feature.NoSuperuserSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai import Protolude +import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "No Superuser" $ do it "proves that the authenticator role is not a superuser" $ do request methodGet "/rpc/is_superuser" diff --git a/test/spec/Feature/ObservabilitySpec.hs b/test/spec/Feature/ObservabilitySpec.hs index b6a59bb47..b173ced5e 100644 --- a/test/spec/Feature/ObservabilitySpec.hs +++ b/test/spec/Feature/ObservabilitySpec.hs @@ -1,15 +1,18 @@ module Feature.ObservabilitySpec where -import Network.Wai (Application) +import Data.CaseInsensitive (mk) import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai -import Protolude +import PostgREST.Config (AppConfig (..)) -spec :: SpecWith ((), Application) -spec = +import Protolude +import SpecHelper + +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configServerTraceHeader = Just $ mk "X-Request-Id" }) $ describe "Observability" $ do it "includes the server trace header on the response" $ do request methodHead "/" diff --git a/test/spec/Feature/OpenApi/DisabledOpenApiSpec.hs b/test/spec/Feature/OpenApi/DisabledOpenApiSpec.hs index ce322da07..75bc30ed6 100644 --- a/test/spec/Feature/OpenApi/DisabledOpenApiSpec.hs +++ b/test/spec/Feature/OpenApi/DisabledOpenApiSpec.hs @@ -1,16 +1,18 @@ module Feature.OpenApi.DisabledOpenApiSpec where import Network.HTTP.Types -import Network.Wai (Application) import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON -import Protolude +import PostgREST.Config (AppConfig (..), OpenAPIMode (..)) -spec :: SpecWith ((), Application) -spec = +import Protolude +import SpecHelper + +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configOpenApiMode = OADisabled }) $ describe "Disabled OpenApi" $ do it "responds with 404" $ request methodGet "/" diff --git a/test/spec/Feature/OpenApi/IgnorePrivOpenApiSpec.hs b/test/spec/Feature/OpenApi/IgnorePrivOpenApiSpec.hs index 00310b187..ffbf1aff4 100644 --- a/test/spec/Feature/OpenApi/IgnorePrivOpenApiSpec.hs +++ b/test/spec/Feature/OpenApi/IgnorePrivOpenApiSpec.hs @@ -4,19 +4,26 @@ import Control.Lens ((^?)) import Data.Aeson.Lens import Data.Aeson.QQ +import Data.List.NonEmpty (fromList) import Network.HTTP.Types -import Network.Wai (Application) import Network.Wai.Test (SResponse (..)) import Test.Hspec hiding (pendingWith) import Test.Hspec.Wai +import PostgREST.Config (AppConfig (..), OpenAPIMode (..)) + import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "OpenAPI Ignore Privileges" $ do +spec :: SpecWithConfig +spec withConfig = withConfig ( + baseCfg { + configOpenApiMode = OAIgnorePriv + , configDbSchemas = fromList ["test", "v1"] + } + ) $ describe "OpenAPI Ignore Privileges" $ do it "root path returns a valid openapi spec" $ do validateOpenApiResponse [("Accept", "application/openapi+json")] request methodHead "/" diff --git a/test/spec/Feature/OpenApi/OpenApiSpec.hs b/test/spec/Feature/OpenApi/OpenApiSpec.hs index 57ed910b7..cd98090e1 100644 --- a/test/spec/Feature/OpenApi/OpenApiSpec.hs +++ b/test/spec/Feature/OpenApi/OpenApiSpec.hs @@ -2,7 +2,6 @@ module Feature.OpenApi.OpenApiSpec where import Control.Lens ((^?)) import Data.Aeson.Types (Value (..)) -import Network.Wai (Application) import Network.Wai.Test (SResponse (..)) import Data.Aeson.Lens @@ -15,8 +14,8 @@ import PostgREST.Version (docsVersion) import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "OpenAPI" $ do +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "OpenAPI" $ do it "root path returns a valid openapi spec" $ do validateOpenApiResponse [("Accept", "application/openapi+json")] request methodHead "/" diff --git a/test/spec/Feature/OpenApi/ProxySpec.hs b/test/spec/Feature/OpenApi/ProxySpec.hs index 57405a7da..7dc09d38b 100644 --- a/test/spec/Feature/OpenApi/ProxySpec.hs +++ b/test/spec/Feature/OpenApi/ProxySpec.hs @@ -1,13 +1,14 @@ module Feature.OpenApi.ProxySpec where -import Network.Wai (Application) -import Test.Hspec hiding (pendingWith) +import Test.Hspec hiding (pendingWith) + +import PostgREST.Config (AppConfig (..)) import Protolude import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configOpenApiServerProxyUri = Just "https://postgrest.com/openapi.json" }) $ describe "GET / with proxy" $ it "returns a valid openapi spec with proxy" $ validateOpenApiResponse [("Accept", "application/openapi+json")] diff --git a/test/spec/Feature/OpenApi/RootSpec.hs b/test/spec/Feature/OpenApi/RootSpec.hs index cd8e06dce..5391ebffc 100644 --- a/test/spec/Feature/OpenApi/RootSpec.hs +++ b/test/spec/Feature/OpenApi/RootSpec.hs @@ -1,16 +1,19 @@ module Feature.OpenApi.RootSpec where import Network.HTTP.Types -import Network.Wai (Application) import Test.Hspec hiding (pendingWith) import Test.Hspec.Wai import Test.Hspec.Wai.JSON -import Protolude hiding (get) +import PostgREST.Config (AppConfig (..)) +import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..)) -spec :: SpecWith ((), Application) -spec = +import Protolude hiding (get) +import SpecHelper + +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configDbRootSpec = Just $ QualifiedIdentifier mempty "root" }) $ describe "root spec function" $ do it "accepts application/openapi+json" $ do request methodGet "/" diff --git a/test/spec/Feature/OpenApi/SecurityOpenApiSpec.hs b/test/spec/Feature/OpenApi/SecurityOpenApiSpec.hs index 1332be058..9483e9c68 100644 --- a/test/spec/Feature/OpenApi/SecurityOpenApiSpec.hs +++ b/test/spec/Feature/OpenApi/SecurityOpenApiSpec.hs @@ -5,16 +5,18 @@ import Control.Lens ((^?)) import Data.Aeson.Lens import Data.Aeson.QQ -import Network.Wai (Application) import Network.Wai.Test (SResponse (..)) import Test.Hspec hiding (pendingWith) import Test.Hspec.Wai -import Protolude hiding (get) +import PostgREST.Config (AppConfig (..)) -spec :: SpecWith ((), Application) -spec = +import Protolude hiding (get) +import SpecHelper + +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configOpenApiSecurityActive = True }) $ describe "Security active" $ it "includes security and security definitions" $ do r <- simpleBody <$> get "/" diff --git a/test/spec/Feature/OptionsSpec.hs b/test/spec/Feature/OptionsSpec.hs index 44e898fdd..3f68716c3 100644 --- a/test/spec/Feature/OptionsSpec.hs +++ b/test/spec/Feature/OptionsSpec.hs @@ -1,6 +1,5 @@ module Feature.OptionsSpec where -import Network.Wai (Application) import Network.Wai.Test (SResponse (..)) import Network.HTTP.Types @@ -10,8 +9,8 @@ import Test.Hspec.Wai import Protolude import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "Allow header" $ do +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "Allow header" $ do context "a table" $ do it "includes read/write methods for writeable table" $ do r <- request methodOptions "/items" [] "" diff --git a/test/spec/Feature/Query/AggregateFunctionsSpec.hs b/test/spec/Feature/Query/AggregateFunctionsSpec.hs index e0d67bb42..7dc6cbede 100644 --- a/test/spec/Feature/Query/AggregateFunctionsSpec.hs +++ b/test/spec/Feature/Query/AggregateFunctionsSpec.hs @@ -1,16 +1,16 @@ module Feature.Query.AggregateFunctionsSpec where -import Network.Wai (Application) - import Test.Hspec hiding (pendingWith) import Test.Hspec.Wai import Test.Hspec.Wai.JSON +import PostgREST.Config (AppConfig (..)) + import Protolude hiding (get) import SpecHelper -allowed :: SpecWith ((), Application) -allowed = +allowed :: SpecWithConfig +allowed withConfig = withConfig (baseCfg { configDbAggregates = True }) $ describe "aggregate functions" $ do context "performing a count without specifying a field" $ do it "returns the count of all rows when no other fields are selected" $ @@ -306,8 +306,8 @@ allowed = { matchStatus = 400 , matchHeaders = [matchContentTypeJson] } -disallowed :: SpecWith ((), Application) -disallowed = +disallowed :: SpecWithConfig +disallowed withConfig = withConfig baseCfg $ describe "attempting to use an aggregate when aggregate functions are disallowed" $ do it "prevents the use of aggregates" $ get "/project_invoices?select=invoice_total.sum()" `shouldRespondWith` diff --git a/test/spec/Feature/Query/AndOrParamsSpec.hs b/test/spec/Feature/Query/AndOrParamsSpec.hs index faa344214..a57e7cbe0 100644 --- a/test/spec/Feature/Query/AndOrParamsSpec.hs +++ b/test/spec/Feature/Query/AndOrParamsSpec.hs @@ -1,7 +1,5 @@ module Feature.Query.AndOrParamsSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai @@ -10,8 +8,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "and/or params used for complex boolean logic" $ do context "used with GET" $ do context "or param" $ do diff --git a/test/spec/Feature/Query/ComputedRelsSpec.hs b/test/spec/Feature/Query/ComputedRelsSpec.hs index b2a9256ab..10c2b56f3 100644 --- a/test/spec/Feature/Query/ComputedRelsSpec.hs +++ b/test/spec/Feature/Query/ComputedRelsSpec.hs @@ -1,7 +1,5 @@ module Feature.Query.ComputedRelsSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai @@ -10,8 +8,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "computed relationships" $ do +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "computed relationships" $ do it "can define a many-to-one relationship with SETOF and ROWS 1 and embed" $ get "/videogames?select=name,designer:computed_designers(name)" `shouldRespondWith` diff --git a/test/spec/Feature/Query/CustomMediaSpec.hs b/test/spec/Feature/Query/CustomMediaSpec.hs index e20b6da67..bb1296440 100644 --- a/test/spec/Feature/Query/CustomMediaSpec.hs +++ b/test/spec/Feature/Query/CustomMediaSpec.hs @@ -1,7 +1,5 @@ module Feature.Query.CustomMediaSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Network.Wai.Test (SResponse (simpleBody, simpleHeaders, simpleStatus)) import Test.Hspec @@ -12,8 +10,8 @@ import Text.Heredoc (str) import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "custom media types" $ do +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "custom media types" $ do context "for tables with aggregate" $ do it "can query if there's an aggregate defined for the table" $ do r <- request methodGet "/lines" (acceptHdrs "application/vnd.twkb") "" diff --git a/test/spec/Feature/Query/DeleteSpec.hs b/test/spec/Feature/Query/DeleteSpec.hs index df76d7009..37bc284c2 100644 --- a/test/spec/Feature/Query/DeleteSpec.hs +++ b/test/spec/Feature/Query/DeleteSpec.hs @@ -1,7 +1,5 @@ module Feature.Query.DeleteSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec hiding (pendingWith) import Test.Hspec.Wai @@ -10,8 +8,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "Deleting" $ do context "existing record" $ do it "succeeds with 204 and deletion count" $ diff --git a/test/spec/Feature/Query/EmbedDisambiguationSpec.hs b/test/spec/Feature/Query/EmbedDisambiguationSpec.hs index 2f7193722..7b79483d9 100644 --- a/test/spec/Feature/Query/EmbedDisambiguationSpec.hs +++ b/test/spec/Feature/Query/EmbedDisambiguationSpec.hs @@ -1,7 +1,5 @@ module Feature.Query.EmbedDisambiguationSpec where -import Network.Wai (Application) - import Test.Hspec hiding (pendingWith) import Test.Hspec.Wai import Test.Hspec.Wai.JSON @@ -9,8 +7,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "resource embedding disambiguation" $ do context "ambiguous requests that give 300 Multiple Choices" $ do it "errs when there are o2m and m2m cardinalities to the target table" $ diff --git a/test/spec/Feature/Query/EmbedInnerJoinSpec.hs b/test/spec/Feature/Query/EmbedInnerJoinSpec.hs index 580bf5c37..3147a42ed 100644 --- a/test/spec/Feature/Query/EmbedInnerJoinSpec.hs +++ b/test/spec/Feature/Query/EmbedInnerJoinSpec.hs @@ -1,7 +1,6 @@ module Feature.Query.EmbedInnerJoinSpec where import Network.HTTP.Types -import Network.Wai (Application) import Test.Hspec import Test.Hspec.Wai @@ -10,8 +9,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "Embedding with an inner join" $ do context "many-to-one relationships" $ do it "ignores null embeddings while the default left join doesn't" $ do diff --git a/test/spec/Feature/Query/ErrorSpec.hs b/test/spec/Feature/Query/ErrorSpec.hs index 73f191a5a..890b19565 100644 --- a/test/spec/Feature/Query/ErrorSpec.hs +++ b/test/spec/Feature/Query/ErrorSpec.hs @@ -1,7 +1,5 @@ module Feature.Query.ErrorSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai @@ -10,8 +8,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -pgErrorCodeMapping :: SpecWith ((), Application) -pgErrorCodeMapping = do +pgErrorCodeMapping :: SpecWithConfig +pgErrorCodeMapping withConfig = withConfig baseCfg $ do describe "PostreSQL error code mappings" $ do it "should return 500 for cardinality_violation" $ get "/bad_subquery" `shouldRespondWith` 500 diff --git a/test/spec/Feature/Query/InsertSpec.hs b/test/spec/Feature/Query/InsertSpec.hs index be895e659..97ebe6774 100644 --- a/test/spec/Feature/Query/InsertSpec.hs +++ b/test/spec/Feature/Query/InsertSpec.hs @@ -1,7 +1,6 @@ module Feature.Query.InsertSpec where import Data.List (lookup) -import Network.Wai (Application) import Network.Wai.Test (SResponse (simpleHeaders)) import Test.Hspec hiding (pendingWith) import Test.Hspec.Wai.Matcher (bodyEquals) @@ -14,8 +13,8 @@ import Text.Heredoc import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = do +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ do describe "Posting new record" $ do context "disparate json types" $ do it "accepts disparate json types" $ do diff --git a/test/spec/Feature/Query/JsonOperatorSpec.hs b/test/spec/Feature/Query/JsonOperatorSpec.hs index 2443976de..afcde23c6 100644 --- a/test/spec/Feature/Query/JsonOperatorSpec.hs +++ b/test/spec/Feature/Query/JsonOperatorSpec.hs @@ -1,7 +1,5 @@ module Feature.Query.JsonOperatorSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai @@ -10,8 +8,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "json and jsonb operators" $ do +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "json and jsonb operators" $ do context "Shaping response with select parameter" $ do it "obtains a json subfield one level with casting" $ get "/complex_items?id=eq.1&select=settings->>foo::json" `shouldRespondWith` diff --git a/test/spec/Feature/Query/MultipleSchemaSpec.hs b/test/spec/Feature/Query/MultipleSchemaSpec.hs index 2f6d13880..3de964b4a 100644 --- a/test/spec/Feature/Query/MultipleSchemaSpec.hs +++ b/test/spec/Feature/Query/MultipleSchemaSpec.hs @@ -1,22 +1,24 @@ module Feature.Query.MultipleSchemaSpec where -import Control.Lens ((^?)) +import Control.Lens ((^?)) import Data.Aeson.Lens import Data.Aeson.QQ +import Data.List.NonEmpty (fromList) import Network.HTTP.Types -import Network.Wai (Application) import Network.Wai.Test (SResponse (simpleHeaders), simpleBody) import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON +import PostgREST.Config (AppConfig (..)) + import Protolude import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configDbSchemas = fromList ["v1", "v2", "SPECIAL \"@/\\#~_-"] }) $ describe "PostGIS features" $ describe "multiple schemas in single instance" $ do context "Reading tables on different schemas" $ do it "succeeds in reading table from default schema v1 if no schema is selected via header" $ diff --git a/test/spec/Feature/Query/NullsStripSpec.hs b/test/spec/Feature/Query/NullsStripSpec.hs index af562d2a2..c5d335359 100644 --- a/test/spec/Feature/Query/NullsStripSpec.hs +++ b/test/spec/Feature/Query/NullsStripSpec.hs @@ -1,7 +1,5 @@ module Feature.Query.NullsStripSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai @@ -10,8 +8,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "Stripping null values from JSON response" $ do let arrayStrip = ("Accept", "application/vnd.pgrst.array+json;nulls=stripped") let singularStrip = ("Accept", "application/vnd.pgrst.object+json;nulls=stripped") diff --git a/test/spec/Feature/Query/PgSafeUpdateSpec.hs b/test/spec/Feature/Query/PgSafeUpdateSpec.hs index 582ca8f39..b73b5c62a 100644 --- a/test/spec/Feature/Query/PgSafeUpdateSpec.hs +++ b/test/spec/Feature/Query/PgSafeUpdateSpec.hs @@ -1,16 +1,18 @@ module Feature.Query.PgSafeUpdateSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec hiding (pendingWith) import Test.Hspec.Wai import Test.Hspec.Wai.JSON -import Protolude hiding (get, put) +import PostgREST.Config (AppConfig (..)) +import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..)) -spec :: SpecWith ((), Application) -spec = +import Protolude hiding (get, put) +import SpecHelper + +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configDbPreRequest = Just $ QualifiedIdentifier "test" "load_safeupdate" }) $ describe "Enabling pg-safeupdate" $ do context "Full table update" $ do it "does not update and throws error if no condition is present" $ @@ -48,8 +50,8 @@ spec = `shouldRespondWith` 204 -disabledSpec :: SpecWith ((), Application) -disabledSpec = +disabledSpec :: SpecWithConfig +disabledSpec withConfig = withConfig baseCfg $ describe "Disabling pg-safeupdate" $ do context "Full table update" $ do it "works if no condition is present" $ diff --git a/test/spec/Feature/Query/PlanSpec.hs b/test/spec/Feature/Query/PlanSpec.hs index 880b76d4b..c2eb5bb77 100644 --- a/test/spec/Feature/Query/PlanSpec.hs +++ b/test/spec/Feature/Query/PlanSpec.hs @@ -3,7 +3,6 @@ module Feature.Query.PlanSpec where import Control.Lens ((^?)) -import Network.Wai (Application) import Network.Wai.Test (SResponse (..)) import Data.Aeson.Lens @@ -15,11 +14,13 @@ import Test.Hspec hiding (pendingWith) import Test.Hspec.Wai import Test.Hspec.Wai.JSON +import PostgREST.Config (AppConfig (..)) + import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = do +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configDbPlanEnabled = True }) $ do describe "read table/view plan" $ do it "outputs the total cost for a single filter on a table" $ do r <- request methodGet "/projects?id=in.(1,2,3)" @@ -529,8 +530,8 @@ spec = do totalCost `shouldSatisfy` (> 67.0) aggregateQty `shouldSatisfy` (> 1) -disabledSpec :: SpecWith ((), Application) -disabledSpec = +disabledSpec :: SpecWithConfig +disabledSpec withConfig = withConfig baseCfg $ it "doesn't work if db-plan-enabled=false(the default)" $ do request methodGet "/projects?id=in.(1,2,3)" (acceptHdrs "application/vnd.pgrst.plan") "" diff --git a/test/spec/Feature/Query/PostGISSpec.hs b/test/spec/Feature/Query/PostGISSpec.hs index c6c431a79..595244c91 100644 --- a/test/spec/Feature/Query/PostGISSpec.hs +++ b/test/spec/Feature/Query/PostGISSpec.hs @@ -1,17 +1,17 @@ module Feature.Query.PostGISSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON +import PostgREST.Config (AppConfig (..)) + import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "PostGIS features" $ +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configDbExtraSearchPath = ["public", "extensions", "EXTRA \"@/\\#~_-"] }) $ describe "PostGIS features" $ context "GeoJSON output" $ do it "works for a table that has a geometry column" $ request methodGet "/shops" diff --git a/test/spec/Feature/Query/Preferences/HandlingSpec.hs b/test/spec/Feature/Query/Preferences/HandlingSpec.hs index 23c095a14..539ec7aad 100644 --- a/test/spec/Feature/Query/Preferences/HandlingSpec.hs +++ b/test/spec/Feature/Query/Preferences/HandlingSpec.hs @@ -1,7 +1,5 @@ module Feature.Query.Preferences.HandlingSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai @@ -10,8 +8,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "test Prefer: handling" $ do context "check behaviour of Prefer: handling=strict" $ do it "throws error when handling=strict and invalid prefs are given" $ diff --git a/test/spec/Feature/Query/Preferences/MaxAffectedSpec.hs b/test/spec/Feature/Query/Preferences/MaxAffectedSpec.hs index 634fd805d..f6751dcf2 100644 --- a/test/spec/Feature/Query/Preferences/MaxAffectedSpec.hs +++ b/test/spec/Feature/Query/Preferences/MaxAffectedSpec.hs @@ -1,17 +1,15 @@ module Feature.Query.Preferences.MaxAffectedSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON -import Protolude hiding (get) +import Protolude hiding (get) +import SpecHelper -spec :: SpecWith ((), Application) -spec = - describe "test Prefer: max-affected" $ do +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "test Prefer: max-affected" $ do context "test Prefer: max-affected with handling=strict" $ do it "should fail if items deleted more than 10" $ request methodDelete "/items?id=lt.15" diff --git a/test/spec/Feature/Query/Preferences/TimezoneSpec.hs b/test/spec/Feature/Query/Preferences/TimezoneSpec.hs index 12603390a..c2063a94b 100644 --- a/test/spec/Feature/Query/Preferences/TimezoneSpec.hs +++ b/test/spec/Feature/Query/Preferences/TimezoneSpec.hs @@ -1,18 +1,17 @@ module Feature.Query.Preferences.TimezoneSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON +import PostgREST.Config (AppConfig (..)) + import Protolude hiding (get) import SpecHelper -enabledSpec :: SpecWith ((), Application) -enabledSpec = - describe "test Prefer: timezone with db-timezone-enabled is true" $ do +enabledSpec :: SpecWithConfig +enabledSpec withConfig = withConfig baseCfg $ describe "test Prefer: timezone with db-timezone-enabled is true" $ do context "test Prefer: timezone=America/Los_Angeles" $ do it "should change timezone with handling=strict" $ request methodGet "/timestamps" @@ -62,8 +61,8 @@ enabledSpec = , "Preference-Applied" <:> "handling=lenient"]} -disabledSpec :: SpecWith ((), Application) -disabledSpec = +disabledSpec :: SpecWithConfig +disabledSpec withConfig = withConfig (baseCfg { configDbTimezoneEnabled = False }) $ describe "test Prefer: timezone with db-timezone-enabled is false" $ do context "test Prefer: timezone=America/Los_Angeles when timezone is disabled" $ do it "should throw error with handling=strict" $ diff --git a/test/spec/Feature/Query/QueryLimitedSpec.hs b/test/spec/Feature/Query/QueryLimitedSpec.hs index 156767a15..1bc4b6c53 100644 --- a/test/spec/Feature/Query/QueryLimitedSpec.hs +++ b/test/spec/Feature/Query/QueryLimitedSpec.hs @@ -1,17 +1,17 @@ module Feature.Query.QueryLimitedSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON +import PostgREST.Config (AppConfig (..)) + import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configDbMaxRows = Just 2 }) $ describe "Requesting many items with server limits(max-rows) enabled" $ do it "restricts results" $ get "/items?order=id" diff --git a/test/spec/Feature/Query/QuerySpec.hs b/test/spec/Feature/Query/QuerySpec.hs index b35b60d80..ca433ceb5 100644 --- a/test/spec/Feature/Query/QuerySpec.hs +++ b/test/spec/Feature/Query/QuerySpec.hs @@ -1,6 +1,5 @@ module Feature.Query.QuerySpec where -import Network.Wai (Application) import Network.Wai.Test (SResponse (simpleHeaders)) import Network.HTTP.Types @@ -11,8 +10,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = do +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ do describe "Querying a table with a column called count" $ it "should not confuse count column with pg_catalog.count aggregate" $ diff --git a/test/spec/Feature/Query/RangeSpec.hs b/test/spec/Feature/Query/RangeSpec.hs index 427c64f65..298ee6224 100644 --- a/test/spec/Feature/Query/RangeSpec.hs +++ b/test/spec/Feature/Query/RangeSpec.hs @@ -1,6 +1,5 @@ module Feature.Query.RangeSpec where -import Network.Wai (Application) import Network.Wai.Test (SResponse (simpleHeaders, simpleStatus)) import Network.HTTP.Types @@ -11,8 +10,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = do +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ do describe "GET /rpc/getitemrange" $ do context "without range headers" $ do context "with response under server size limit" $ diff --git a/test/spec/Feature/Query/RawOutputTypesSpec.hs b/test/spec/Feature/Query/RawOutputTypesSpec.hs index b76df7813..0111a761e 100644 --- a/test/spec/Feature/Query/RawOutputTypesSpec.hs +++ b/test/spec/Feature/Query/RawOutputTypesSpec.hs @@ -1,17 +1,15 @@ module Feature.Query.RawOutputTypesSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON import Protolude -import SpecHelper (acceptHdrs) +import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "When raw-media-types config variable is missing or left empty" $ do +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "When raw-media-types config variable is missing or left empty" $ do let firefoxAcceptHdrs = acceptHdrs "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" chromeAcceptHdrs = acceptHdrs "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3" it "responds json to a GET request with Firefox Accept headers" $ diff --git a/test/spec/Feature/Query/RelatedQueriesSpec.hs b/test/spec/Feature/Query/RelatedQueriesSpec.hs index c5a7d4e56..5bd5fe06f 100644 --- a/test/spec/Feature/Query/RelatedQueriesSpec.hs +++ b/test/spec/Feature/Query/RelatedQueriesSpec.hs @@ -1,7 +1,5 @@ module Feature.Query.RelatedQueriesSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai @@ -10,8 +8,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = describe "related queries" $ do +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "related queries" $ do context "related orders" $ do it "works on a many-to-one relationship" $ do get "/projects?select=id,clients(name)&order=clients(name).nullsfirst" `shouldRespondWith` diff --git a/test/spec/Feature/Query/RpcSpec.hs b/test/spec/Feature/Query/RpcSpec.hs index 63e1733af..121fe5f72 100644 --- a/test/spec/Feature/Query/RpcSpec.hs +++ b/test/spec/Feature/Query/RpcSpec.hs @@ -2,7 +2,6 @@ module Feature.Query.RpcSpec where import qualified Data.ByteString.Lazy as BL (empty) -import Network.Wai (Application) import Network.Wai.Test (SResponse (simpleBody, simpleHeaders, simpleStatus)) import Network.HTTP.Types @@ -16,8 +15,8 @@ import PostgREST.Config.PgVersion (PgVersion, pgVersion180) import Protolude hiding (get) import SpecHelper -spec :: PgVersion -> SpecWith ((), Application) -spec actualPgVersion = +spec :: PgVersion -> SpecWithConfig +spec actualPgVersion withConfig = withConfig baseCfg $ describe "remote procedure call" $ do context "a proc that returns a set" $ do context "returns paginated results" $ do diff --git a/test/spec/Feature/Query/ServerTimingSpec.hs b/test/spec/Feature/Query/ServerTimingSpec.hs index 11cf29948..914d7316a 100644 --- a/test/spec/Feature/Query/ServerTimingSpec.hs +++ b/test/spec/Feature/Query/ServerTimingSpec.hs @@ -1,17 +1,17 @@ module Feature.Query.ServerTimingSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON +import PostgREST.Config (AppConfig (..)) + import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configDbPlanEnabled = True }) $ describe "Show Duration on Server-Timing header" $ do context "responds with Server-Timing header" $ do diff --git a/test/spec/Feature/Query/SingularSpec.hs b/test/spec/Feature/Query/SingularSpec.hs index 86c58a33d..25010dbfb 100644 --- a/test/spec/Feature/Query/SingularSpec.hs +++ b/test/spec/Feature/Query/SingularSpec.hs @@ -1,6 +1,5 @@ module Feature.Query.SingularSpec where -import Network.Wai (Application) import Network.Wai.Test (SResponse (..)) import Network.HTTP.Types @@ -11,8 +10,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "Requesting singular json object" $ do let singular = ("Accept", "application/vnd.pgrst.object+json") diff --git a/test/spec/Feature/Query/SpreadQueriesSpec.hs b/test/spec/Feature/Query/SpreadQueriesSpec.hs index f3e0de85e..4382a4f62 100644 --- a/test/spec/Feature/Query/SpreadQueriesSpec.hs +++ b/test/spec/Feature/Query/SpreadQueriesSpec.hs @@ -1,7 +1,5 @@ module Feature.Query.SpreadQueriesSpec where -import Network.Wai (Application) - import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON @@ -9,8 +7,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "spread embeds" $ do it "works on a many-to-one relationship" $ do get "/projects?select=id,...clients(client_name:name)" `shouldRespondWith` diff --git a/test/spec/Feature/Query/UnicodeSpec.hs b/test/spec/Feature/Query/UnicodeSpec.hs index f6cff6f82..216f9866e 100644 --- a/test/spec/Feature/Query/UnicodeSpec.hs +++ b/test/spec/Feature/Query/UnicodeSpec.hs @@ -1,17 +1,18 @@ module Feature.Query.UnicodeSpec where -import Network.Wai (Application) - +import Data.List.NonEmpty (fromList) import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON +import PostgREST.Config (AppConfig (..)) + import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configDbSchemas = fromList ["تست"] }) $ describe "Reading and writing to unicode schema and table names" $ it "Can read and write values" $ do get "/%D9%85%D9%88%D8%A7%D8%B1%D8%AF" diff --git a/test/spec/Feature/Query/UpdateSpec.hs b/test/spec/Feature/Query/UpdateSpec.hs index 44e7c0c79..2873354f8 100644 --- a/test/spec/Feature/Query/UpdateSpec.hs +++ b/test/spec/Feature/Query/UpdateSpec.hs @@ -1,7 +1,6 @@ module Feature.Query.UpdateSpec where -import Network.Wai (Application) -import Test.Hspec hiding (pendingWith) +import Test.Hspec hiding (pendingWith) import Network.HTTP.Types import Test.Hspec.Wai @@ -10,8 +9,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get) import SpecHelper -spec :: SpecWith ((), Application) -spec = do +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ do describe "Patching record" $ do context "to unknown uri" $ it "indicates no table found by returning 404" $ diff --git a/test/spec/Feature/Query/UpsertSpec.hs b/test/spec/Feature/Query/UpsertSpec.hs index f5cbaff6f..f5c9c8f4e 100644 --- a/test/spec/Feature/Query/UpsertSpec.hs +++ b/test/spec/Feature/Query/UpsertSpec.hs @@ -3,8 +3,6 @@ -- - Upsert/IgnoreDuplicates.hs module Feature.Query.UpsertSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai @@ -13,8 +11,8 @@ import Test.Hspec.Wai.JSON import Protolude hiding (get, put) import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig baseCfg $ describe "UPSERT" $ do context "with POST" $ do context "when Prefer: resolution=merge-duplicates is specified" $ do diff --git a/test/spec/Feature/RollbackSpec.hs b/test/spec/Feature/RollbackSpec.hs index b1f77d327..7ca680153 100644 --- a/test/spec/Feature/RollbackSpec.hs +++ b/test/spec/Feature/RollbackSpec.hs @@ -1,12 +1,12 @@ module Feature.RollbackSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai import Test.Hspec.Wai.JSON +import PostgREST.Config (AppConfig (..)) + import Protolude hiding (get) import SpecHelper @@ -211,8 +211,8 @@ shouldNotPersistMutations reqHeaders respHeaders = do `shouldRespondWith` [json|[{"id":1}]|] -allowed :: SpecWith ((), Application) -allowed = describe "tx-allow-override = true" $ do +allowed :: SpecWithConfig +allowed withConfig = withConfig baseCfg $ describe "tx-allow-override = true" $ do describe "without Prefer tx" $ do preferDefault `shouldRespondToReads` withoutPreferenceApplied preferDefault `shouldNotPersistMutations` withoutPreferenceApplied @@ -232,8 +232,13 @@ allowed = describe "tx-allow-override = true" $ do -- because they return before the end of the transaction. preferRollback `shouldRaiseExceptions` withoutPreferenceApplied -disallowed :: SpecWith ((), Application) -disallowed = describe "tx-rollback-all = false, tx-allow-override = false" $ do +disallowed :: SpecWithConfig +disallowed withConfig = withConfig ( + baseCfg { + configDbTxAllowOverride = False + , configDbTxRollbackAll = False + } + ) $ describe "tx-rollback-all = false, tx-allow-override = false" $ do describe "without Prefer tx" $ do preferDefault `shouldRespondToReads` withoutPreferenceApplied preferDefault `shouldPersistMutations` withoutPreferenceApplied @@ -250,8 +255,13 @@ disallowed = describe "tx-rollback-all = false, tx-allow-override = false" $ do preferRollback `shouldRaiseExceptions` withoutPreferenceApplied -forced :: SpecWith ((), Application) -forced = describe "tx-rollback-all = true, tx-allow-override = false" $ do +forced :: SpecWithConfig +forced withConfig = withConfig ( + baseCfg { + configDbTxAllowOverride = False + , configDbTxRollbackAll = True + } + ) $ describe "tx-rollback-all = true, tx-allow-override = false" $ do describe "without Prefer tx" $ do preferDefault `shouldRespondToReads` withoutPreferenceApplied preferDefault `shouldNotPersistMutations` withoutPreferenceApplied diff --git a/test/spec/Feature/RpcPreRequestGucsSpec.hs b/test/spec/Feature/RpcPreRequestGucsSpec.hs index d013d6015..2caa9c50c 100644 --- a/test/spec/Feature/RpcPreRequestGucsSpec.hs +++ b/test/spec/Feature/RpcPreRequestGucsSpec.hs @@ -1,17 +1,18 @@ module Feature.RpcPreRequestGucsSpec where -import Network.Wai (Application) - import Network.HTTP.Types import Test.Hspec hiding (pendingWith) import Test.Hspec.Wai import Test.Hspec.Wai.JSON +import PostgREST.Config (AppConfig (..)) +import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..)) + import Protolude hiding (get, put) import SpecHelper -spec :: SpecWith ((), Application) -spec = +spec :: SpecWithConfig +spec withConfig = withConfig (baseCfg { configDbPreRequest = Just $ QualifiedIdentifier mempty "custom_headers" }) $ describe "GUC headers on all methods via pre-request" $ do it "succeeds setting the headers on POST" $ post "/items" diff --git a/test/spec/Main.hs b/test/spec/Main.hs index 34c8edde4..435f1d640 100644 --- a/test/spec/Main.hs +++ b/test/spec/Main.hs @@ -79,15 +79,15 @@ main = do , P.acquisitionTimeout 10 , P.agingTimeout 60 , P.idlenessTimeout 60 - , P.staticConnectionSettings $ toConnectionSettings identity testCfg + , P.staticConnectionSettings $ toConnectionSettings identity baseCfg ] actualPgVersion <- either (panic . show) id <$> P.use pool queryPgVersion -- cached schema cache so most tests run fast - baseSchemaCache <- loadSCache pool testCfg + baseSchemaCache <- loadSCache pool baseCfg loggerState <- Logger.init - metricsState <- Metrics.init (configDbPoolSize testCfg) + metricsState <- Metrics.init (configDbPoolSize baseCfg) let initApp sCache config = do @@ -104,42 +104,29 @@ main = do customSchemaCache <- loadSCache pool config initApp customSchemaCache config - let withApp = app testCfg - maxRowsApp = app testMaxRowsCfg - disabledOpenApi = app testDisabledOpenApiCfg - securityOpenApi = app testSecurityOpenApiCfg - proxyApp = app testProxyCfg - noAnonApp = app testCfgNoAnon - noJwtSecretApp = app testCfgNoJwtSecret - binaryJwtApp = app testCfgBinaryJWT - audJwtApp = app testCfgAudienceJWT - asymJwkApp = app testCfgAsymJWK - asymJwkSetApp = app testCfgAsymJWKSet - rootSpecApp = app testCfgRootSpec - responseHeadersApp = app testCfgResponseHeaders - disallowRollbackApp = app testCfgDisallowRollback - forceRollbackApp = app testCfgForceRollback - planEnabledApp = app testPlanEnabledCfg - pgSafeUpdateApp = app testPgSafeUpdateEnabledCfg - obsApp = app testObservabilityCfg - serverTiming = app testCfgServerTiming - aggregatesEnabled = app testCfgAggregatesEnabled + withConfig config = before (app config) + withConfigDbs config = before (appDbs config) + describeWithConfig label spec = describe label $ spec withConfig - extraSearchPathApp = appDbs testCfgExtraSearchPath - unicodeApp = appDbs testUnicodeCfg - multipleSchemaApp = appDbs testMultipleSchemaCfg - ignorePrivOpenApi = appDbs testIgnorePrivOpenApiCfg - timezoneDisabled = appDbs testCfgTimezoneDisabled - - - let specs = uncurry describe <$> [ - ("Feature.Auth.AudienceJwtSecretSpec" , Feature.Auth.AudienceJwtSecretSpec.disabledSpec) + let specs = uncurry describeWithConfig <$> [ + ("Feature.Auth.AsymmetricJwtSpec" , Feature.Auth.AsymmetricJwtSpec.spec) + , ("Feature.Auth.AudienceJwtSecretSpec" , Feature.Auth.AudienceJwtSecretSpec.disabledSpec) + , ("Feature.Auth.AudienceJwtSecretSpec" , Feature.Auth.AudienceJwtSecretSpec.spec) , ("Feature.Auth.AuthSpec" , Feature.Auth.AuthSpec.spec) + , ("Feature.Auth.BinaryJwtSecretSpec" , Feature.Auth.BinaryJwtSecretSpec.spec) + , ("Feature.Auth.NoAnonSpec" , Feature.Auth.NoAnonSpec.spec) + , ("Feature.Auth.NoJwtSecretSpec" , Feature.Auth.NoJwtSecretSpec.spec) , ("Feature.ConcurrentSpec" , Feature.ConcurrentSpec.spec) , ("Feature.CorsSpec" , Feature.CorsSpec.spec) , ("Feature.NoSuperuserSpec" , Feature.NoSuperuserSpec.spec) + , ("Feature.ObservabilitySpec" , Feature.ObservabilitySpec.spec) + , ("Feature.OpenApi.DisabledOpenApiSpec" , Feature.OpenApi.DisabledOpenApiSpec.spec) , ("Feature.OpenApi.OpenApiSpec" , Feature.OpenApi.OpenApiSpec.spec) + , ("Feature.OpenApi.ProxySpec" , Feature.OpenApi.ProxySpec.spec) + , ("Feature.OpenApi.RootSpec" , Feature.OpenApi.RootSpec.spec) + , ("Feature.OpenApi.SecurityOpenApiSpec" , Feature.OpenApi.SecurityOpenApiSpec.spec) , ("Feature.OptionsSpec" , Feature.OptionsSpec.spec) + , ("Feature.Query.AggregateFunctionsSpec.allowed" , Feature.Query.AggregateFunctionsSpec.allowed) , ("Feature.Query.AggregateFunctionsSpec.disallowed" , Feature.Query.AggregateFunctionsSpec.disallowed) , ("Feature.Query.AndOrParamsSpec" , Feature.Query.AndOrParamsSpec.spec) , ("Feature.Query.ComputedRelsSpec" , Feature.Query.ComputedRelsSpec.spec) @@ -153,126 +140,43 @@ main = do , ("Feature.Query.NullsStripSpec" , Feature.Query.NullsStripSpec.spec) , ("Feature.Query.PgSafeUpdateSpec.disabledSpec" , Feature.Query.PgSafeUpdateSpec.disabledSpec) , ("Feature.Query.PlanSpec.disabledSpec" , Feature.Query.PlanSpec.disabledSpec) + , ("Feature.Query.PlanSpec.spec" , Feature.Query.PlanSpec.spec) , ("Feature.Query.Preferences.HandlingSpec" , Feature.Query.Preferences.HandlingSpec.spec) , ("Feature.Query.Preferences.MaxAffectedSpec" , Feature.Query.Preferences.MaxAffectedSpec.spec) , ("Feature.Query.Preferences.TimezoneSpec.enabledSpec", Feature.Query.Preferences.TimezoneSpec.enabledSpec) + , ("Feature.Query.QueryLimitedSpec" , Feature.Query.QueryLimitedSpec.spec) , ("Feature.Query.QuerySpec" , Feature.Query.QuerySpec.spec) , ("Feature.Query.RangeSpec" , Feature.Query.RangeSpec.spec) , ("Feature.Query.RawOutputTypesSpec" , Feature.Query.RawOutputTypesSpec.spec) , ("Feature.Query.RelatedQueriesSpec" , Feature.Query.RelatedQueriesSpec.spec) , ("Feature.Query.RpcSpec" , Feature.Query.RpcSpec.spec actualPgVersion) + , ("Feature.Query.ServerTimingSpec" , Feature.Query.ServerTimingSpec.spec) , ("Feature.Query.SingularSpec" , Feature.Query.SingularSpec.spec) , ("Feature.Query.SpreadQueriesSpec" , Feature.Query.SpreadQueriesSpec.spec) , ("Feature.Query.UpdateSpec" , Feature.Query.UpdateSpec.spec) , ("Feature.Query.UpsertSpec" , Feature.Query.UpsertSpec.spec) + , ("Feature.RpcPreRequestGucsSpec" , Feature.RpcPreRequestGucsSpec.spec) ] hspec $ do - mapM_ (parallel . before withApp) specs - - -- this test runs with a different server flag - parallel $ before maxRowsApp $ - describe "Feature.Query.QueryLimitedSpec" Feature.Query.QueryLimitedSpec.spec - - -- this test runs with a different schema - parallel $ before unicodeApp $ - describe "Feature.Query.UnicodeSpec" Feature.Query.UnicodeSpec.spec - - -- this test runs with openapi-mode set to disabled - parallel $ before disabledOpenApi $ - describe "Feature.DisabledOpenApiSpec" Feature.OpenApi.DisabledOpenApiSpec.spec - - -- this test runs with openapi-mode set to ignore-acl - parallel $ before ignorePrivOpenApi $ - describe "Feature.OpenApi.IgnorePrivOpenApiSpec" Feature.OpenApi.IgnorePrivOpenApiSpec.spec - - -- this test runs with a proxy - parallel $ before proxyApp $ - describe "Feature.OpenApi.ProxySpec" Feature.OpenApi.ProxySpec.spec - - -- this test runs with openapi-security-active set to true - parallel $ before securityOpenApi $ - describe "Feature.OpenApi.SecurityOpenApiSpec" Feature.OpenApi.SecurityOpenApiSpec.spec - - -- this test runs without an anonymous role - parallel $ before noAnonApp $ - describe "Feature.Auth.NoAnonSpec" Feature.Auth.NoAnonSpec.spec - - -- this test runs without a JWT secret - parallel $ before noJwtSecretApp $ - describe "Feature.Auth.NoJwtSecretSpec" Feature.Auth.NoJwtSecretSpec.spec - - -- this test runs with a binary JWT secret - parallel $ before binaryJwtApp $ - describe "Feature.Auth.BinaryJwtSecretSpec" Feature.Auth.BinaryJwtSecretSpec.spec - - -- this test runs with a binary JWT secret and an audience claim - parallel $ before audJwtApp $ - describe "Feature.Auth.AudienceJwtSecretSpec" Feature.Auth.AudienceJwtSecretSpec.spec - - -- this test runs with asymmetric JWK - parallel $ before asymJwkApp $ - describe "Feature.Auth.AsymmetricJwtSpec" Feature.Auth.AsymmetricJwtSpec.spec - - -- this test runs with asymmetric JWKSet - parallel $ before asymJwkSetApp $ - describe "Feature.Auth.AsymmetricJwtSpec" Feature.Auth.AsymmetricJwtSpec.spec - - -- this test runs with an extra search path - parallel $ before extraSearchPathApp $ do - describe "Feature.ExtraSearchPathSpec" Feature.ExtraSearchPathSpec.spec - describe "Feature.Query.PostGISSpec" Feature.Query.PostGISSpec.spec - - -- this test runs with a root spec function override - parallel $ before rootSpecApp $ - describe "Feature.OpenApi.RootSpec" Feature.OpenApi.RootSpec.spec - - -- this test runs with a pre request function override - parallel $ before responseHeadersApp $ - describe "Feature.RpcPreRequestGucsSpec" Feature.RpcPreRequestGucsSpec.spec - - -- this test runs with multiple schemas - parallel $ before multipleSchemaApp $ - describe "Feature.Query.MultipleSchemaSpec" Feature.Query.MultipleSchemaSpec.spec - - -- this test runs with db-plan-enabled = true - parallel $ before planEnabledApp $ - describe "Feature.Query.PlanSpec.spec" Feature.Query.PlanSpec.spec - - -- this test runs with server-trace-header set - parallel $ before obsApp $ - describe "Feature.ObservabilitySpec.spec" Feature.ObservabilitySpec.spec - - parallel $ before serverTiming $ - describe "Feature.Query.ServerTimingSpec.spec" Feature.Query.ServerTimingSpec.spec - - parallel $ before aggregatesEnabled $ - describe "Feature.Query.AggregateFunctionsSpec" Feature.Query.AggregateFunctionsSpec.allowed - - -- this test runs with db-timezone-enabled = false - parallel $ before timezoneDisabled $ - describe "Feature.Query.Preferences.TimezoneSpec.disabledSpec" Feature.Query.Preferences.TimezoneSpec.disabledSpec + mapM_ parallel specs + parallel $ describe "Feature.Query.UnicodeSpec" $ Feature.Query.UnicodeSpec.spec withConfigDbs + parallel $ describe "Feature.OpenApi.IgnorePrivOpenApiSpec" $ Feature.OpenApi.IgnorePrivOpenApiSpec.spec withConfigDbs + parallel $ describe "Feature.ExtraSearchPathSpec" $ Feature.ExtraSearchPathSpec.spec withConfigDbs + parallel $ describe "Feature.Query.PostGISSpec" $ Feature.Query.PostGISSpec.spec withConfigDbs + parallel $ describe "Feature.Query.MultipleSchemaSpec" $ Feature.Query.MultipleSchemaSpec.spec withConfigDbs + parallel $ describe "Feature.Query.Preferences.TimezoneSpec.disabledSpec" $ Feature.Query.Preferences.TimezoneSpec.disabledSpec withConfigDbs -- Note: the rollback tests can not run in parallel, because they test persistence and -- this results in race conditions - - -- this test runs with tx-rollback-all = true and tx-allow-override = true - before withApp $ - describe "Feature.RollbackAllowedSpec" Feature.RollbackSpec.allowed - - -- this test runs with tx-rollback-all = false and tx-allow-override = false - before disallowRollbackApp $ - describe "Feature.RollbackDisallowedSpec" Feature.RollbackSpec.disallowed - - -- this test runs with tx-rollback-all = true and tx-allow-override = false - before forceRollbackApp $ - describe "Feature.RollbackForcedSpec" Feature.RollbackSpec.forced + describe "Feature.RollbackAllowedSpec" $ Feature.RollbackSpec.allowed withConfig + describe "Feature.RollbackDisallowedSpec" $ Feature.RollbackSpec.disallowed withConfig + describe "Feature.RollbackForcedSpec" $ Feature.RollbackSpec.forced withConfig -- This test runs with a pre request to enable the pg-safeupdate library per-session. -- This needs to run last, because once pg safe update is loaded, it can't be unloaded again. - before pgSafeUpdateApp $ - describe "Feature.Query.PgSafeUpdateSpec.spec" Feature.Query.PgSafeUpdateSpec.spec + describe "Feature.Query.PgSafeUpdateSpec.spec" $ Feature.Query.PgSafeUpdateSpec.spec withConfig where loadSCache pool conf = diff --git a/test/spec/SpecHelper.hs b/test/spec/SpecHelper.hs index 73cb1b182..4e45a5a31 100644 --- a/test/spec/SpecHelper.hs +++ b/test/spec/SpecHelper.hs @@ -14,9 +14,10 @@ import qualified Jose.Jws as JWT import qualified Jose.Jwt as JWT import Data.Aeson ((.=)) -import Data.CaseInsensitive (CI (..), mk, original) +import Data.CaseInsensitive (CI (..), original) import Data.List (lookup) import Data.List.NonEmpty (fromList) +import Network.Wai (Application) import Network.Wai.Test (SResponse (simpleBody, simpleHeaders, simpleStatus)) import System.IO.Unsafe (unsafePerformIO) import Text.Regex.TDFA ((=~)) @@ -25,7 +26,6 @@ import Text.Regex.TDFA ((=~)) import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai -import Text.Heredoc import Data.String (String) import PostgREST.Config (AppConfig (..), @@ -106,6 +106,7 @@ validateOpenApiResponse headers = do , matchHeaders = [] } +type SpecWithConfig = (AppConfig -> SpecWith ((), Application) -> Spec) -> Spec baseCfg :: AppConfig baseCfg = let secret = encodeUtf8 "reallyreallyreallyreallyverysafe" in @@ -161,100 +162,6 @@ baseCfg = let secret = encodeUtf8 "reallyreallyreallyreallyverysafe" in , configServerTimingEnabled = True } -testCfg :: AppConfig -testCfg = baseCfg - -testCfgDisallowRollback :: AppConfig -testCfgDisallowRollback = baseCfg { configDbTxAllowOverride = False, configDbTxRollbackAll = False } - -testCfgForceRollback :: AppConfig -testCfgForceRollback = baseCfg { configDbTxAllowOverride = False, configDbTxRollbackAll = True } - -testCfgNoAnon :: AppConfig -testCfgNoAnon = baseCfg { configDbAnonRole = Nothing } - -testCfgNoJwtSecret :: AppConfig -testCfgNoJwtSecret = baseCfg { configJwtSecret = Nothing, configJWKS = Nothing } - -testUnicodeCfg :: AppConfig -testUnicodeCfg = baseCfg { configDbSchemas = fromList ["تست"] } - -testMaxRowsCfg :: AppConfig -testMaxRowsCfg = baseCfg { configDbMaxRows = Just 2 } - -testDisabledOpenApiCfg :: AppConfig -testDisabledOpenApiCfg = baseCfg { configOpenApiMode = OADisabled } - -testIgnorePrivOpenApiCfg :: AppConfig -testIgnorePrivOpenApiCfg = baseCfg { configOpenApiMode = OAIgnorePriv, configDbSchemas = fromList ["test", "v1"] } - -testProxyCfg :: AppConfig -testProxyCfg = baseCfg { configOpenApiServerProxyUri = Just "https://postgrest.com/openapi.json" } - -testSecurityOpenApiCfg :: AppConfig -testSecurityOpenApiCfg = baseCfg { configOpenApiSecurityActive = True } - -testPlanEnabledCfg :: AppConfig -testPlanEnabledCfg = baseCfg { configDbPlanEnabled = True } - -testCfgBinaryJWT :: AppConfig -testCfgBinaryJWT = - baseCfg { - configJwtSecret = Just generateSecret - , configJWKS = rightToMaybe $ parseSecret generateSecret - } - -testCfgAudienceJWT :: AppConfig -testCfgAudienceJWT = - baseCfg { - configJwtSecret = Just generateSecret - , configJwtAudience = Just "youraudience" - , configJWKS = rightToMaybe $ parseSecret generateSecret - } - -testCfgAsymJWK :: AppConfig -testCfgAsymJWK = - let secret = encodeUtf8 [str|{"alg":"RS256","e":"AQAB","key_ops":["verify"],"kty":"RSA","n":"0etQ2Tg187jb04MWfpuogYGV75IFrQQBxQaGH75eq_FpbkyoLcEpRUEWSbECP2eeFya2yZ9vIO5ScD-lPmovePk4Aa4SzZ8jdjhmAbNykleRPCxMg0481kz6PQhnHRUv3nF5WP479CnObJKqTVdEagVL66oxnX9VhZG9IZA7k0Th5PfKQwrKGyUeTGczpOjaPqbxlunP73j9AfnAt4XCS8epa-n3WGz1j-wfpr_ys57Aq-zBCfqP67UYzNpeI1AoXsJhD9xSDOzvJgFRvc3vm2wjAW4LEMwi48rCplamOpZToIHEPIaPzpveYQwDnB1HFTR1ove9bpKJsHmi-e2uzQ","use":"sig"}|] - in baseCfg { - configJwtSecret = Just secret - , configJWKS = rightToMaybe $ parseSecret secret - } - -testCfgAsymJWKSet :: AppConfig -testCfgAsymJWKSet = - let secret = encodeUtf8 [str|{"keys": [{"alg":"RS256","e":"AQAB","key_ops":["verify"],"kty":"RSA","n":"0etQ2Tg187jb04MWfpuogYGV75IFrQQBxQaGH75eq_FpbkyoLcEpRUEWSbECP2eeFya2yZ9vIO5ScD-lPmovePk4Aa4SzZ8jdjhmAbNykleRPCxMg0481kz6PQhnHRUv3nF5WP479CnObJKqTVdEagVL66oxnX9VhZG9IZA7k0Th5PfKQwrKGyUeTGczpOjaPqbxlunP73j9AfnAt4XCS8epa-n3WGz1j-wfpr_ys57Aq-zBCfqP67UYzNpeI1AoXsJhD9xSDOzvJgFRvc3vm2wjAW4LEMwi48rCplamOpZToIHEPIaPzpveYQwDnB1HFTR1ove9bpKJsHmi-e2uzQ","use":"sig"}]}|] - in baseCfg { - configJwtSecret = Just secret - , configJWKS = rightToMaybe $ parseSecret secret - } - -testCfgExtraSearchPath :: AppConfig -testCfgExtraSearchPath = baseCfg { configDbExtraSearchPath = ["public", "extensions", "EXTRA \"@/\\#~_-"] } - -testCfgRootSpec :: AppConfig -testCfgRootSpec = baseCfg { configDbRootSpec = Just $ QualifiedIdentifier mempty "root"} - -testCfgResponseHeaders :: AppConfig -testCfgResponseHeaders = baseCfg { configDbPreRequest = Just $ QualifiedIdentifier mempty "custom_headers" } - -testMultipleSchemaCfg :: AppConfig -testMultipleSchemaCfg = baseCfg { configDbSchemas = fromList ["v1", "v2", "SPECIAL \"@/\\#~_-"] } - -testPgSafeUpdateEnabledCfg :: AppConfig -testPgSafeUpdateEnabledCfg = baseCfg { configDbPreRequest = Just $ QualifiedIdentifier "test" "load_safeupdate" } - -testObservabilityCfg :: AppConfig -testObservabilityCfg = baseCfg { configServerTraceHeader = Just $ mk "X-Request-Id" } - -testCfgServerTiming :: AppConfig -testCfgServerTiming = baseCfg { configDbPlanEnabled = True } - -testCfgAggregatesEnabled :: AppConfig -testCfgAggregatesEnabled = baseCfg { configDbAggregates = True } - -testCfgTimezoneDisabled :: AppConfig -testCfgTimezoneDisabled = baseCfg { configDbTimezoneEnabled = False } - rangeHdrs :: ByteRange -> [Header] rangeHdrs r = [rangeUnit, (hRange, renderByteRange r)]