Skip to content

Commit

Permalink
Merge pull request #107 from coveo/unit-tests
Browse files Browse the repository at this point in the history
Unit tests
  • Loading branch information
jdevost authored Oct 24, 2018
2 parents 0b5ce57 + d9aa571 commit e43ba1e
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 13 deletions.
14 changes: 8 additions & 6 deletions defaults/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,12 @@ var DEFAULTPAGEVIEWFIELD = "urihash"
// DEFAULTORIGIN1 defaults to "All"
var DEFAULTORIGIN1 = "All"

var SEARCHENDPOINT_PROD = "https://cloudplatform.coveo.com/rest/search/"
var SEARCHENDPOINT_STAGING = "https://cloudplatformstaging.coveo.com/rest/search/"
var SEARCHENDPOINT_DEV = "https://cloudplatformdev.coveo.com/rest/search/"
var SEARCH_REST_PATH = "/rest/search/"
var SEARCHENDPOINT_PROD = "https://cloudplatform.coveo.com" + SEARCH_REST_PATH
var SEARCHENDPOINT_STAGING = "https://cloudplatformstaging.coveo.com" + SEARCH_REST_PATH
var SEARCHENDPOINT_DEV = "https://cloudplatformdev.coveo.com" + SEARCH_REST_PATH

var ANALYTICSENDPOINT_PROD = "https://usageanalytics.coveo.com/rest/v15/analytics/"
var ANALYTICSENDPOINT_STAGING = "https://usageanalyticsstaging.coveo.com/rest/v15/analytics/"
var ANALYTICSENDPOINT_DEV = "https://usageanalyticsdev.coveo.com/rest/v15/analytics/"
var ANALYTICS_REST_PATH = "/rest/v15/analytics/"
var ANALYTICSENDPOINT_PROD = "https://usageanalytics.coveo.com" + ANALYTICS_REST_PATH
var ANALYTICSENDPOINT_STAGING = "https://usageanalyticsstaging.coveo.com" + ANALYTICS_REST_PATH
var ANALYTICSENDPOINT_DEV = "https://usageanalyticsdev.coveo.com" + ANALYTICS_REST_PATH
133 changes: 128 additions & 5 deletions scenariolib/event_searchandclick_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package scenariolib_test

import (
"encoding/json"
"os"
"testing"

"github.com/coveo/uabot/defaults"
"github.com/coveo/uabot/scenariolib"
)

Expand All @@ -19,15 +21,10 @@ func TestSearchAndClickEventValid(t *testing.T) {
assert(t, valid, "Expected event to be valid, was false with error: %s", message)

equals(t, "queryTextTest", event.Query)

equals(t, 0.5, event.Probability)

equals(t, "docTitleTest", event.DocTitle)

assert(t, !event.Quickview, "Expected Quickview to be false.")

assert(t, !event.CaseSearch, "Expected CaseSearch to be false.")

equals(t, "inputTitleTest", event.InputTitle)

// Expect CustomData to be not nil
Expand All @@ -36,3 +33,129 @@ func TestSearchAndClickEventValid(t *testing.T) {
// Expect CustomData["data1"] to be "one"
equals(t, "one", event.CustomData["data1"])
}

func TestDecorateSearchAndClickEvent(t *testing.T) {
scenariolib.InitLogger(os.Stdout, os.Stdout, os.Stdout, os.Stderr)

// All requests caught by the Test server will be added to 'requests'
requests := make(map[string]RestRequest)

server := createTestServer(t, requests)
defer server.Close() // Close the server when test finishes

event := &scenariolib.SearchAndClickEvent{}
conf, err := scenariolib.NewConfigFromPath("../scenarios_examples/TESTScenarios.json")
ok(t, err)

// Use the server url to define the endpoints
conf.SearchEndpoint = server.URL + defaults.SEARCH_REST_PATH
conf.AnalyticsEndpoint = server.URL + defaults.ANALYTICS_REST_PATH

v, err := scenariolib.NewVisit("bot.searchToken", "bot.analyticsToken", "scenario.UserAgent", "en", conf)

v.SetupGeneral()
event.Execute(v)

// Validate the search request we expect Execute() to send.
req, exists := requests["/rest/search/"]
assert(t, exists, "Missing request for /rest/search/")
equals(t, "POST", req.Method)
equals(t, "Bearer bot.searchToken", req.Headers["Authorization"])
equals(t, "application/json", req.Headers["Content-Type"])
expectedBody := []byte(`{
"q": "aaaaaaaaaaa",
"numberOfResults": 20,
"tab": "All",
"pipeline": "besttechCommunity"
}`)
eq, err := JSONBytesEqual(expectedBody, req.Body)
assert(t, eq, "The Request's body for Search is not what we expected\nGot: %s\nExp: %s", expectedBody, req.Body)

// Validate analytics request we expect Execute() to send.
req, exists = requests["/rest/v15/analytics/search/"]
assert(t, exists, "Missing request for /rest/v15/analytics/search/")
equals(t, "POST", req.Method)
equals(t, "Bearer bot.analyticsToken", req.Headers["Authorization"])
equals(t, "application/json", req.Headers["Content-Type"])
expectedBody = []byte(`{
"language": "en",
"device": "Bot",
"customData": {
"JSUIVersion": "0.0.0.0;0.0.0.0",
"customData1": "customValue 1",
"ipaddress": "216.249.112.8"
},
"anonymous": true,
"originLevel1": "BotSearch",
"originLevel2": "",
"searchQueryUid": "",
"queryText": "aaaaaaaaaaa",
"actionCause": "searchboxSubmit",
"contextual": false
}`)
eq, err = JSONBytesEqual(expectedBody, req.Body)
assert(t, eq, "The Request's body for Analytics is not what we expected\nGot: %s\nExp: %s", expectedBody, req.Body)
}

func TestDecorateSearchAndClickEvent2(t *testing.T) {
scenariolib.InitLogger(os.Stdout, os.Stdout, os.Stdout, os.Stderr)

// All requests caught by the Test server will be added to 'requests'
requests := make(map[string]RestRequest)

server := createTestServer(t, requests)
defer server.Close() // Close the server when test finishes

event := &scenariolib.SearchAndClickEvent{}
conf, err := scenariolib.NewConfigFromPath("../scenarios_examples/DemoMovies.json")
ok(t, err)

// Use the server url to define the endpoints
conf.SearchEndpoint = server.URL + defaults.SEARCH_REST_PATH
conf.AnalyticsEndpoint = server.URL + defaults.ANALYTICS_REST_PATH

v, err := scenariolib.NewVisit("bot.searchToken", "bot.analyticsToken", "scenario.UserAgent", "en", conf)

v.SetupGeneral()
event.Execute(v)

// Validate the search request we expect Execute() to send.
req, exists := requests["/rest/search/"]
assert(t, exists, "Missing request for /rest/search/")
equals(t, "POST", req.Method)
equals(t, "Bearer bot.searchToken", req.Headers["Authorization"])
equals(t, "application/json", req.Headers["Content-Type"])
expectedBody := []byte(`{
"q": "Gostbuster",
"numberOfResults": 20,
"tab": "All",
"pipeline": "ML"
}`)
eq, err := JSONBytesEqual(expectedBody, req.Body)
assert(t, eq, "The Request's body for Search is not what we expected\nGot: %s\nExp: %s", expectedBody, req.Body)

// Validate analytics request we expect Execute() to send.
req, exists = requests["/rest/v15/analytics/search/"]
assert(t, exists, "Missing request for /rest/v15/analytics/search/")
equals(t, "POST", req.Method)
equals(t, "Bearer bot.analyticsToken", req.Headers["Authorization"])
equals(t, "application/json", req.Headers["Content-Type"])
expectedBody = []byte(`{
"language": "en",
"device": "Bot",
"customData": {
"JSUIVersion": "0.0.0.0;0.0.0.0",
"c_isbot": "true",
"ipaddress": "198.199.154.209"
},
"username": "avery.caldwell@hexzone.com",
"originLevel1": "Movie",
"originLevel2": "default",
"searchQueryUid": "",
"queryText": "Gostbuster",
"actionCause": "searchboxSubmit",
"contextual": false
}`)
eq, err = JSONBytesEqual(expectedBody, req.Body)
assert(t, eq, "The Request's body for Analytics is not what we expected\nGot: %s\nExp: %s", expectedBody, req.Body)
}
52 changes: 52 additions & 0 deletions scenariolib/uabot_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package scenariolib_test

import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"path/filepath"
"reflect"
"runtime"
Expand Down Expand Up @@ -43,3 +47,51 @@ func equals(tb testing.TB, exp, act interface{}) {
tb.FailNow()
}
}

type RestRequest struct {
Method string
Headers map[string]string
Body []byte
}

// JSONBytesEqual compares the JSON in two byte slices.
func JSONBytesEqual(a, b []byte) (bool, error) {
var j, j2 interface{}
if err := json.Unmarshal(a, &j); err != nil {
return false, err
}
if err := json.Unmarshal(b, &j2); err != nil {
return false, err
}
return reflect.DeepEqual(j2, j), nil
}

// This a proxy to intercept requests sent to platform endpoints and add them into a map (receivedRequests).
// receivedRequests will then be used for validation in unit tests.
func createTestServer(t testing.TB, receivedRequests map[string]RestRequest) *httptest.Server {
// Start a local HTTP server to intercept requests
// Using url as key for the map of received requests.
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
url := req.URL.String()

headers := make(map[string]string)

for k := range req.Header {
headers[k] = req.Header.Get(k)
}
body, err := ioutil.ReadAll(req.Body)
if err != nil {
panic(err)
}
receivedRequests[url] = RestRequest{
Method: req.Method,
Headers: headers,
Body: body,
}

// Send back a static response
rw.Write([]byte(`{"status":"OK"}`))
}))

return server
}
4 changes: 2 additions & 2 deletions scenarios_examples/DemoMovies.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"anonymousThreshold": 0.3,
"timeBetweenVisits": 2,
"timeBetweenActions": 1,
"randomGoodQueries": [],
"randomBadQueries": [],
"randomGoodQueries": ["Ghostbusters"],
"randomBadQueries": ["Gostbuster"],
"randomCustomData": [{"apiname": "c_isbot", "values": ["true"]}],
"globalFilter": "@mytype=Movie",
"scenarios": [{
Expand Down

0 comments on commit e43ba1e

Please sign in to comment.