/*
* Copyright 2014 michael-simons.eu.
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ac.simons.autolinker;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Document.OutputSettings.Syntax;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
/**
*
* @author Michael J. Simons
*/
public class AutoLinkServiceTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
static List<Node> makeAutoLinker(final TextNode textNode, final String pattern) {
final String text = textNode.getWholeText();
final String baseUri = textNode.baseUri();
final List<Node> nodes = new ArrayList<>();
final Matcher matcher = Pattern.compile(pattern).matcher(text);
int start = 0;
while (matcher.find()) {
final String textBefore = text.substring(start, matcher.start());
if (!textBefore.isEmpty()) {
nodes.add(new TextNode(textBefore, baseUri));
}
nodes.add(new TextNode("THELINK!", baseUri));
start = matcher.end();
}
final String textAfter = text.substring(start);
if (!textAfter.isEmpty()) {
nodes.add(new TextNode(textAfter, baseUri));
}
return nodes;
}
static List<Node> autoLink1(final TextNode textNode) {
return makeAutoLinker(textNode, "(linkme)");
}
static List<Node> autoLink2(final TextNode textNode) {
return makeAutoLinker(textNode, "(meToo)");
}
@Test
public void applyAutoLinkerShouldWork() {
final AutoLinkService autoLinkService = new AutoLinkService(new ArrayList<>());
Document document;
Document processedDocument;
Element newElement;
String in, expected;
final AutoLinker autolinker = AutoLinkServiceTest::autoLink1;
document = Jsoup.parseBodyFragment("<p>das ist linkme ein test</p>");
newElement = autoLinkService.applyAutoLinker(autolinker, document);
processedDocument = new Document("");
processedDocument.appendChild(newElement);
Assert.assertEquals("<p>das ist THELINK! ein test</p>", processedDocument.body().html().trim());
document = Jsoup.parseBodyFragment("<p></p>");
newElement = autoLinkService.applyAutoLinker(autolinker, document);
processedDocument = new Document("");
processedDocument.appendChild(newElement);
Assert.assertEquals("<p></p>", processedDocument.body().html().trim());
document = Jsoup.parseBodyFragment("<p>Einfach nur so ein Text</p>");
newElement = autoLinkService.applyAutoLinker(autolinker, document);
processedDocument = new Document("");
processedDocument.appendChild(newElement);
Assert.assertEquals("<p>Einfach nur so ein Text</p>", processedDocument.body().html().trim());
document = Jsoup.parseBodyFragment("<p>Einfach nur so ein Text mit einem <a href=\"http://heise.de\">linkme</a>.</p>");
newElement = autoLinkService.applyAutoLinker(autolinker, document);
processedDocument = new Document("");
processedDocument.appendChild(newElement);
Assert.assertEquals("<p>Einfach nur so ein Text mit einem <a href=\"http://heise.de\">linkme</a>.</p>", processedDocument.body().html().trim());
in = "<p>Einfach </p><form><input type=\"text\" /></form><p> nur so ein Text</p>";
expected = in;
document = Jsoup.parseBodyFragment(in);
newElement = autoLinkService.applyAutoLinker(autolinker, document);
processedDocument = new Document("");
processedDocument.appendChild(newElement);
processedDocument.outputSettings().prettyPrint(false).syntax(Syntax.xml);
Assert.assertEquals(expected, processedDocument.body().html().trim());
in = "<p>das <!-- das ist ein kommentar --> ist ein linkme.</p>";
expected = "<p>das <!-- das ist ein kommentar --> ist ein THELINK!.</p>";
document = Jsoup.parseBodyFragment(in);
newElement = autoLinkService.applyAutoLinker(autolinker, document);
processedDocument = new Document("");
processedDocument.appendChild(newElement);
processedDocument.outputSettings().prettyPrint(false).syntax(Syntax.xml);
Assert.assertEquals(expected, processedDocument.body().html().trim());
in = "<p>Einfach </p><form><input type=\"text\" /><div><p>das <!-- das ist ein kommentar --> ist ein linkme.</p></div></form><p> nur so ein Text</p>";
expected = "<p>Einfach </p><form><input type=\"text\" /><div><p>das <!-- das ist ein kommentar --> ist ein THELINK!.</p></div></form><p> nur so ein Text</p>";
document = Jsoup.parseBodyFragment(in);
newElement = autoLinkService.applyAutoLinker(autolinker, document);
processedDocument = new Document("");
processedDocument.appendChild(newElement);
processedDocument.outputSettings().prettyPrint(false).syntax(Syntax.xml);
Assert.assertEquals(expected, processedDocument.body().html().trim());
}
@Test
public void addLinksShouldWork() {
final AutoLinkService autoLinkService = new AutoLinkService(Arrays.asList(AutoLinkServiceTest::autoLink1, AutoLinkServiceTest::autoLink2));
String in, expected;
in = "Einfach nur so ein Text";
expected = in;
Assert.assertEquals(expected, autoLinkService.addLinks(in, Optional.empty()));
in = "Einfach nur linkme so ein Text und meToo.";
expected = "Einfach nur THELINK! so ein Text und THELINK!.";
Assert.assertEquals(expected, autoLinkService.addLinks(in, Optional.empty()));
Assert.assertNull(autoLinkService.addLinks(null, Optional.empty()));
Assert.assertEquals("", autoLinkService.addLinks("", Optional.empty()));
Assert.assertEquals(" ", autoLinkService.addLinks(" ", Optional.empty()));
Assert.assertEquals(" ", autoLinkService.addLinks(" ", Optional.empty()));
}
@Test
public void addLinksShouldWork2() {
expectedException.expect(RuntimeException.class);
expectedException.expectMessage("Invalid target class: java.lang.Integer");
final AutoLinkService autoLinkService = new AutoLinkService(Arrays.asList(AutoLinkServiceTest::autoLink1, AutoLinkServiceTest::autoLink2));
autoLinkService.addLinks(null, Optional.empty(), Integer.class);
}
@Test
public void oldJavaAutolinkerTest() throws IOException {
Properties texts = new Properties();
texts.load(new InputStreamReader(AutoLinkServiceTest.class.getResourceAsStream("/ac/simons/autolinker/testdata.properties"), StandardCharsets.UTF_8));
final Set<String> keys = new TreeSet<>();
for (Object _prop : texts.keySet()) {
String property = (String) _prop;
keys.add(property.substring(0, property.indexOf(".")));
}
final AutoLinkService autoLinkService = new AutoLinkService(Arrays.asList(
new EmailAddressAutoLinker(true, true),
new TwitterUserAutoLinker(),
new UrlAutoLinker(30)
));
int cnt = keys.stream().map((key) -> {
final String in = String.format("%s.in", key.trim());
final String out = String.format("%s.out", key.trim());
String result = autoLinkService.addLinks(texts.getProperty(in), Optional.empty());
Assert.assertEquals("Test " + key + " fails", texts.getProperty(out), result);
return key;
}).map((_item) -> 1).reduce(0, Integer::sum);
Assert.assertTrue(cnt > 0);
}
}