packages feed

bloodhound-1.0.0.0: tests/Test/ScriptContextsSpec.hs

{-# LANGUAGE OverloadedStrings #-}

module Test.ScriptContextsSpec (spec) where

import Database.Bloodhound.Common.Types
import TestsUtils.Common
import TestsUtils.Import

spec :: Spec
spec = do
  -- ------------------------------------------------------------------ --
  -- Pure JSON decoder tests (no ES required).                          --
  -- ------------------------------------------------------------------ --
  describe "ScriptContextsResponse JSON parsing" $ do
    let emptyBody = "{\"contexts\":[]}"
        withMethodsBody =
          "{\"contexts\":[{\"name\":\"aggs\",\"methods\":[\
          \{\"name\":\"execute\",\"return_type\":\"java.lang.Object\",\"params\":[]},\
          \{\"name\":\"getDoc\",\"return_type\":\"java.util.Map\",\"params\":[]}]}]}"
        -- The @analysis@ context's execute is one of the few methods
        -- that carries a non-empty params array; captured from a live
        -- ES 7.17.25 cluster.
        withParamsBody =
          "{\"contexts\":[{\"name\":\"analysis\",\"methods\":[\
          \{\"name\":\"execute\",\"return_type\":\"boolean\",\
          \\"params\":[{\"type\":\"org.elasticsearch.analysis.common.AnalysisPredicateScript$Token\",\
          \\"name\":\"token\"}]}]}]}"

    it "parses the empty contexts array" $ do
      let Just (r :: ScriptContextsResponse) = decode emptyBody
      scrContexts r `shouldBe` []

    it "parses contexts with zero-argument methods" $ do
      let Just (r :: ScriptContextsResponse) = decode withMethodsBody
      scrContexts r `shouldSatisfy` (not . null)
      let ctx = head (scrContexts r)
      sciName ctx `shouldBe` "aggs"
      length (sciMethods ctx) `shouldBe` 2
      let m = head (sciMethods ctx)
      scmName m `shouldBe` "execute"
      scmReturnType m `shouldBe` "java.lang.Object"
      scmParams m `shouldBe` []

    it "parses a method with non-empty params (the `type` key)" $ do
      let Just (r :: ScriptContextsResponse) = decode withParamsBody
      let ctx = head (scrContexts r)
      sciName ctx `shouldBe` "analysis"
      let m = head (sciMethods ctx)
      scmName m `shouldBe` "execute"
      scmReturnType m `shouldBe` "boolean"
      length (scmParams m) `shouldBe` 1
      let p = head (scmParams m)
      scpName p `shouldBe` "token"
      scpType p
        `shouldBe` "org.elasticsearch.analysis.common.AnalysisPredicateScript$Token"

    it "treats a missing contexts key as the empty list" $ do
      let Just (r :: ScriptContextsResponse) = decode "{}"
      scrContexts r `shouldBe` []

    it "round-trips the full response via ToJSON/FromJSON" $ do
      let Just (original :: ScriptContextsResponse) = decode withParamsBody
          reDecoded = decode (encode original) :: Maybe ScriptContextsResponse
      Just original `shouldBe` reDecoded

  -- ------------------------------------------------------------------ --
  -- Endpoint shape: pure checks against the BHRequest value; no live   --
  -- backend needed.                                                     --
  -- ------------------------------------------------------------------ --
  describe "getScriptContexts endpoint shape" $ do
    it "GETs /_script_context with no body and no params" $ do
      let req = getScriptContexts
      bhRequestMethod req `shouldBe` "GET"
      getRawEndpoint (bhRequestEndpoint req) `shouldBe` ["_script_context"]
      getRawEndpointQueries (bhRequestEndpoint req) `shouldBe` []
      bhRequestBody req `shouldBe` Nothing

  -- ------------------------------------------------------------------ --
  -- Live backend tests (need ES on ES_TEST_SERVER, default 9200).      --
  -- _script_context is served by ES 7.x/8.x/9.x and OpenSearch         --
  -- 1.x/2.x/3.x.                                                       --
  -- ------------------------------------------------------------------ --
  describe "getScriptContexts live API" $ do
    it "returns a non-empty contexts catalogue" $
      withTestEnv $ do
        r <- performBHRequest getScriptContexts
        liftIO $ scrContexts r `shouldSatisfy` (not . null)
    it "every context has a name and at least an execute method" $
      withTestEnv $ do
        r <- performBHRequest getScriptContexts
        liftIO $
          mapM_
            ( \ctx -> do
                sciName ctx `shouldSatisfy` (/= "")
                map scmName (sciMethods ctx) `shouldContain` ["execute"]
            )
            (scrContexts r)