mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
Merge remote-tracking branch 'origin/master' into livyInterperter
This commit is contained in:
commit
f2ea724ab2
15 changed files with 239 additions and 59 deletions
|
|
@ -48,7 +48,7 @@ JIRA_USERNAME = os.environ.get("JIRA_USERNAME", "moon")
|
|||
# ASF JIRA password
|
||||
JIRA_PASSWORD = os.environ.get("JIRA_PASSWORD", "00000")
|
||||
|
||||
GITHUB_BASE = "https://github.com/apache/incubator-zeppelin/pulls"
|
||||
GITHUB_BASE = "https://github.com/apache/incubator-zeppelin/pull"
|
||||
GITHUB_API_BASE = "https://api.github.com/repos/apache/incubator-zeppelin"
|
||||
JIRA_BASE = "https://issues.apache.org/jira/browse"
|
||||
JIRA_API_BASE = "https://issues.apache.org/jira"
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ At the "Interpreters" menu, you have to create a new Flink interpreter and provi
|
|||
</tr>
|
||||
</table>
|
||||
|
||||
For more information about Flink configuration, you can find it [here](https://ci.apache.org/projects/flink/flink-docs-release-0.10/setup/config.html).
|
||||
For more information about Flink configuration, you can find it [here](https://ci.apache.org/projects/flink/flink-docs-release-1.0/setup/config.html).
|
||||
|
||||
## How to test it's working
|
||||
In example, by using the [Zeppelin notebook](https://www.zeppelinhub.com/viewer/notebooks/aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL05GTGFicy96ZXBwZWxpbi1ub3RlYm9va3MvbWFzdGVyL25vdGVib29rcy8yQVFFREs1UEMvbm90ZS5qc29u) is from Till Rohrmann's presentation [Interactive data analysis with Apache Flink](http://www.slideshare.net/tillrohrmann/data-analysis-49806564) for Apache Flink Meetup.
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ public class LoginRestApi {
|
|||
JsonResponse response = null;
|
||||
// ticket set to anonymous for anonymous user. Simplify testing.
|
||||
Subject currentUser = org.apache.shiro.SecurityUtils.getSubject();
|
||||
if (currentUser.isAuthenticated()) {
|
||||
currentUser.logout();
|
||||
}
|
||||
if (!currentUser.isAuthenticated()) {
|
||||
try {
|
||||
UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
|
||||
|
|
@ -107,6 +110,23 @@ public class LoginRestApi {
|
|||
LOG.warn(response.toString());
|
||||
return response.build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("logout")
|
||||
public Response logout() {
|
||||
JsonResponse response;
|
||||
|
||||
Subject currentUser = org.apache.shiro.SecurityUtils.getSubject();
|
||||
currentUser.logout();
|
||||
|
||||
Map<String, String> data = new HashMap<>();
|
||||
data.put("principal", "anonymous");
|
||||
data.put("roles", "");
|
||||
data.put("ticket", "anonymous");
|
||||
|
||||
response = new JsonResponse(Response.Status.OK, "", data);
|
||||
LOG.warn(response.toString());
|
||||
return response.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -756,5 +756,31 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
|
|||
ZeppelinServer.notebook.removeNote(note2.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTitleSearch() throws IOException {
|
||||
Note note = ZeppelinServer.notebook.createNote();
|
||||
String jsonRequest = "{\"title\": \"testTitleSearchOfParagraph\", \"text\": \"ThisIsToTestSearchMethodWithTitle \"}";
|
||||
PostMethod postNotebookText = httpPost("/notebook/" + note.getId() + "/paragraph", jsonRequest);
|
||||
postNotebookText.releaseConnection();
|
||||
|
||||
GetMethod searchNotebook = httpGet("/notebook/search?q='testTitleSearchOfParagraph'");
|
||||
searchNotebook.addRequestHeader("Origin", "http://localhost");
|
||||
Map<String, Object> respSearchResult = gson.fromJson(searchNotebook.getResponseBodyAsString(),
|
||||
new TypeToken<Map<String, Object>>() {
|
||||
}.getType());
|
||||
ArrayList searchBody = (ArrayList) respSearchResult.get("body");
|
||||
|
||||
int numberOfTitleHits = 0;
|
||||
for (int i = 0; i < searchBody.size(); i++) {
|
||||
Map<String, String> searchResult = (Map<String, String>) searchBody.get(i);
|
||||
if (searchResult.get("header").contains("testTitleSearchOfParagraph")) {
|
||||
numberOfTitleHits++;
|
||||
}
|
||||
}
|
||||
assertEquals("Paragraph title hits must be at-least one", true, numberOfTitleHits >= 1);
|
||||
searchNotebook.releaseConnection();
|
||||
ZeppelinServer.notebook.removeNote(note.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
"angular-elastic": "~2.4.2",
|
||||
"angular-elastic-input": "~2.2.0",
|
||||
"angular-xeditable": "0.1.8",
|
||||
"highlightjs": "~8.4.0",
|
||||
"highlightjs": "^9.2.0",
|
||||
"lodash": "~3.9.3",
|
||||
"angular-filter": "~0.5.4",
|
||||
"ngtoast": "~2.0.0",
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ limitations under the License.
|
|||
You can make beautiful data-driven, interactive, collaborative document with SQL, code and even more!<br>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-4" ng-if="ticket">
|
||||
<h4>Notebook
|
||||
<i ng-class="isReloadingNotes ? 'fa fa-refresh fa-spin' : 'fa fa-refresh'"
|
||||
ng-style="!isReloadingNotes && {'cursor': 'pointer'}" style="font-size: 13px;"
|
||||
|
|
|
|||
|
|
@ -686,10 +686,24 @@ angular.module('zeppelinWebApp').controller('NotebookCtrl',
|
|||
}).
|
||||
error(function(data, status, headers, config) {
|
||||
console.log('Error %o %o', status, data.message);
|
||||
BootstrapDialog.alert({
|
||||
closable: true,
|
||||
title: 'Insufficient privileges',
|
||||
message: data.message
|
||||
BootstrapDialog.show({
|
||||
closable: true,
|
||||
title: 'Insufficient privileges',
|
||||
message: data.message,
|
||||
buttons: [{
|
||||
label: 'Login',
|
||||
action: function(dialog) {
|
||||
dialog.close();
|
||||
angular.element('#loginModal').modal({
|
||||
show: 'true'
|
||||
});
|
||||
}
|
||||
}, {
|
||||
label: 'Cancel',
|
||||
action: function(dialog){
|
||||
dialog.close();
|
||||
}
|
||||
}]
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -74,12 +74,20 @@ angular
|
|||
};
|
||||
}
|
||||
|
||||
var lines = note.snippet
|
||||
var result = '';
|
||||
if (note.header !== '') {
|
||||
result = note.header + '\n\n' + note.snippet;
|
||||
} else {
|
||||
result = note.snippet;
|
||||
}
|
||||
|
||||
var lines = result
|
||||
.split('\n')
|
||||
.map(function(line, row) {
|
||||
|
||||
var match = line.match(/<B>(.+?)<\/B>/);
|
||||
|
||||
// return early if nothing to highlight
|
||||
// return early if nothing to highlight
|
||||
if (!match) {
|
||||
return line;
|
||||
}
|
||||
|
|
@ -93,15 +101,31 @@ angular
|
|||
|
||||
indeces.forEach(function(start) {
|
||||
var end = start + term.length;
|
||||
_editor
|
||||
.getSession()
|
||||
.addMarker(
|
||||
if (note.header !== '' && row === 0) {
|
||||
_editor
|
||||
.getSession()
|
||||
.addMarker(
|
||||
new Range(row, 0, row, line.length),
|
||||
'search-results-highlight-header',
|
||||
'background'
|
||||
);
|
||||
_editor
|
||||
.getSession()
|
||||
.addMarker(
|
||||
new Range(row, start, row, end),
|
||||
'search-results-highlight',
|
||||
'line'
|
||||
);
|
||||
} else {
|
||||
_editor
|
||||
.getSession()
|
||||
.addMarker(
|
||||
new Range(row, start, row, end),
|
||||
'search-results-highlight',
|
||||
'line'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return __line;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@
|
|||
position: absolute;
|
||||
}
|
||||
|
||||
.search-results-highlight-header {
|
||||
background-color: #e6f2ff;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* remove error highlighting */
|
||||
.search-results .ace_invalid {
|
||||
background: none !important;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ angular.module('zeppelinWebApp').controller('LoginCtrl',
|
|||
$rootScope.ticket = response.data.body;
|
||||
angular.element('#loginModal').modal('toggle');
|
||||
$rootScope.$broadcast('loginSuccess', true);
|
||||
$rootScope.userName = $scope.loginParams.userName;
|
||||
}, function errorCallback(errorResponse) {
|
||||
$scope.loginParams.errorText = 'The username and password that you entered don\'t match.';
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
angular.module('zeppelinWebApp').controller('NavCtrl', function($scope, $rootScope, $routeParams,
|
||||
$location, notebookListDataFactory, websocketMsgSrv, arrayOrderingSrv) {
|
||||
angular.module('zeppelinWebApp').controller('NavCtrl', function($scope, $rootScope, $http, $routeParams,
|
||||
$location, notebookListDataFactory, baseUrlSrv, websocketMsgSrv, arrayOrderingSrv) {
|
||||
/** Current list of notes (ids) */
|
||||
|
||||
$scope.showLoginWindow = function() {
|
||||
|
|
@ -71,6 +71,26 @@ angular.module('zeppelinWebApp').controller('NavCtrl', function($scope, $rootSco
|
|||
loadNotes();
|
||||
});
|
||||
|
||||
$scope.logout = function() {
|
||||
$http.post(baseUrlSrv.getRestApiBase()+'/login/logout')
|
||||
.success(function(data, status, headers, config) {
|
||||
$rootScope.userName = '';
|
||||
$rootScope.ticket.principal = '';
|
||||
$rootScope.ticket.ticket = '';
|
||||
$rootScope.ticket.roles = '';
|
||||
BootstrapDialog.show({
|
||||
message: 'Logout Success'
|
||||
});
|
||||
setTimeout(function() {
|
||||
window.location = '#';
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
}).
|
||||
error(function(data, status, headers, config) {
|
||||
console.log('Error %o %o', status, data.message);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.search = function() {
|
||||
$location.url(/search/ + $scope.searchTerm);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@
|
|||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
|
@ -37,7 +35,7 @@ limitations under the License.
|
|||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" ng-controller="NavCtrl as navbar">
|
||||
<ul class="nav navbar-nav">
|
||||
<ul class="nav navbar-nav" ng-if="ticket">
|
||||
<li class="dropdown" dropdown>
|
||||
<a href="#" class="dropdown-toggle" dropdown-toggle>Notebook <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
|
|
@ -63,7 +61,7 @@ limitations under the License.
|
|||
|
||||
|
||||
<ul class="nav navbar-nav navbar-right" style="margin-top:10px; margin-right:5px;">
|
||||
<li>
|
||||
<li ng-if="ticket">
|
||||
<!--TODO(bzz): move to Typeahead https://angular-ui.github.io/bootstrap -->
|
||||
<form role="search"
|
||||
style="width: 300px; display: inline-block; margin: 0 10px"
|
||||
|
|
@ -96,6 +94,9 @@ limitations under the License.
|
|||
<li ng-if="!ticket">
|
||||
<button class="btn btn-default" data-toggle="modal" data-target="#loginModal" ng-click="showLoginWindow()" style="margin-left: 10px">Login</button>
|
||||
</li>
|
||||
<li ng-show="ticket.principal && ticket.principal!='anonymous'" style="left: 5px;">
|
||||
<button class="btn btn-default" ng-click="logout()" tooltip-placement="bottom" tooltip="logout">Logout</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -60,10 +60,24 @@ angular.module('zeppelinWebApp').factory('websocketEvents', function($rootScope,
|
|||
} else if (op === 'NOTES_INFO') {
|
||||
$rootScope.$broadcast('setNoteMenu', data.notes);
|
||||
} else if (op === 'AUTH_INFO') {
|
||||
BootstrapDialog.alert({
|
||||
closable: true,
|
||||
title: 'Insufficient privileges',
|
||||
message: data.info.toString()
|
||||
BootstrapDialog.show({
|
||||
closable: true,
|
||||
title: 'Insufficient privileges',
|
||||
message: data.info.toString(),
|
||||
buttons: [{
|
||||
label: 'Login',
|
||||
action: function(dialog) {
|
||||
dialog.close();
|
||||
angular.element('#loginModal').modal({
|
||||
show: 'true'
|
||||
});
|
||||
}
|
||||
}, {
|
||||
label: 'Cancel',
|
||||
action: function(dialog){
|
||||
dialog.close();
|
||||
}
|
||||
}]
|
||||
});
|
||||
} else if (op === 'PARAGRAPH') {
|
||||
$rootScope.$broadcast('updateParagraph', data);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import org.apache.lucene.index.IndexReader;
|
|||
import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.index.IndexWriterConfig;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
|
||||
import org.apache.lucene.queryparser.classic.ParseException;
|
||||
import org.apache.lucene.queryparser.classic.QueryParser;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
|
|
@ -69,7 +70,8 @@ import com.google.common.collect.Lists;
|
|||
public class LuceneSearch implements SearchService {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LuceneSearch.class);
|
||||
|
||||
private static final String SEARCH_FIELD = "contents";
|
||||
private static final String SEARCH_FIELD_TEXT = "contents";
|
||||
private static final String SEARCH_FIELD_TITLE = "header";
|
||||
static final String PARAGRAPH = "paragraph";
|
||||
static final String ID_FIELD = "id";
|
||||
|
||||
|
|
@ -85,7 +87,7 @@ public class LuceneSearch implements SearchService {
|
|||
try {
|
||||
writer = new IndexWriter(ramDirectory, iwc);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to reate new IndexWriter", e);
|
||||
LOG.error("Failed to create new IndexWriter", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,10 +104,12 @@ public class LuceneSearch implements SearchService {
|
|||
try (IndexReader indexReader = DirectoryReader.open(ramDirectory)) {
|
||||
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
|
||||
Analyzer analyzer = new StandardAnalyzer();
|
||||
QueryParser parser = new QueryParser(SEARCH_FIELD, analyzer);
|
||||
MultiFieldQueryParser parser = new MultiFieldQueryParser(
|
||||
new String[] {SEARCH_FIELD_TEXT, SEARCH_FIELD_TITLE},
|
||||
analyzer);
|
||||
|
||||
Query query = parser.parse(queryStr);
|
||||
LOG.debug("Searching for: " + query.toString(SEARCH_FIELD));
|
||||
LOG.debug("Searching for: " + query.toString(SEARCH_FIELD_TEXT));
|
||||
|
||||
SimpleHTMLFormatter htmlFormatter = new SimpleHTMLFormatter();
|
||||
Highlighter highlighter = new Highlighter(htmlFormatter, new QueryScorer(query));
|
||||
|
|
@ -139,20 +143,33 @@ public class LuceneSearch implements SearchService {
|
|||
LOG.debug(" Title: {}", doc.get("title"));
|
||||
}
|
||||
|
||||
String text = doc.get(SEARCH_FIELD);
|
||||
TokenStream tokenStream = TokenSources.getTokenStream(searcher.getIndexReader(), id,
|
||||
SEARCH_FIELD, analyzer);
|
||||
TextFragment[] frag = highlighter.getBestTextFragments(tokenStream, text, true, 3);
|
||||
LOG.debug(" {} fragments found for query '{}'", frag.length, query);
|
||||
for (int j = 0; j < frag.length; j++) {
|
||||
if ((frag[j] != null) && (frag[j].getScore() > 0)) {
|
||||
LOG.debug(" Fragment: {}", frag[j].toString());
|
||||
}
|
||||
}
|
||||
String fragment = (frag != null && frag.length > 0) ? frag[0].toString() : "";
|
||||
String text = doc.get(SEARCH_FIELD_TEXT);
|
||||
String header = doc.get(SEARCH_FIELD_TITLE);
|
||||
String fragment = "";
|
||||
|
||||
if (text != null) {
|
||||
TokenStream tokenStream = TokenSources.getTokenStream(searcher.getIndexReader(), id,
|
||||
SEARCH_FIELD_TEXT, analyzer);
|
||||
TextFragment[] frag = highlighter.getBestTextFragments(tokenStream, text, true, 3);
|
||||
LOG.debug(" {} fragments found for query '{}'", frag.length, query);
|
||||
for (int j = 0; j < frag.length; j++) {
|
||||
if ((frag[j] != null) && (frag[j].getScore() > 0)) {
|
||||
LOG.debug(" Fragment: {}", frag[j].toString());
|
||||
}
|
||||
}
|
||||
fragment = (frag != null && frag.length > 0) ? frag[0].toString() : "";
|
||||
}
|
||||
|
||||
if (header != null) {
|
||||
TokenStream tokenTitle = TokenSources.getTokenStream(searcher.getIndexReader(), id,
|
||||
SEARCH_FIELD_TITLE, analyzer);
|
||||
TextFragment[] frgTitle = highlighter.getBestTextFragments(tokenTitle, header, true, 3);
|
||||
header = (frgTitle != null && frgTitle.length > 0) ? frgTitle[0].toString() : "";
|
||||
} else {
|
||||
header = "";
|
||||
}
|
||||
matchingParagraphs.add(ImmutableMap.of("id", path, // <noteId>/paragraph/<paragraphId>
|
||||
"name", title, "snippet", fragment, "text", text));
|
||||
"name", title, "snippet", fragment, "text", text, "header", header));
|
||||
} else {
|
||||
LOG.info("{}. No {} for this document", i + 1, ID_FIELD);
|
||||
}
|
||||
|
|
@ -252,11 +269,14 @@ public class LuceneSearch implements SearchService {
|
|||
doc.add(new StringField("title", noteName, Field.Store.YES));
|
||||
|
||||
if (null != p) {
|
||||
doc.add(new TextField(SEARCH_FIELD, p.getText(), Field.Store.YES));
|
||||
doc.add(new TextField(SEARCH_FIELD_TEXT, p.getText(), Field.Store.YES));
|
||||
if (p.getTitle() != null) {
|
||||
doc.add(new TextField(SEARCH_FIELD_TITLE, p.getTitle(), Field.Store.YES));
|
||||
}
|
||||
Date date = p.getDateStarted() != null ? p.getDateStarted() : p.getDateCreated();
|
||||
doc.add(new LongField("modified", date.getTime(), Field.Store.NO));
|
||||
} else {
|
||||
doc.add(new TextField(SEARCH_FIELD, noteName, Field.Store.YES));
|
||||
doc.add(new TextField(SEARCH_FIELD_TEXT, noteName, Field.Store.YES));
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@ public class LuceneSearchTest {
|
|||
|
||||
@Test public void canIndexNotebook() {
|
||||
//give
|
||||
Note note1 = newNoteWithParapgraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParapgraph("Notebook2", "not test");
|
||||
Note note1 = newNoteWithParagraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParagraph("Notebook2", "not test");
|
||||
List<Note> notebook = Arrays.asList(note1, note2);
|
||||
|
||||
//when
|
||||
|
|
@ -75,8 +75,8 @@ public class LuceneSearchTest {
|
|||
|
||||
@Test public void canIndexAndQuery() {
|
||||
//given
|
||||
Note note1 = newNoteWithParapgraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParapgraphs("Notebook2", "not test", "not test at all");
|
||||
Note note1 = newNoteWithParagraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParagraphs("Notebook2", "not test", "not test at all");
|
||||
notebookIndex.addIndexDocs(Arrays.asList(note1, note2));
|
||||
|
||||
//when
|
||||
|
|
@ -91,8 +91,8 @@ public class LuceneSearchTest {
|
|||
|
||||
@Test public void canIndexAndQueryByNotebookName() {
|
||||
//given
|
||||
Note note1 = newNoteWithParapgraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParapgraphs("Notebook2", "not test", "not test at all");
|
||||
Note note1 = newNoteWithParagraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParagraphs("Notebook2", "not test", "not test at all");
|
||||
notebookIndex.addIndexDocs(Arrays.asList(note1, note2));
|
||||
|
||||
//when
|
||||
|
|
@ -104,9 +104,31 @@ public class LuceneSearchTest {
|
|||
assertThat(results.get(0)).containsEntry("id", note1.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canIndexAndQueryByParagraphTitle() {
|
||||
//given
|
||||
Note note1 = newNoteWithParagraph("Notebook1", "test", "testingTitleSearch");
|
||||
Note note2 = newNoteWithParagraph("Notebook2", "not test", "notTestingTitleSearch");
|
||||
notebookIndex.addIndexDocs(Arrays.asList(note1, note2));
|
||||
|
||||
//when
|
||||
List<Map<String, String>> results = notebookIndex.query("testingTitleSearch");
|
||||
|
||||
//then
|
||||
assertThat(results).isNotEmpty();
|
||||
assertThat(results.size()).isAtLeast(1);
|
||||
int TitleHits = 0;
|
||||
for (Map<String, String> res : results) {
|
||||
if (res.get("header").contains("testingTitleSearch")) {
|
||||
TitleHits++;
|
||||
}
|
||||
}
|
||||
assertThat(TitleHits).isAtLeast(1);
|
||||
}
|
||||
|
||||
@Test public void indexKeyContract() throws IOException {
|
||||
//give
|
||||
Note note1 = newNoteWithParapgraph("Notebook1", "test");
|
||||
Note note1 = newNoteWithParagraph("Notebook1", "test");
|
||||
//when
|
||||
notebookIndex.addIndexDoc(note1);
|
||||
//then
|
||||
|
|
@ -129,8 +151,8 @@ public class LuceneSearchTest {
|
|||
|
||||
@Test public void canIndexAndReIndex() throws IOException {
|
||||
//given
|
||||
Note note1 = newNoteWithParapgraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParapgraphs("Notebook2", "not test", "not test at all");
|
||||
Note note1 = newNoteWithParagraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParagraphs("Notebook2", "not test", "not test at all");
|
||||
notebookIndex.addIndexDocs(Arrays.asList(note1, note2));
|
||||
|
||||
//when
|
||||
|
|
@ -155,8 +177,8 @@ public class LuceneSearchTest {
|
|||
|
||||
@Test public void canDeleteFromIndex() throws IOException {
|
||||
//given
|
||||
Note note1 = newNoteWithParapgraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParapgraphs("Notebook2", "not test", "not test at all");
|
||||
Note note1 = newNoteWithParagraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParagraphs("Notebook2", "not test", "not test at all");
|
||||
notebookIndex.addIndexDocs(Arrays.asList(note1, note2));
|
||||
assertThat(resultForQuery("Notebook2")).isNotEmpty();
|
||||
|
||||
|
|
@ -174,8 +196,8 @@ public class LuceneSearchTest {
|
|||
|
||||
@Test public void indexParagraphUpdatedOnNoteSave() throws IOException {
|
||||
//given: total 2 notebooks, 3 paragraphs
|
||||
Note note1 = newNoteWithParapgraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParapgraphs("Notebook2", "not test", "not test at all");
|
||||
Note note1 = newNoteWithParagraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParagraphs("Notebook2", "not test", "not test at all");
|
||||
notebookIndex.addIndexDocs(Arrays.asList(note1, note2));
|
||||
assertThat(resultForQuery("test").size()).isEqualTo(3);
|
||||
|
||||
|
|
@ -199,8 +221,8 @@ public class LuceneSearchTest {
|
|||
|
||||
@Test public void indexNoteNameUpdatedOnNoteSave() throws IOException {
|
||||
//given: total 2 notebooks, 3 paragraphs
|
||||
Note note1 = newNoteWithParapgraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParapgraphs("Notebook2", "not test", "not test at all");
|
||||
Note note1 = newNoteWithParagraph("Notebook1", "test");
|
||||
Note note2 = newNoteWithParagraphs("Notebook2", "not test", "not test at all");
|
||||
notebookIndex.addIndexDocs(Arrays.asList(note1, note2));
|
||||
assertThat(resultForQuery("test").size()).isEqualTo(3);
|
||||
|
||||
|
|
@ -226,17 +248,23 @@ public class LuceneSearchTest {
|
|||
* @param parText text of the paragraph
|
||||
* @return Note
|
||||
*/
|
||||
private Note newNoteWithParapgraph(String noteName, String parText) {
|
||||
private Note newNoteWithParagraph(String noteName, String parText) {
|
||||
Note note1 = newNote(noteName);
|
||||
addParagraphWithText(note1, parText);
|
||||
return note1;
|
||||
}
|
||||
|
||||
private Note newNoteWithParagraph(String noteName, String parText,String title) {
|
||||
Note note = newNote(noteName);
|
||||
addParagraphWithTextAndTitle(note, parText, title);
|
||||
return note;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Note \w given name,
|
||||
* adds N paragraphs \w given texts
|
||||
*/
|
||||
private Note newNoteWithParapgraphs(String noteName, String... parTexts) {
|
||||
private Note newNoteWithParagraphs(String noteName, String... parTexts) {
|
||||
Note note1 = newNote(noteName);
|
||||
for (String parText : parTexts) {
|
||||
addParagraphWithText(note1, parText);
|
||||
|
|
@ -250,6 +278,13 @@ public class LuceneSearchTest {
|
|||
return p;
|
||||
}
|
||||
|
||||
private Paragraph addParagraphWithTextAndTitle(Note note, String text, String title) {
|
||||
Paragraph p = note.addParagraph();
|
||||
p.setText(text);
|
||||
p.setTitle(title);
|
||||
return p;
|
||||
}
|
||||
|
||||
private Note newNote(String name) {
|
||||
Note note = new Note(notebookRepoMock, replLoaderMock, null, notebookIndex);
|
||||
note.setName(name);
|
||||
|
|
|
|||
Loading…
Reference in a new issue