bloodhound-1.0.0.0: tests/Test/MultiGetSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Test.MultiGetSpec where
import Data.List (isInfixOf)
import TestsUtils.Common
import TestsUtils.Import
spec :: Spec
spec =
describe "multi-get API" $ do
it "fetches multiple documents by ID" $
withTestEnv $ do
_ <- insertData
_ <- insertOther
result <- tryPerformBHRequest $ getDocuments @Tweet testIndex [DocId "1", DocId "2"]
case result of
Left _ -> liftIO $ expectationFailure "Multi-get failed"
Right resp -> do
let docs = multiGetResponseDocs resp
liftIO $ length docs `shouldBe` 2
it "returns found status for existing documents" $
withTestEnv $ do
_ <- insertData
result <- tryPerformBHRequest $ getDocuments @Tweet testIndex [DocId "1"]
case result of
Left _ -> liftIO $ expectationFailure "Multi-get failed"
Right resp -> do
let docs = multiGetResponseDocs resp
liftIO $ length docs `shouldBe` 1
let firstDoc = head docs
liftIO $ foundResult firstDoc `shouldSatisfy` isJust
it "returns not found for missing documents" $
withTestEnv $ do
_ <- insertData
result <- tryPerformBHRequest $ getDocuments @Tweet testIndex [DocId "nonexistent"]
case result of
Left _ -> liftIO $ expectationFailure "Multi-get failed"
Right resp -> do
let docs = multiGetResponseDocs resp
liftIO $ length docs `shouldBe` 1
let firstDoc = head docs
liftIO $ foundResult firstDoc `shouldBe` Nothing
it "handles mixed found and not found documents" $
withTestEnv $ do
_ <- insertData
result <- tryPerformBHRequest $ getDocuments @Tweet testIndex [DocId "1", DocId "nonexistent"]
case result of
Left _ -> liftIO $ expectationFailure "Multi-get failed"
Right resp -> do
let docs = multiGetResponseDocs resp
liftIO $ length docs `shouldBe` 2
let [firstDoc, secondDoc] = docs
liftIO $ foundResult firstDoc `shouldSatisfy` isJust
liftIO $ foundResult secondDoc `shouldBe` Nothing
describe "per-document source filtering (MultiGetDoc body)" $ do
it "multiGetDocSource=NoSource omits the source for that document only" $
withTestEnv $ do
_ <- insertData
_ <- insertOther
-- POST /_mget requires _index per-doc since no index is in the URL.
let doc1 =
(mkMultiGetDoc (DocId "1"))
{ multiGetDocSource = Just NoSource,
multiGetDocIndex = Just testIndex
}
doc2 = (mkMultiGetDoc (DocId "2")) {multiGetDocIndex = Just testIndex}
body = MultiGet [doc1, doc2]
result <- tryPerformBHRequest $ getDocumentsMulti @Tweet body
case result of
Left _ -> liftIO $ expectationFailure "Multi-get failed"
Right resp -> do
let [firstDoc, secondDoc] = multiGetResponseDocs resp
-- First doc: _source=false per-doc → source absent → foundResult Nothing
-- Second doc: normal → source present
liftIO $ getSource firstDoc `shouldBe` Nothing
liftIO $ getSource secondDoc `shouldBe` Just otherTweet
it "getDocumentsMultiWith applies MultiGetOptions at URI level" $
withTestEnv $ do
_ <- insertData
_ <- insertOther
let opts = defaultMultiGetOptions {mgoSource = Just False}
doc i = (mkMultiGetDoc (DocId i)) {multiGetDocIndex = Just testIndex}
body = MultiGet (map doc ["1", "2"])
result <- tryPerformBHRequest $ getDocumentsMultiWith @Tweet opts body
case result of
Left _ -> liftIO $ expectationFailure "Multi-get failed"
Right resp -> do
let docs = multiGetResponseDocs resp
liftIO $ length docs `shouldBe` 2
-- With _source=false at the URI level, no document should
-- carry a source.
liftIO $ all (isNothing . getSource) docs `shouldBe` True
it "getDocumentsWith applies MultiGetOptions at URI level" $
withTestEnv $ do
_ <- insertData
_ <- insertOther
let opts = defaultMultiGetOptions {mgoSourceIncludes = Just "user"}
-- Parse as Value so we can inspect the partial source without
-- requiring every Tweet field to be present.
result <- tryPerformBHRequest $ getDocumentsWith @Value opts testIndex [DocId "1", DocId "2"]
case result of
Left _ -> liftIO $ expectationFailure "Multi-get failed"
Right resp -> do
let docs = multiGetResponseDocs resp
liftIO $ length docs `shouldBe` 2
let firstAsValue = getSource (head docs)
liftIO $ firstAsValue `shouldSatisfy` isJust
-- With _source_includes=user, the re-encoded source should
-- contain exactly the "user" field and nothing else.
case firstAsValue of
Just v -> do
let s = show v
liftIO $ s `shouldSatisfy` isInfixOf "\"user\""
liftIO $ s `shouldSatisfy` not . isInfixOf "\"age\""
Nothing ->
liftIO $ expectationFailure "expected a source"