bloodhound-1.0.0.0: tests/Test/DocumentOptionsSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Test.DocumentOptionsSpec (spec) where
import Data.Aeson (Value (..), encode, object, (.=))
import Data.List (sort)
import Data.Text qualified as T
import Database.Bloodhound.Common.Types
import Test.Hspec (Spec, describe, it, shouldBe, shouldSatisfy)
-- | Stable ordering for equality. The renderers preserve field-declaration
-- order but tests should compare the set of params, not the order.
normalize :: [(T.Text, Maybe T.Text)] -> [(T.Text, Maybe T.Text)]
normalize = sort
-- | Boolean helpers rendered as @true@/@false@ strings.
boolTrue :: Maybe T.Text
boolTrue = Just "true"
boolFalse :: Maybe T.Text
boolFalse = Just "false"
spec :: Spec
spec = do
describe "GetDocumentOptions URI param rendering" $ do
it "defaultGetDocumentOptions emits no params" $
getDocumentOptionsParams defaultGetDocumentOptions
`shouldBe` []
describe "_source" $ do
it "Just True renders as _source=true" $ do
let opts = defaultGetDocumentOptions {gdoSource = Just True}
getDocumentOptionsParams opts `shouldBe` [("_source", boolTrue)]
it "Just False renders as _source=false" $ do
let opts = defaultGetDocumentOptions {gdoSource = Just False}
getDocumentOptionsParams opts `shouldBe` [("_source", boolFalse)]
it "_source_includes renders verbatim" $ do
let opts = defaultGetDocumentOptions {gdoSourceIncludes = Just "metadata.*,name"}
getDocumentOptionsParams opts
`shouldBe` [("_source_includes", Just "metadata.*,name")]
it "_source_excludes renders verbatim" $ do
let opts = defaultGetDocumentOptions {gdoSourceExcludes = Just "internal.*"}
getDocumentOptionsParams opts
`shouldBe` [("_source_excludes", Just "internal.*")]
it "stored_fields renders verbatim" $ do
let opts = defaultGetDocumentOptions {gdoStoredFields = Just "user,location"}
getDocumentOptionsParams opts
`shouldBe` [("stored_fields", Just "user,location")]
it "preference renders verbatim" $ do
let opts = defaultGetDocumentOptions {gdoPreference = Just "_local"}
getDocumentOptionsParams opts
`shouldBe` [("preference", Just "_local")]
describe "realtime" $ do
it "Just True renders as realtime=true" $ do
let opts = defaultGetDocumentOptions {gdoRealtime = Just True}
getDocumentOptionsParams opts `shouldBe` [("realtime", boolTrue)]
it "Just False renders as realtime=false" $ do
let opts = defaultGetDocumentOptions {gdoRealtime = Just False}
getDocumentOptionsParams opts `shouldBe` [("realtime", boolFalse)]
describe "refresh" $ do
it "Just True renders as refresh=true" $ do
let opts = defaultGetDocumentOptions {gdoRefresh = Just True}
getDocumentOptionsParams opts `shouldBe` [("refresh", boolTrue)]
it "Just False renders as refresh=false" $ do
let opts = defaultGetDocumentOptions {gdoRefresh = Just False}
getDocumentOptionsParams opts `shouldBe` [("refresh", boolFalse)]
it "routing renders verbatim" $ do
let opts = defaultGetDocumentOptions {gdoRouting = Just "user-42"}
getDocumentOptionsParams opts `shouldBe` [("routing", Just "user-42")]
it "version renders the Word64 as a decimal string" $ do
let opts = defaultGetDocumentOptions {gdoVersion = Just 7}
getDocumentOptionsParams opts `shouldBe` [("version", Just "7")]
describe "version_type" $ do
it "renders internal" $ do
let opts = defaultGetDocumentOptions {gdoVersionType = Just VersionTypeInternal}
getDocumentOptionsParams opts
`shouldBe` [("version_type", Just "internal")]
it "renders external_gte" $ do
let opts = defaultGetDocumentOptions {gdoVersionType = Just VersionTypeExternalGTE}
getDocumentOptionsParams opts
`shouldBe` [("version_type", Just "external_gte")]
it "renders every field together when all are populated" $ do
let opts =
defaultGetDocumentOptions
{ gdoSource = Just False,
gdoSourceIncludes = Just "a,b",
gdoSourceExcludes = Just "c",
gdoStoredFields = Just "s",
gdoPreference = Just "_local",
gdoRealtime = Just True,
gdoRefresh = Just False,
gdoRouting = Just "r",
gdoVersion = Just 9,
gdoVersionType = Just VersionTypeExternal
}
let rendered = getDocumentOptionsParams opts
length rendered `shouldBe` 10
rendered `shouldSatisfy` all (isJust . snd)
normalize rendered
`shouldBe` sort
[ ("_source", Just "false"),
("_source_excludes", Just "c"),
("_source_includes", Just "a,b"),
("preference", Just "_local"),
("realtime", Just "true"),
("refresh", Just "false"),
("routing", Just "r"),
("stored_fields", Just "s"),
("version", Just "9"),
("version_type", Just "external")
]
describe "GetDocumentSourceOptions URI param rendering" $ do
it "defaultGetDocumentSourceOptions emits no params" $
getDocumentSourceOptionsParams defaultGetDocumentSourceOptions
`shouldBe` []
it "_source_includes renders verbatim" $ do
let opts = defaultGetDocumentSourceOptions {gdsoSourceIncludes = Just "metadata.*,name"}
getDocumentSourceOptionsParams opts
`shouldBe` [("_source_includes", Just "metadata.*,name")]
it "_source_excludes renders verbatim" $ do
let opts = defaultGetDocumentSourceOptions {gdsoSourceExcludes = Just "internal.*"}
getDocumentSourceOptionsParams opts
`shouldBe` [("_source_excludes", Just "internal.*")]
it "preference renders verbatim" $ do
let opts = defaultGetDocumentSourceOptions {gdsoPreference = Just "_local"}
getDocumentSourceOptionsParams opts
`shouldBe` [("preference", Just "_local")]
describe "realtime" $ do
it "Just True renders as realtime=true" $ do
let opts = defaultGetDocumentSourceOptions {gdsoRealtime = Just True}
getDocumentSourceOptionsParams opts `shouldBe` [("realtime", boolTrue)]
it "Just False renders as realtime=false" $ do
let opts = defaultGetDocumentSourceOptions {gdsoRealtime = Just False}
getDocumentSourceOptionsParams opts `shouldBe` [("realtime", boolFalse)]
describe "refresh" $ do
it "Just True renders as refresh=true" $ do
let opts = defaultGetDocumentSourceOptions {gdsoRefresh = Just True}
getDocumentSourceOptionsParams opts `shouldBe` [("refresh", boolTrue)]
it "Just False renders as refresh=false" $ do
let opts = defaultGetDocumentSourceOptions {gdsoRefresh = Just False}
getDocumentSourceOptionsParams opts `shouldBe` [("refresh", boolFalse)]
it "routing renders verbatim" $ do
let opts = defaultGetDocumentSourceOptions {gdsoRouting = Just "user-42"}
getDocumentSourceOptionsParams opts `shouldBe` [("routing", Just "user-42")]
it "version renders the Word64 as a decimal string" $ do
let opts = defaultGetDocumentSourceOptions {gdsoVersion = Just 7}
getDocumentSourceOptionsParams opts `shouldBe` [("version", Just "7")]
describe "version_type" $ do
it "renders internal" $ do
let opts = defaultGetDocumentSourceOptions {gdsoVersionType = Just VersionTypeInternal}
getDocumentSourceOptionsParams opts
`shouldBe` [("version_type", Just "internal")]
it "renders external_gte" $ do
let opts = defaultGetDocumentSourceOptions {gdsoVersionType = Just VersionTypeExternalGTE}
getDocumentSourceOptionsParams opts
`shouldBe` [("version_type", Just "external_gte")]
it "renders every field together when all are populated" $ do
let opts =
defaultGetDocumentSourceOptions
{ gdsoSourceIncludes = Just "a,b",
gdsoSourceExcludes = Just "c",
gdsoPreference = Just "_local",
gdsoRealtime = Just True,
gdsoRefresh = Just False,
gdsoRouting = Just "r",
gdsoVersion = Just 9,
gdsoVersionType = Just VersionTypeExternal
}
let rendered = getDocumentSourceOptionsParams opts
length rendered `shouldBe` 8
rendered `shouldSatisfy` all (isJust . snd)
normalize rendered
`shouldBe` sort
[ ("_source_excludes", Just "c"),
("_source_includes", Just "a,b"),
("preference", Just "_local"),
("realtime", Just "true"),
("refresh", Just "false"),
("routing", Just "r"),
("version", Just "9"),
("version_type", Just "external")
]
describe "DeleteDocumentOptions URI param rendering" $ do
it "defaultDeleteDocumentOptions emits no params" $
deleteDocumentOptionsParams defaultDeleteDocumentOptions
`shouldBe` []
describe "wait_for_active_shards" $ do
it "AllActiveShards renders as wait_for_active_shards=all" $ do
let opts = defaultDeleteDocumentOptions {ddoWaitForActiveShards = Just AllActiveShards}
deleteDocumentOptionsParams opts
`shouldBe` [("wait_for_active_shards", Just "all")]
it "ActiveShards n renders as wait_for_active_shards=<n>" $ do
let opts = defaultDeleteDocumentOptions {ddoWaitForActiveShards = Just (ActiveShards 3)}
deleteDocumentOptionsParams opts
`shouldBe` [("wait_for_active_shards", Just "3")]
describe "refresh" $ do
it "RefreshTrue renders as refresh=true" $ do
let opts = defaultDeleteDocumentOptions {ddoRefresh = Just RefreshTrue}
deleteDocumentOptionsParams opts `shouldBe` [("refresh", Just "true")]
it "RefreshFalse renders as refresh=false" $ do
let opts = defaultDeleteDocumentOptions {ddoRefresh = Just RefreshFalse}
deleteDocumentOptionsParams opts `shouldBe` [("refresh", Just "false")]
it "RefreshWaitFor renders as refresh=wait_for" $ do
let opts = defaultDeleteDocumentOptions {ddoRefresh = Just RefreshWaitFor}
deleteDocumentOptionsParams opts `shouldBe` [("refresh", Just "wait_for")]
it "routing renders verbatim" $ do
let opts = defaultDeleteDocumentOptions {ddoRouting = Just "user-42"}
deleteDocumentOptionsParams opts `shouldBe` [("routing", Just "user-42")]
it "timeout renders verbatim" $ do
let opts = defaultDeleteDocumentOptions {ddoTimeout = Just "5s"}
deleteDocumentOptionsParams opts `shouldBe` [("timeout", Just "5s")]
it "version renders the Word64 as a decimal string" $ do
let opts = defaultDeleteDocumentOptions {ddoVersion = Just 7}
deleteDocumentOptionsParams opts `shouldBe` [("version", Just "7")]
describe "version_type" $ do
it "renders internal" $ do
let opts = defaultDeleteDocumentOptions {ddoVersionType = Just VersionTypeInternal}
deleteDocumentOptionsParams opts
`shouldBe` [("version_type", Just "internal")]
it "renders external" $ do
let opts = defaultDeleteDocumentOptions {ddoVersionType = Just VersionTypeExternal}
deleteDocumentOptionsParams opts
`shouldBe` [("version_type", Just "external")]
it "renders external_gte" $ do
let opts = defaultDeleteDocumentOptions {ddoVersionType = Just VersionTypeExternalGTE}
deleteDocumentOptionsParams opts
`shouldBe` [("version_type", Just "external_gte")]
describe "if_seq_no / if_primary_term" $ do
it "emits both when both are set" $ do
let opts =
defaultDeleteDocumentOptions
{ ddoIfSeqNo = Just 7,
ddoIfPrimaryTerm = Just 2
}
normalize (deleteDocumentOptionsParams opts)
`shouldBe` [ ("if_primary_term", Just "2"),
("if_seq_no", Just "7")
]
-- As with IndexDocumentSettings, each member of the OCC pair is
-- emitted independently: a half-set pair is passed through to
-- Elasticsearch's HTTP 400 rather than being silently dropped.
it "emits if_seq_no alone when only if_seq_no is set" $ do
let opts = defaultDeleteDocumentOptions {ddoIfSeqNo = Just 7}
deleteDocumentOptionsParams opts
`shouldBe` [("if_seq_no", Just "7")]
it "emits if_primary_term alone when only if_primary_term is set" $ do
let opts = defaultDeleteDocumentOptions {ddoIfPrimaryTerm = Just 2}
deleteDocumentOptionsParams opts
`shouldBe` [("if_primary_term", Just "2")]
it "renders every field together when all are populated" $ do
let opts =
defaultDeleteDocumentOptions
{ ddoWaitForActiveShards = Just AllActiveShards,
ddoRefresh = Just RefreshWaitFor,
ddoRouting = Just "r",
ddoTimeout = Just "5s",
ddoVersion = Just 9,
ddoVersionType = Just VersionTypeExternal,
ddoIfSeqNo = Just 10,
ddoIfPrimaryTerm = Just 1
}
let rendered = deleteDocumentOptionsParams opts
length rendered `shouldBe` 8
rendered `shouldSatisfy` all (isJust . snd)
normalize rendered
`shouldBe` sort
[ ("if_primary_term", Just "1"),
("if_seq_no", Just "10"),
("refresh", Just "wait_for"),
("routing", Just "r"),
("timeout", Just "5s"),
("version", Just "9"),
("version_type", Just "external"),
("wait_for_active_shards", Just "all")
]
describe "DocumentExistsOptions URI param rendering" $ do
it "defaultDocumentExistsOptions emits no params" $
documentExistsOptionsParams defaultDocumentExistsOptions
`shouldBe` []
it "stored_fields renders verbatim" $ do
let opts = defaultDocumentExistsOptions {deoStoredFields = Just "user,location"}
documentExistsOptionsParams opts
`shouldBe` [("stored_fields", Just "user,location")]
it "preference renders verbatim" $ do
let opts = defaultDocumentExistsOptions {deoPreference = Just "_local"}
documentExistsOptionsParams opts
`shouldBe` [("preference", Just "_local")]
describe "realtime" $ do
it "Just True renders as realtime=true" $ do
let opts = defaultDocumentExistsOptions {deoRealtime = Just True}
documentExistsOptionsParams opts `shouldBe` [("realtime", boolTrue)]
it "Just False renders as realtime=false" $ do
let opts = defaultDocumentExistsOptions {deoRealtime = Just False}
documentExistsOptionsParams opts `shouldBe` [("realtime", boolFalse)]
describe "refresh" $ do
it "Just True renders as refresh=true" $ do
let opts = defaultDocumentExistsOptions {deoRefresh = Just True}
documentExistsOptionsParams opts `shouldBe` [("refresh", boolTrue)]
it "Just False renders as refresh=false" $ do
let opts = defaultDocumentExistsOptions {deoRefresh = Just False}
documentExistsOptionsParams opts `shouldBe` [("refresh", boolFalse)]
it "routing renders verbatim" $ do
let opts = defaultDocumentExistsOptions {deoRouting = Just "user-42"}
documentExistsOptionsParams opts `shouldBe` [("routing", Just "user-42")]
it "version renders the Word64 as a decimal string" $ do
let opts = defaultDocumentExistsOptions {deoVersion = Just 7}
documentExistsOptionsParams opts `shouldBe` [("version", Just "7")]
describe "version_type" $ do
it "renders internal" $ do
let opts = defaultDocumentExistsOptions {deoVersionType = Just VersionTypeInternal}
documentExistsOptionsParams opts
`shouldBe` [("version_type", Just "internal")]
it "renders external" $ do
let opts = defaultDocumentExistsOptions {deoVersionType = Just VersionTypeExternal}
documentExistsOptionsParams opts
`shouldBe` [("version_type", Just "external")]
it "renders external_gte" $ do
let opts = defaultDocumentExistsOptions {deoVersionType = Just VersionTypeExternalGTE}
documentExistsOptionsParams opts
`shouldBe` [("version_type", Just "external_gte")]
it "renders every field together when all are populated" $ do
let opts =
defaultDocumentExistsOptions
{ deoStoredFields = Just "s",
deoPreference = Just "_local",
deoRealtime = Just True,
deoRefresh = Just False,
deoRouting = Just "r",
deoVersion = Just 9,
deoVersionType = Just VersionTypeExternal
}
let rendered = documentExistsOptionsParams opts
length rendered `shouldBe` 7
rendered `shouldSatisfy` all (isJust . snd)
normalize rendered
`shouldBe` sort
[ ("preference", Just "_local"),
("realtime", Just "true"),
("refresh", Just "false"),
("routing", Just "r"),
("stored_fields", Just "s"),
("version", Just "9"),
("version_type", Just "external")
]
describe "DocumentSourceExistsOptions URI param rendering" $ do
it "defaultDocumentSourceExistsOptions emits no params" $
documentSourceExistsParams defaultDocumentSourceExistsOptions
`shouldBe` []
it "preference renders verbatim" $ do
let opts = defaultDocumentSourceExistsOptions {dseoPreference = Just "_local"}
documentSourceExistsParams opts
`shouldBe` [("preference", Just "_local")]
describe "realtime" $ do
it "Just True renders as realtime=true" $ do
let opts = defaultDocumentSourceExistsOptions {dseoRealtime = Just True}
documentSourceExistsParams opts `shouldBe` [("realtime", boolTrue)]
it "Just False renders as realtime=false" $ do
let opts = defaultDocumentSourceExistsOptions {dseoRealtime = Just False}
documentSourceExistsParams opts `shouldBe` [("realtime", boolFalse)]
describe "refresh" $ do
it "Just True renders as refresh=true" $ do
let opts = defaultDocumentSourceExistsOptions {dseoRefresh = Just True}
documentSourceExistsParams opts `shouldBe` [("refresh", boolTrue)]
it "Just False renders as refresh=false" $ do
let opts = defaultDocumentSourceExistsOptions {dseoRefresh = Just False}
documentSourceExistsParams opts `shouldBe` [("refresh", boolFalse)]
it "routing renders verbatim" $ do
let opts = defaultDocumentSourceExistsOptions {dseoRouting = Just "user-42"}
documentSourceExistsParams opts `shouldBe` [("routing", Just "user-42")]
it "version renders the Word64 as a decimal string" $ do
let opts = defaultDocumentSourceExistsOptions {dseoVersion = Just 7}
documentSourceExistsParams opts `shouldBe` [("version", Just "7")]
describe "version_type" $ do
it "renders internal" $ do
let opts = defaultDocumentSourceExistsOptions {dseoVersionType = Just VersionTypeInternal}
documentSourceExistsParams opts
`shouldBe` [("version_type", Just "internal")]
it "renders external_gte" $ do
let opts = defaultDocumentSourceExistsOptions {dseoVersionType = Just VersionTypeExternalGTE}
documentSourceExistsParams opts
`shouldBe` [("version_type", Just "external_gte")]
it "renders every field together when all are populated" $ do
let opts =
defaultDocumentSourceExistsOptions
{ dseoPreference = Just "_local",
dseoRealtime = Just True,
dseoRefresh = Just False,
dseoRouting = Just "r",
dseoVersion = Just 9,
dseoVersionType = Just VersionTypeExternal
}
let rendered = documentSourceExistsParams opts
length rendered `shouldBe` 6
rendered `shouldSatisfy` all (isJust . snd)
normalize rendered
`shouldBe` sort
[ ("preference", Just "_local"),
("realtime", Just "true"),
("refresh", Just "false"),
("routing", Just "r"),
("version", Just "9"),
("version_type", Just "external")
]
describe "ByQueryOptions URI param rendering" $ do
it "defaultByQueryOptions emits no params" $
byQueryOptionsParams defaultByQueryOptions
`shouldBe` []
describe "conflicts" $ do
it "ConflictsProceed renders as conflicts=proceed" $ do
let opts = defaultByQueryOptions {bqoConflicts = Just ConflictsProceed}
byQueryOptionsParams opts `shouldBe` [("conflicts", Just "proceed")]
it "ConflictsAbort renders as conflicts=abort" $ do
let opts = defaultByQueryOptions {bqoConflicts = Just ConflictsAbort}
byQueryOptionsParams opts `shouldBe` [("conflicts", Just "abort")]
describe "wait_for_completion" $ do
it "Just True renders as wait_for_completion=true" $ do
let opts = defaultByQueryOptions {bqoWaitForCompletion = Just True}
byQueryOptionsParams opts `shouldBe` [("wait_for_completion", boolTrue)]
it "Just False renders as wait_for_completion=false" $ do
let opts = defaultByQueryOptions {bqoWaitForCompletion = Just False}
byQueryOptionsParams opts `shouldBe` [("wait_for_completion", boolFalse)]
it "refresh renders via RefreshPolicy" $ do
let opts = defaultByQueryOptions {bqoRefresh = Just RefreshTrue}
byQueryOptionsParams opts `shouldBe` [("refresh", Just "true")]
it "timeout renders verbatim" $ do
let opts = defaultByQueryOptions {bqoTimeout = Just "5s"}
byQueryOptionsParams opts `shouldBe` [("timeout", Just "5s")]
it "scroll renders verbatim" $ do
let opts = defaultByQueryOptions {bqoScroll = Just "1m"}
byQueryOptionsParams opts `shouldBe` [("scroll", Just "1m")]
it "scroll_size renders as decimal" $ do
let opts = defaultByQueryOptions {bqoScrollSize = Just 500}
byQueryOptionsParams opts `shouldBe` [("scroll_size", Just "500")]
describe "slices" $ do
it "SlicesAuto renders as slices=auto" $ do
let opts = defaultByQueryOptions {bqoSlices = Just SlicesAuto}
byQueryOptionsParams opts `shouldBe` [("slices", Just "auto")]
it "SlicesCount n renders as slices=<n>" $ do
let opts = defaultByQueryOptions {bqoSlices = Just (SlicesCount 4)}
byQueryOptionsParams opts `shouldBe` [("slices", Just "4")]
it "routing renders verbatim" $ do
let opts = defaultByQueryOptions {bqoRouting = Just "user-1"}
byQueryOptionsParams opts `shouldBe` [("routing", Just "user-1")]
it "max_docs renders as decimal" $ do
let opts = defaultByQueryOptions {bqoMaxDocs = Just 100}
byQueryOptionsParams opts `shouldBe` [("max_docs", Just "100")]
describe "request_cache" $ do
it "Just True renders as request_cache=true" $ do
let opts = defaultByQueryOptions {bqoRequestCache = Just True}
byQueryOptionsParams opts `shouldBe` [("request_cache", boolTrue)]
it "Just False renders as request_cache=false" $ do
let opts = defaultByQueryOptions {bqoRequestCache = Just False}
byQueryOptionsParams opts `shouldBe` [("request_cache", boolFalse)]
it "pipeline renders verbatim" $ do
let opts = defaultByQueryOptions {bqoPipeline = Just "my-pipe"}
byQueryOptionsParams opts `shouldBe` [("pipeline", Just "my-pipe")]
it "renders every field together when all are populated" $ do
let opts =
defaultByQueryOptions
{ bqoConflicts = Just ConflictsProceed,
bqoWaitForCompletion = Just True,
bqoRefresh = Just RefreshWaitFor,
bqoTimeout = Just "5s",
bqoScroll = Just "1m",
bqoScrollSize = Just 100,
bqoSlices = Just (SlicesCount 3),
bqoRouting = Just "r",
bqoMaxDocs = Just 50,
bqoRequestCache = Just False,
bqoPipeline = Just "p"
}
let rendered = byQueryOptionsParams opts
length rendered `shouldBe` 11
rendered `shouldSatisfy` all (isJust . snd)
normalize rendered
`shouldBe` sort
[ ("conflicts", Just "proceed"),
("max_docs", Just "50"),
("pipeline", Just "p"),
("refresh", Just "wait_for"),
("request_cache", Just "false"),
("routing", Just "r"),
("scroll", Just "1m"),
("scroll_size", Just "100"),
("slices", Just "3"),
("timeout", Just "5s"),
("wait_for_completion", Just "true")
]
describe "UpdateBody JSON encoding" $ do
describe "UpdateDoc" $ do
it "encodes as {\"doc\": ...} with no extras" $ do
let body = mkUpdateDoc (object ["counter" .= (1 :: Int)])
encode body
`shouldBe` encode (object ["doc" .= object ["counter" .= (1 :: Int)]])
it "includes doc_as_upsert when set to Just True" $ do
let body =
UpdateDoc
{ ubDoc = object ["name" .= String "x"],
ubDocAsUpsert = Just True
}
encode body
`shouldBe` encode
( object
[ "doc" .= object ["name" .= String "x"],
"doc_as_upsert" .= Bool True
]
)
it "omits doc_as_upsert when Nothing" $ do
let body = mkUpdateDoc (object ["name" .= String "x"])
encode body
`shouldBe` encode (object ["doc" .= object ["name" .= String "x"]])
it "omits doc_as_upsert when Just False is NOT set — Nothing is the only omit" $
-- doc_as_upsert=Just False is a real value the caller might want to
-- send; we should NOT collapse it. The omission is only for Nothing.
do
let body =
UpdateDoc
{ ubDoc = object ["name" .= String "x"],
ubDocAsUpsert = Just False
}
encode body
`shouldBe` encode
( object
[ "doc" .= object ["name" .= String "x"],
"doc_as_upsert" .= Bool False
]
)
describe "UpdateScript" $ do
it "encodes the script as a top-level \"script\" key without double-wrapping" $ do
let script =
Script
{ scriptLanguage = Just (ScriptLanguage "painless"),
scriptSource = ScriptInline "ctx._source.counter += 1",
scriptParams = Nothing,
scriptOptions = Nothing
}
body = mkUpdateScript script
encode body
`shouldBe` encode
( object
[ "script"
.= object
[ "lang" .= String "painless",
"source" .= String "ctx._source.counter += 1"
]
]
)
it "includes upsert when set" $ do
let script =
Script Nothing (ScriptInline "ctx._source.x = 1") Nothing Nothing
body =
UpdateScript
{ ubScript = script,
ubUpsert = Just (object ["x" .= (0 :: Int)]),
ubScriptedUpsert = Nothing
}
encode body
`shouldBe` encode
( object
[ "script" .= object ["source" .= String "ctx._source.x = 1"],
"upsert" .= object ["x" .= (0 :: Int)]
]
)
it "includes scripted_upsert when set to Just True" $ do
let script =
Script Nothing (ScriptInline "ctx._source.x = 1") Nothing Nothing
body =
UpdateScript
{ ubScript = script,
ubUpsert = Nothing,
ubScriptedUpsert = Just True
}
encode body
`shouldBe` encode
( object
[ "script" .= object ["source" .= String "ctx._source.x = 1"],
"scripted_upsert" .= Bool True
]
)
it "uses 'id' (not 'source') for stored scripts" $ do
let script =
Script Nothing (ScriptId "my-stored-script") Nothing Nothing
body = mkUpdateScript script
encode body
`shouldBe` encode
(object ["script" .= object ["id" .= String "my-stored-script"]])
where
isJust (Just _) = True
isJust Nothing = False