1// Copyright 2012-present Oliver Eilhard. All rights reserved.
2// Use of this source code is governed by a MIT-license.
3// See http://olivere.mit-license.org/license.txt for details.
4
5package elastic
6
7import (
8	"context"
9	"encoding/json"
10	"testing"
11)
12
13func TestHighlighterField(t *testing.T) {
14	field := NewHighlighterField("grade")
15	src, err := field.Source()
16	if err != nil {
17		t.Fatal(err)
18	}
19	data, err := json.Marshal(src)
20	if err != nil {
21		t.Fatalf("marshaling to JSON failed: %v", err)
22	}
23	got := string(data)
24	expected := `{}`
25	if got != expected {
26		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
27	}
28}
29
30func TestHighlighterFieldWithOptions(t *testing.T) {
31	field := NewHighlighterField("grade").FragmentSize(2).NumOfFragments(1)
32	src, err := field.Source()
33	if err != nil {
34		t.Fatal(err)
35	}
36	data, err := json.Marshal(src)
37	if err != nil {
38		t.Fatalf("marshaling to JSON failed: %v", err)
39	}
40	got := string(data)
41	expected := `{"fragment_size":2,"number_of_fragments":1}`
42	if got != expected {
43		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
44	}
45}
46
47func TestHighlightWithStringField(t *testing.T) {
48	builder := NewHighlight().Field("grade")
49	src, err := builder.Source()
50	if err != nil {
51		t.Fatal(err)
52	}
53	data, err := json.Marshal(src)
54	if err != nil {
55		t.Fatalf("marshaling to JSON failed: %v", err)
56	}
57	got := string(data)
58	expected := `{"fields":{"grade":{}}}`
59	if got != expected {
60		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
61	}
62}
63
64func TestHighlightWithFields(t *testing.T) {
65	gradeField := NewHighlighterField("grade")
66	builder := NewHighlight().Fields(gradeField)
67	src, err := builder.Source()
68	if err != nil {
69		t.Fatal(err)
70	}
71	data, err := json.Marshal(src)
72	if err != nil {
73		t.Fatalf("marshaling to JSON failed: %v", err)
74	}
75	got := string(data)
76	expected := `{"fields":{"grade":{}}}`
77	if got != expected {
78		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
79	}
80}
81
82func TestHighlightWithMultipleFields(t *testing.T) {
83	gradeField := NewHighlighterField("grade")
84	colorField := NewHighlighterField("color")
85	builder := NewHighlight().Fields(gradeField, colorField)
86	src, err := builder.Source()
87	if err != nil {
88		t.Fatal(err)
89	}
90	data, err := json.Marshal(src)
91	if err != nil {
92		t.Fatalf("marshaling to JSON failed: %v", err)
93	}
94	got := string(data)
95	expected := `{"fields":{"color":{},"grade":{}}}`
96	if got != expected {
97		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
98	}
99}
100
101func TestHighlighterWithExplicitFieldOrder(t *testing.T) {
102	gradeField := NewHighlighterField("grade").FragmentSize(2)
103	colorField := NewHighlighterField("color").FragmentSize(2).NumOfFragments(1)
104	builder := NewHighlight().Fields(gradeField, colorField).UseExplicitFieldOrder(true)
105	src, err := builder.Source()
106	if err != nil {
107		t.Fatal(err)
108	}
109	data, err := json.Marshal(src)
110	if err != nil {
111		t.Fatalf("marshaling to JSON failed: %v", err)
112	}
113	got := string(data)
114	expected := `{"fields":[{"grade":{"fragment_size":2}},{"color":{"fragment_size":2,"number_of_fragments":1}}]}`
115	if got != expected {
116		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
117	}
118}
119
120func TestHighlightWithBoundarySettings(t *testing.T) {
121	builder := NewHighlight().
122		BoundaryChars(" \t\r").
123		BoundaryScannerType("word")
124	src, err := builder.Source()
125	if err != nil {
126		t.Fatal(err)
127	}
128	data, err := json.Marshal(src)
129	if err != nil {
130		t.Fatalf("marshaling to JSON failed: %v", err)
131	}
132	got := string(data)
133	expected := `{"boundary_chars":" \t\r","boundary_scanner":"word"}`
134	if got != expected {
135		t.Errorf("expected\n%s\n,got:\n%s", expected, got)
136	}
137}
138
139func TestHighlightWithTermQuery(t *testing.T) {
140	client := setupTestClientAndCreateIndex(t)
141
142	tweet1 := tweet{User: "olivere", Message: "Welcome to Golang and Elasticsearch."}
143	tweet2 := tweet{User: "olivere", Message: "Another unrelated topic."}
144	tweet3 := tweet{User: "sandrae", Message: "Cycling is fun to do."}
145
146	// Add all documents
147	_, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO())
148	if err != nil {
149		t.Fatal(err)
150	}
151
152	_, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO())
153	if err != nil {
154		t.Fatal(err)
155	}
156
157	_, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO())
158	if err != nil {
159		t.Fatal(err)
160	}
161
162	_, err = client.Flush().Index(testIndexName).Do(context.TODO())
163	if err != nil {
164		t.Fatal(err)
165	}
166
167	// Specify highlighter
168	hl := NewHighlight()
169	hl = hl.Fields(NewHighlighterField("message"))
170	hl = hl.PreTags("<em>").PostTags("</em>")
171
172	// Match all should return all documents
173	query := NewPrefixQuery("message", "golang")
174	searchResult, err := client.Search().
175		Index(testIndexName).
176		Highlight(hl).
177		Query(query).
178		Do(context.TODO())
179	if err != nil {
180		t.Fatal(err)
181	}
182	if searchResult.Hits == nil {
183		t.Fatalf("expected SearchResult.Hits != nil; got nil")
184	}
185	if searchResult.Hits.TotalHits != 1 {
186		t.Fatalf("expected SearchResult.Hits.TotalHits = %d; got %d", 1, searchResult.Hits.TotalHits)
187	}
188	if len(searchResult.Hits.Hits) != 1 {
189		t.Fatalf("expected len(SearchResult.Hits.Hits) = %d; got %d", 1, len(searchResult.Hits.Hits))
190	}
191
192	hit := searchResult.Hits.Hits[0]
193	var tw tweet
194	if err := json.Unmarshal(*hit.Source, &tw); err != nil {
195		t.Fatal(err)
196	}
197	if hit.Highlight == nil || len(hit.Highlight) == 0 {
198		t.Fatal("expected hit to have a highlight; got nil")
199	}
200	if hl, found := hit.Highlight["message"]; found {
201		if len(hl) != 1 {
202			t.Fatalf("expected to have one highlight for field \"message\"; got %d", len(hl))
203		}
204		expected := "Welcome to <em>Golang</em> and Elasticsearch."
205		if hl[0] != expected {
206			t.Errorf("expected to have highlight \"%s\"; got \"%s\"", expected, hl[0])
207		}
208	} else {
209		t.Fatal("expected to have a highlight on field \"message\"; got none")
210	}
211}
212