mirror of
https://github.com/Athou/commafeed.git
synced 2026-11-06 04:16:54 +00:00
use 120 max line length for both server and client code (was 100 and 140)
This commit is contained in:
@@ -25,26 +25,14 @@ class NativeImageClassesTest {
|
||||
void annotationContainsAllRequiredRomeClasses() {
|
||||
Reflections reflections = new Reflections("com.rometools");
|
||||
Set<Class<?>> classesInAnnotation =
|
||||
Set.copyOf(
|
||||
List.of(
|
||||
NativeImageClasses.class
|
||||
.getAnnotation(RegisterForReflection.class)
|
||||
.targets()));
|
||||
Set.copyOf(List.of(NativeImageClasses.class.getAnnotation(RegisterForReflection.class).targets()));
|
||||
|
||||
List<Class<?>> missingClasses = new ArrayList<>();
|
||||
for (Class<?> clazz :
|
||||
List.of(
|
||||
Module.class,
|
||||
Cloneable.class,
|
||||
CopyFrom.class,
|
||||
WireFeedParser.class,
|
||||
WireFeedGenerator.class)) {
|
||||
Set<Class<?>> moduleClasses =
|
||||
new HashSet<>(reflections.get(Scanners.SubTypes.of(clazz).asClass()));
|
||||
List.of(Module.class, Cloneable.class, CopyFrom.class, WireFeedParser.class, WireFeedGenerator.class)) {
|
||||
Set<Class<?>> moduleClasses = new HashSet<>(reflections.get(Scanners.SubTypes.of(clazz).asClass()));
|
||||
moduleClasses.removeIf(c ->
|
||||
c.isInterface()
|
||||
|| Modifier.isAbstract(c.getModifiers())
|
||||
|| !Modifier.isPublic(c.getModifiers()));
|
||||
c.isInterface() || Modifier.isAbstract(c.getModifiers()) || !Modifier.isPublic(c.getModifiers()));
|
||||
moduleClasses.removeAll(classesInAnnotation);
|
||||
missingClasses.addAll(moduleClasses);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@ class DigestsTest {
|
||||
|
||||
@Test
|
||||
void sha1Hex() {
|
||||
Assertions.assertEquals(
|
||||
"aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d", Digests.sha1Hex("hello"));
|
||||
Assertions.assertEquals("aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d", Digests.sha1Hex("hello"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -65,9 +65,7 @@ class HttpGetterTest {
|
||||
void init() throws IOException {
|
||||
this.mockServerClient = ClientAndServer.startClientAndServer(0);
|
||||
this.feedUrl = "http://localhost:" + this.mockServerClient.getPort() + "/";
|
||||
this.feedContent =
|
||||
IOUtils.toByteArray(
|
||||
Objects.requireNonNull(getClass().getResource("/feed/rss.xml")));
|
||||
this.feedContent = IOUtils.toByteArray(Objects.requireNonNull(getClass().getResource("/feed/rss.xml")));
|
||||
|
||||
this.config = Mockito.mock(CommaFeedConfiguration.class, Mockito.RETURNS_DEEP_STUBS);
|
||||
Mockito.when(config.httpClient().userAgent()).thenReturn(Optional.of("http-getter-test"));
|
||||
@@ -78,14 +76,12 @@ class HttpGetterTest {
|
||||
Mockito.when(config.httpClient().connectionTimeToLive()).thenReturn(Duration.ofSeconds(30));
|
||||
Mockito.when(config.httpClient().maxResponseSize()).thenReturn(MemorySize.of("10000"));
|
||||
Mockito.when(config.httpClient().cache().enabled()).thenReturn(true);
|
||||
Mockito.when(config.httpClient().cache().maximumMemorySize())
|
||||
.thenReturn(MemorySize.of("100000"));
|
||||
Mockito.when(config.httpClient().cache().maximumMemorySize()).thenReturn(MemorySize.of("100000"));
|
||||
Mockito.when(config.httpClient().cache().expiration()).thenReturn(Duration.ofMinutes(1));
|
||||
Mockito.when(config.feedRefresh().httpThreads()).thenReturn(3);
|
||||
|
||||
this.provider = new HttpClientFactory(config, Mockito.mock(CommaFeedVersion.class));
|
||||
this.getter =
|
||||
new HttpGetter(config, () -> NOW, provider, Mockito.mock(MetricRegistry.class));
|
||||
this.getter = new HttpGetter(config, () -> NOW, provider, Mockito.mock(MetricRegistry.class));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -108,9 +104,7 @@ class HttpGetterTest {
|
||||
.when(HttpRequest.request().withMethod("GET"))
|
||||
.respond(HttpResponse.response().withStatusCode(code));
|
||||
|
||||
HttpResponseException e =
|
||||
Assertions.assertThrows(
|
||||
HttpResponseException.class, () -> getter.get(this.feedUrl));
|
||||
HttpResponseException e = Assertions.assertThrows(HttpResponseException.class, () -> getter.get(this.feedUrl));
|
||||
Assertions.assertEquals(code, e.getCode());
|
||||
}
|
||||
|
||||
@@ -124,8 +118,7 @@ class HttpGetterTest {
|
||||
.withContentType(MediaType.APPLICATION_ATOM_XML)
|
||||
.withHeader(HttpHeaders.LAST_MODIFIED, "123456")
|
||||
.withHeader(HttpHeaders.ETAG, "78910")
|
||||
.withHeader(
|
||||
HttpHeaders.CACHE_CONTROL, "max-age=60, must-revalidate")
|
||||
.withHeader(HttpHeaders.CACHE_CONTROL, "max-age=60, must-revalidate")
|
||||
.withHeader(HttpHeaders.RETRY_AFTER, "120"));
|
||||
|
||||
HttpResult result = getter.get(this.feedUrl);
|
||||
@@ -145,8 +138,7 @@ class HttpGetterTest {
|
||||
HttpResponse.response()
|
||||
.withBody(feedContent)
|
||||
.withContentType(MediaType.APPLICATION_ATOM_XML)
|
||||
.withHeader(
|
||||
HttpHeaders.CACHE_CONTROL, "max-age=60; must-revalidate"));
|
||||
.withHeader(HttpHeaders.CACHE_CONTROL, "max-age=60; must-revalidate"));
|
||||
|
||||
HttpResult result = getter.get(this.feedUrl);
|
||||
Assertions.assertEquals(Duration.ZERO, result.validFor());
|
||||
@@ -162,8 +154,7 @@ class HttpGetterTest {
|
||||
.withHeader(HttpHeaders.RETRY_AFTER, "120"));
|
||||
|
||||
TooManyRequestsException e =
|
||||
Assertions.assertThrows(
|
||||
TooManyRequestsException.class, () -> getter.get(this.feedUrl));
|
||||
Assertions.assertThrows(TooManyRequestsException.class, () -> getter.get(this.feedUrl));
|
||||
Assertions.assertEquals(NOW.plusSeconds(120), e.getRetryAfter());
|
||||
}
|
||||
|
||||
@@ -174,12 +165,10 @@ class HttpGetterTest {
|
||||
.respond(
|
||||
HttpResponse.response()
|
||||
.withStatusCode(HttpStatus.SC_TOO_MANY_REQUESTS)
|
||||
.withHeader(
|
||||
HttpHeaders.RETRY_AFTER, "Wed, 21 Oct 2015 07:28:00 GMT"));
|
||||
.withHeader(HttpHeaders.RETRY_AFTER, "Wed, 21 Oct 2015 07:28:00 GMT"));
|
||||
|
||||
TooManyRequestsException e =
|
||||
Assertions.assertThrows(
|
||||
TooManyRequestsException.class, () -> getter.get(this.feedUrl));
|
||||
Assertions.assertThrows(TooManyRequestsException.class, () -> getter.get(this.feedUrl));
|
||||
Assertions.assertEquals(Instant.parse("2015-10-21T07:28:00Z"), e.getRetryAfter());
|
||||
}
|
||||
|
||||
@@ -200,9 +189,7 @@ class HttpGetterTest {
|
||||
.withStatusCode(code)
|
||||
.withHeader(
|
||||
HttpHeaders.LOCATION,
|
||||
"http://localhost:"
|
||||
+ this.mockServerClient.getPort()
|
||||
+ "/redirected"));
|
||||
"http://localhost:" + this.mockServerClient.getPort() + "/redirected"));
|
||||
|
||||
// second redirect
|
||||
this.mockServerClient
|
||||
@@ -212,29 +199,22 @@ class HttpGetterTest {
|
||||
.withStatusCode(code)
|
||||
.withHeader(
|
||||
HttpHeaders.LOCATION,
|
||||
"http://localhost:"
|
||||
+ this.mockServerClient.getPort()
|
||||
+ "/redirected-2"));
|
||||
"http://localhost:" + this.mockServerClient.getPort() + "/redirected-2"));
|
||||
|
||||
// final destination
|
||||
this.mockServerClient
|
||||
.when(HttpRequest.request().withMethod("GET").withPath("/redirected-2"))
|
||||
.respond(
|
||||
HttpResponse.response()
|
||||
.withBody(feedContent)
|
||||
.withContentType(MediaType.APPLICATION_ATOM_XML));
|
||||
.respond(HttpResponse.response().withBody(feedContent).withContentType(MediaType.APPLICATION_ATOM_XML));
|
||||
|
||||
HttpResult result = getter.get(this.feedUrl);
|
||||
Assertions.assertEquals(
|
||||
"http://localhost:" + this.mockServerClient.getPort() + "/redirected-2",
|
||||
result.urlAfterRedirect());
|
||||
"http://localhost:" + this.mockServerClient.getPort() + "/redirected-2", result.urlAfterRedirect());
|
||||
}
|
||||
|
||||
@Test
|
||||
void dataTimeout() {
|
||||
Mockito.when(config.httpClient().responseTimeout()).thenReturn(Duration.ofMillis(500));
|
||||
this.getter =
|
||||
new HttpGetter(config, () -> NOW, provider, Mockito.mock(MetricRegistry.class));
|
||||
this.getter = new HttpGetter(config, () -> NOW, provider, Mockito.mock(MetricRegistry.class));
|
||||
|
||||
this.mockServerClient
|
||||
.when(HttpRequest.request().withMethod("GET"))
|
||||
@@ -246,29 +226,23 @@ class HttpGetterTest {
|
||||
@Test
|
||||
void connectTimeout() {
|
||||
Mockito.when(config.httpClient().connectTimeout()).thenReturn(Duration.ofMillis(500));
|
||||
this.getter =
|
||||
new HttpGetter(config, () -> NOW, provider, Mockito.mock(MetricRegistry.class));
|
||||
this.getter = new HttpGetter(config, () -> NOW, provider, Mockito.mock(MetricRegistry.class));
|
||||
// try to connect to a non-routable address
|
||||
// https://stackoverflow.com/a/904609
|
||||
Exception e =
|
||||
Assertions.assertThrows(Exception.class, () -> getter.get("http://10.255.255.1"));
|
||||
Exception e = Assertions.assertThrows(Exception.class, () -> getter.get("http://10.255.255.1"));
|
||||
Assertions.assertTrue(
|
||||
e instanceof ConnectTimeoutException
|
||||
// A NoRouteToHostException can also be thrown in some cases
|
||||
// depending on the underlying network configuration
|
||||
// https://github.com/Athou/commafeed/issues/1876
|
||||
|| e instanceof NoRouteToHostException,
|
||||
"Expected ConnectTimeoutException or NoRouteToHostException, but got: "
|
||||
+ e.getClass().getName());
|
||||
"Expected ConnectTimeoutException or NoRouteToHostException, but got: " + e.getClass().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void userAgent() throws Exception {
|
||||
this.mockServerClient
|
||||
.when(
|
||||
HttpRequest.request()
|
||||
.withMethod("GET")
|
||||
.withHeader(HttpHeaders.USER_AGENT, "http-getter-test"))
|
||||
.when(HttpRequest.request().withMethod("GET").withHeader(HttpHeaders.USER_AGENT, "http-getter-test"))
|
||||
.respond(HttpResponse.response().withBody("ok"));
|
||||
|
||||
HttpResult result = getter.get(this.feedUrl);
|
||||
@@ -278,37 +252,23 @@ class HttpGetterTest {
|
||||
@Test
|
||||
void lastModifiedReturns304() {
|
||||
this.mockServerClient
|
||||
.when(
|
||||
HttpRequest.request()
|
||||
.withMethod("GET")
|
||||
.withHeader(HttpHeaders.IF_MODIFIED_SINCE, "123456"))
|
||||
.when(HttpRequest.request().withMethod("GET").withHeader(HttpHeaders.IF_MODIFIED_SINCE, "123456"))
|
||||
.respond(HttpResponse.response().withStatusCode(HttpStatus.SC_NOT_MODIFIED));
|
||||
|
||||
Assertions.assertThrows(
|
||||
NotModifiedException.class,
|
||||
() ->
|
||||
getter.get(
|
||||
HttpGetter.HttpRequest.builder(this.feedUrl)
|
||||
.lastModified("123456")
|
||||
.build()));
|
||||
() -> getter.get(HttpGetter.HttpRequest.builder(this.feedUrl).lastModified("123456").build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void eTagReturns304() {
|
||||
this.mockServerClient
|
||||
.when(
|
||||
HttpRequest.request()
|
||||
.withMethod("GET")
|
||||
.withHeader(HttpHeaders.IF_NONE_MATCH, "78910"))
|
||||
.when(HttpRequest.request().withMethod("GET").withHeader(HttpHeaders.IF_NONE_MATCH, "78910"))
|
||||
.respond(HttpResponse.response().withStatusCode(HttpStatus.SC_NOT_MODIFIED));
|
||||
|
||||
Assertions.assertThrows(
|
||||
NotModifiedException.class,
|
||||
() ->
|
||||
getter.get(
|
||||
HttpGetter.HttpRequest.builder(this.feedUrl)
|
||||
.eTag("78910")
|
||||
.build()));
|
||||
() -> getter.get(HttpGetter.HttpRequest.builder(this.feedUrl).eTag("78910").build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -324,9 +284,7 @@ class HttpGetterTest {
|
||||
throw new Exception("cookie should not be sent by the client");
|
||||
}
|
||||
|
||||
return HttpResponse.response()
|
||||
.withBody("ok")
|
||||
.withHeader(HttpHeaders.SET_COOKIE, "foo=bar");
|
||||
return HttpResponse.response().withBody("ok").withHeader(HttpHeaders.SET_COOKIE, "foo=bar");
|
||||
});
|
||||
|
||||
Assertions.assertDoesNotThrow(() -> getter.get(this.feedUrl));
|
||||
@@ -360,8 +318,7 @@ class HttpGetterTest {
|
||||
|
||||
IOException e = Assertions.assertThrows(IOException.class, () -> getter.get(this.feedUrl));
|
||||
Assertions.assertEquals(
|
||||
"Response size (100000 bytes) exceeds the maximum allowed size (10000 bytes)",
|
||||
e.getMessage());
|
||||
"Response size (100000 bytes) exceeds the maximum allowed size (10000 bytes)", e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -374,12 +331,10 @@ class HttpGetterTest {
|
||||
HttpResponse.response()
|
||||
.withBody(bytes)
|
||||
.withConnectionOptions(
|
||||
ConnectionOptions.connectionOptions()
|
||||
.withSuppressContentLengthHeader(true)));
|
||||
ConnectionOptions.connectionOptions().withSuppressContentLengthHeader(true)));
|
||||
|
||||
IOException e = Assertions.assertThrows(IOException.class, () -> getter.get(this.feedUrl));
|
||||
Assertions.assertEquals(
|
||||
"Response size exceeds the maximum allowed size (10000 bytes)", e.getMessage());
|
||||
Assertions.assertEquals("Response size exceeds the maximum allowed size (10000 bytes)", e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -427,8 +382,7 @@ class HttpGetterTest {
|
||||
supportsCompression("deflate", DeflaterOutputStream::new);
|
||||
}
|
||||
|
||||
void supportsCompression(String encoding, CompressionFunction compressionFunction)
|
||||
throws Exception {
|
||||
void supportsCompression(String encoding, CompressionFunction compressionFunction) throws Exception {
|
||||
String body = "my body";
|
||||
|
||||
HttpGetterTest.this
|
||||
@@ -436,8 +390,7 @@ class HttpGetterTest {
|
||||
.when(HttpRequest.request().withMethod("GET"))
|
||||
.respond(req -> {
|
||||
try {
|
||||
String acceptEncodingHeader =
|
||||
req.getFirstHeader(HttpHeaders.ACCEPT_ENCODING);
|
||||
String acceptEncodingHeader = req.getFirstHeader(HttpHeaders.ACCEPT_ENCODING);
|
||||
if (!ACCEPT_ENCODING.equals(acceptEncodingHeader)) {
|
||||
throw new Exception(
|
||||
"Wrong value in the Accept-Encoding header, should be '%s' but was '%s'"
|
||||
@@ -445,8 +398,7 @@ class HttpGetterTest {
|
||||
}
|
||||
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
try (OutputStream compressionOutputStream =
|
||||
compressionFunction.apply(output)) {
|
||||
try (OutputStream compressionOutputStream = compressionFunction.apply(output)) {
|
||||
compressionOutputStream.write(body.getBytes());
|
||||
}
|
||||
|
||||
@@ -473,16 +425,12 @@ class HttpGetterTest {
|
||||
class SchemeNotAllowed {
|
||||
@Test
|
||||
void file() {
|
||||
Assertions.assertThrows(
|
||||
HttpGetter.SchemeNotAllowedException.class,
|
||||
() -> getter.get("file://localhost"));
|
||||
Assertions.assertThrows(HttpGetter.SchemeNotAllowedException.class, () -> getter.get("file://localhost"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void ftp() {
|
||||
Assertions.assertThrows(
|
||||
HttpGetter.SchemeNotAllowedException.class,
|
||||
() -> getter.get("ftp://localhost"));
|
||||
Assertions.assertThrows(HttpGetter.SchemeNotAllowedException.class, () -> getter.get("ftp://localhost"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,20 +440,15 @@ class HttpGetterTest {
|
||||
@BeforeEach
|
||||
void init() {
|
||||
Mockito.when(config.httpClient().blockLocalAddresses()).thenReturn(true);
|
||||
getter =
|
||||
new HttpGetter(config, () -> NOW, provider, Mockito.mock(MetricRegistry.class));
|
||||
getter = new HttpGetter(config, () -> NOW, provider, Mockito.mock(MetricRegistry.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void localhost() {
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://localhost"));
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://127.0.0.1"));
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://2130706433"));
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://0x7F.0x00.0x00.0X01"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://localhost"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://127.0.0.1"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://2130706433"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://0x7F.0x00.0x00.0X01"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -515,72 +458,54 @@ class HttpGetterTest {
|
||||
|
||||
@Test
|
||||
void linkLocal() {
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://169.254.12.34"));
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://169.254.169.254"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://169.254.12.34"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://169.254.169.254"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void multicast() {
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://224.2.3.4"));
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://239.255.255.254"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://224.2.3.4"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://239.255.255.254"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void privateIpv4Ranges() {
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://10.0.0.1"));
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://172.16.0.1"));
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://192.168.0.1"));
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://100.64.0.1"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://10.0.0.1"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://172.16.0.1"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://192.168.0.1"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://100.64.0.1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void privateIpv6Ranges() {
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class,
|
||||
() -> getter.get("http://[fe80::215:5dff:fe15:102]"));
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://[fd00:dead:beef::50]"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://[fe80::215:5dff:fe15:102]"));
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://[fd00:dead:beef::50]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void nat64() {
|
||||
// 64:ff9b::/96 embeds the IPv4 address in the lower 32 bits (RFC 6052)
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class,
|
||||
() -> getter.get("http://[64:ff9b::a9fe:a9fe]")); // 169.254.169.254
|
||||
UnknownHostException.class, () -> getter.get("http://[64:ff9b::a9fe:a9fe]")); // 169.254.169.254
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class,
|
||||
() -> getter.get("http://[64:ff9b::a00:1]")); // 10.0.0.1
|
||||
UnknownHostException.class, () -> getter.get("http://[64:ff9b::a00:1]")); // 10.0.0.1
|
||||
}
|
||||
|
||||
@Test
|
||||
void nat64LocalUse() {
|
||||
// 64:ff9b:1::/48 is reserved for local use (RFC 8215), the whole range is blocked
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class,
|
||||
() -> getter.get("http://[64:ff9b:1::a9fe:a9fe]")); // 169.254.169.254
|
||||
UnknownHostException.class, () -> getter.get("http://[64:ff9b:1::a9fe:a9fe]")); // 169.254.169.254
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class,
|
||||
() -> getter.get("http://[64:ff9b:1:ffff::a00:1]")); // 10.0.0.1
|
||||
UnknownHostException.class, () -> getter.get("http://[64:ff9b:1:ffff::a00:1]")); // 10.0.0.1
|
||||
}
|
||||
|
||||
@Test
|
||||
void sixToFour() {
|
||||
// 2002::/16 embeds the IPv4 address in bits 16-47 (RFC 3056)
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class,
|
||||
() -> getter.get("http://[2002:a9fe:a9fe::]")); // 169.254.169.254
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class,
|
||||
() -> getter.get("http://[2002:a00:1::]")); // 10.0.0.1
|
||||
UnknownHostException.class, () -> getter.get("http://[2002:a9fe:a9fe::]")); // 169.254.169.254
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://[2002:a00:1::]")); // 10.0.0.1
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -597,10 +522,8 @@ class HttpGetterTest {
|
||||
// deprecated ::/96 IPv4-compatible addresses embed the IPv4 address in the lower 32
|
||||
// bits
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class,
|
||||
() -> getter.get("http://[::a9fe:a9fe]")); // 169.254.169.254
|
||||
Assertions.assertThrows(
|
||||
UnknownHostException.class, () -> getter.get("http://[::a00:1]")); // 10.0.0.1
|
||||
UnknownHostException.class, () -> getter.get("http://[::a9fe:a9fe]")); // 169.254.169.254
|
||||
Assertions.assertThrows(UnknownHostException.class, () -> getter.get("http://[::a00:1]")); // 10.0.0.1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,25 +50,17 @@ class UrlsTest {
|
||||
|
||||
// usual cases
|
||||
Assertions.assertEquals(
|
||||
expected,
|
||||
Urls.toAbsolute(
|
||||
"http://a.com/blog/entry/1", "http://a.com/feed/", "http://a.com/feed/"));
|
||||
expected, Urls.toAbsolute("http://a.com/blog/entry/1", "http://a.com/feed/", "http://a.com/feed/"));
|
||||
Assertions.assertEquals(
|
||||
expected,
|
||||
Urls.toAbsolute(
|
||||
"http://a.com/blog/entry/1", "http://a.com/feed", "http://a.com/feed"));
|
||||
expected, Urls.toAbsolute("http://a.com/blog/entry/1", "http://a.com/feed", "http://a.com/feed"));
|
||||
|
||||
// relative links
|
||||
Assertions.assertEquals(
|
||||
expected,
|
||||
Urls.toAbsolute("../blog/entry/1", "http://a.com/feed/", "http://a.com/feed/"));
|
||||
Assertions.assertEquals(
|
||||
expected,
|
||||
Urls.toAbsolute("../blog/entry/1", "feed.xml", "http://a.com/feed/feed.xml"));
|
||||
expected, Urls.toAbsolute("../blog/entry/1", "http://a.com/feed/", "http://a.com/feed/"));
|
||||
Assertions.assertEquals(expected, Urls.toAbsolute("../blog/entry/1", "feed.xml", "http://a.com/feed/feed.xml"));
|
||||
|
||||
// root-relative links
|
||||
Assertions.assertEquals(
|
||||
expected, Urls.toAbsolute("/blog/entry/1", "/feed", "http://a.com/feed"));
|
||||
Assertions.assertEquals(expected, Urls.toAbsolute("/blog/entry/1", "/feed", "http://a.com/feed"));
|
||||
|
||||
// real cases
|
||||
Assertions.assertEquals(
|
||||
@@ -79,10 +71,7 @@ class UrlsTest {
|
||||
"https://github.com/erusev/parsedown/tags.atom"));
|
||||
Assertions.assertEquals(
|
||||
"http://ergoemacs.org/emacs/elisp_all_about_lines.html",
|
||||
Urls.toAbsolute(
|
||||
"elisp_all_about_lines.html",
|
||||
"blog.xml",
|
||||
"http://ergoemacs.org/emacs/blog.xml"));
|
||||
Urls.toAbsolute("elisp_all_about_lines.html", "blog.xml", "http://ergoemacs.org/emacs/blog.xml"));
|
||||
|
||||
// invalid relative urls
|
||||
Assertions.assertEquals(
|
||||
@@ -97,13 +86,11 @@ class UrlsTest {
|
||||
void testSanitize() {
|
||||
// valid http/https urls are kept as is
|
||||
Assertions.assertEquals("http://example.com/foo", Urls.sanitize("http://example.com/foo"));
|
||||
Assertions.assertEquals(
|
||||
"https://example.com/foo", Urls.sanitize("https://example.com/foo"));
|
||||
Assertions.assertEquals("https://example.com/foo", Urls.sanitize("https://example.com/foo"));
|
||||
|
||||
// scheme matching is case-insensitive
|
||||
Assertions.assertEquals("HTTP://example.com/foo", Urls.sanitize("HTTP://example.com/foo"));
|
||||
Assertions.assertEquals(
|
||||
"HTTPS://example.com/foo", Urls.sanitize("HTTPS://example.com/foo"));
|
||||
Assertions.assertEquals("HTTPS://example.com/foo", Urls.sanitize("HTTPS://example.com/foo"));
|
||||
|
||||
// malicious or disallowed schemes are stripped
|
||||
Assertions.assertNull(Urls.sanitize("javascript:alert(1)"));
|
||||
|
||||
@@ -36,11 +36,8 @@ class FacebookFaviconFetcherTest {
|
||||
byte[] iconBytes = new byte[1000];
|
||||
String contentType = "image/png";
|
||||
|
||||
HttpResult httpResult =
|
||||
new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
Mockito.when(
|
||||
httpGetter.get(
|
||||
"https://graph.facebook.com/validUserId/picture?type=square&height=16"))
|
||||
HttpResult httpResult = new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://graph.facebook.com/validUserId/picture?type=square&height=16"))
|
||||
.thenReturn(httpResult);
|
||||
|
||||
Favicon result = faviconFetcher.fetch(feed);
|
||||
@@ -73,9 +70,7 @@ class FacebookFaviconFetcherTest {
|
||||
Feed feed = new Feed();
|
||||
feed.setUrl("https://www.facebook.com/something?id=validUserId");
|
||||
|
||||
Mockito.when(
|
||||
httpGetter.get(
|
||||
"https://graph.facebook.com/validUserId/picture?type=square&height=16"))
|
||||
Mockito.when(httpGetter.get("https://graph.facebook.com/validUserId/picture?type=square&height=16"))
|
||||
.thenThrow(new RuntimeException("Network error"));
|
||||
|
||||
Assertions.assertNull(faviconFetcher.fetch(feed));
|
||||
|
||||
@@ -45,8 +45,7 @@ class FeedFaviconFetcherTest {
|
||||
|
||||
byte[] iconBytes = new byte[1000];
|
||||
String contentType = "image/png";
|
||||
HttpResult httpResult =
|
||||
new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
HttpResult httpResult = new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://example.com/icon.png")).thenReturn(httpResult);
|
||||
|
||||
Favicon result = faviconFetcher.fetch(feed);
|
||||
@@ -62,8 +61,7 @@ class FeedFaviconFetcherTest {
|
||||
feed.setUrl("https://example.com/feed");
|
||||
feed.setIconUrl("https://example.com/icon.png");
|
||||
|
||||
Mockito.when(httpGetter.get("https://example.com/icon.png"))
|
||||
.thenThrow(new RuntimeException("Network error"));
|
||||
Mockito.when(httpGetter.get("https://example.com/icon.png")).thenThrow(new RuntimeException("Network error"));
|
||||
|
||||
Assertions.assertNull(faviconFetcher.fetch(feed));
|
||||
}
|
||||
|
||||
@@ -43,16 +43,13 @@ class HtmlFaviconFetcherTest {
|
||||
feed.setUrl("https://example.com/feed");
|
||||
feed.setLink("https://example.com");
|
||||
|
||||
String html =
|
||||
"<html><head><link rel=\"icon\" href=\"/favicon.png\" /></head><body></body></html>";
|
||||
HttpResult pageResult =
|
||||
new HttpResult(html.getBytes(), "text/html", null, null, null, Duration.ZERO);
|
||||
String html = "<html><head><link rel=\"icon\" href=\"/favicon.png\" /></head><body></body></html>";
|
||||
HttpResult pageResult = new HttpResult(html.getBytes(), "text/html", null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://example.com")).thenReturn(pageResult);
|
||||
|
||||
byte[] iconBytes = new byte[1000];
|
||||
String contentType = "image/png";
|
||||
HttpResult iconResult =
|
||||
new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
HttpResult iconResult = new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://example.com/favicon.png")).thenReturn(iconResult);
|
||||
|
||||
Favicon result = faviconFetcher.fetch(feed);
|
||||
@@ -70,16 +67,13 @@ class HtmlFaviconFetcherTest {
|
||||
|
||||
String html =
|
||||
"<html><head><link rel=\"shortcut icon\" href=\"https://example.com/shortcut-favicon.ico\" /></head><body></body></html>";
|
||||
HttpResult pageResult =
|
||||
new HttpResult(html.getBytes(), "text/html", null, null, null, Duration.ZERO);
|
||||
HttpResult pageResult = new HttpResult(html.getBytes(), "text/html", null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://example.com")).thenReturn(pageResult);
|
||||
|
||||
byte[] iconBytes = new byte[1000];
|
||||
String contentType = "image/x-icon";
|
||||
HttpResult iconResult =
|
||||
new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://example.com/shortcut-favicon.ico"))
|
||||
.thenReturn(iconResult);
|
||||
HttpResult iconResult = new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://example.com/shortcut-favicon.ico")).thenReturn(iconResult);
|
||||
|
||||
Favicon result = faviconFetcher.fetch(feed);
|
||||
|
||||
@@ -95,8 +89,7 @@ class HtmlFaviconFetcherTest {
|
||||
feed.setLink("https://example.com");
|
||||
|
||||
String html = "<html><head></head><body></body></html>";
|
||||
HttpResult pageResult =
|
||||
new HttpResult(html.getBytes(), "text/html", null, null, null, Duration.ZERO);
|
||||
HttpResult pageResult = new HttpResult(html.getBytes(), "text/html", null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://example.com")).thenReturn(pageResult);
|
||||
|
||||
Assertions.assertNull(faviconFetcher.fetch(feed));
|
||||
@@ -108,8 +101,7 @@ class HtmlFaviconFetcherTest {
|
||||
feed.setUrl("https://example.com/feed");
|
||||
feed.setLink("https://example.com");
|
||||
|
||||
Mockito.when(httpGetter.get("https://example.com"))
|
||||
.thenThrow(new RuntimeException("Network error"));
|
||||
Mockito.when(httpGetter.get("https://example.com")).thenThrow(new RuntimeException("Network error"));
|
||||
|
||||
Assertions.assertNull(faviconFetcher.fetch(feed));
|
||||
}
|
||||
@@ -122,8 +114,7 @@ class HtmlFaviconFetcherTest {
|
||||
|
||||
String html =
|
||||
"<html><head><link rel=\"icon\" href=\"https://example.com/favicon.png\" /></head><body></body></html>";
|
||||
HttpResult pageResult =
|
||||
new HttpResult(html.getBytes(), "text/html", null, null, null, Duration.ZERO);
|
||||
HttpResult pageResult = new HttpResult(html.getBytes(), "text/html", null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://example.com")).thenReturn(pageResult);
|
||||
Mockito.when(httpGetter.get("https://example.com/favicon.png"))
|
||||
.thenThrow(new RuntimeException("Network error"));
|
||||
|
||||
@@ -36,8 +36,7 @@ class RootFaviconFetcherTest {
|
||||
|
||||
byte[] iconBytes = new byte[1000];
|
||||
String contentType = "image/x-icon";
|
||||
HttpResult httpResult =
|
||||
new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
HttpResult httpResult = new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://www.example.com/favicon.ico")).thenReturn(httpResult);
|
||||
|
||||
Favicon result = faviconFetcher.fetch(feed);
|
||||
@@ -55,10 +54,8 @@ class RootFaviconFetcherTest {
|
||||
|
||||
byte[] iconBytes = new byte[1000];
|
||||
String contentType = "image/x-icon";
|
||||
HttpResult httpResult =
|
||||
new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://www.example.com:8000/favicon.ico"))
|
||||
.thenReturn(httpResult);
|
||||
HttpResult httpResult = new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://www.example.com:8000/favicon.ico")).thenReturn(httpResult);
|
||||
|
||||
Favicon result = faviconFetcher.fetch(feed);
|
||||
|
||||
@@ -74,8 +71,7 @@ class RootFaviconFetcherTest {
|
||||
|
||||
byte[] iconBytes = new byte[1000];
|
||||
String contentType = "image/x-icon";
|
||||
HttpResult httpResult =
|
||||
new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
HttpResult httpResult = new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://example.com/favicon.ico")).thenReturn(httpResult);
|
||||
|
||||
Favicon result = faviconFetcher.fetch(feed);
|
||||
|
||||
@@ -71,8 +71,7 @@ class YoutubeFaviconFetcherTest {
|
||||
{"items":[{"snippet":{"thumbnails":{"default":{"url":"https://example.com/icon.png"}}}}]}\
|
||||
"""
|
||||
.getBytes();
|
||||
HttpResult apiHttpResult =
|
||||
new HttpResult(apiResponse, "application/json", null, null, null, Duration.ZERO);
|
||||
HttpResult apiHttpResult = new HttpResult(apiResponse, "application/json", null, null, null, Duration.ZERO);
|
||||
Mockito.when(
|
||||
httpGetter.get(
|
||||
"https://www.googleapis.com/youtube/v3/channels?part=snippet&key=test-api-key&forUsername=testUser"))
|
||||
@@ -83,8 +82,7 @@ class YoutubeFaviconFetcherTest {
|
||||
|
||||
byte[] iconBytes = new byte[1000];
|
||||
String contentType = "image/png";
|
||||
HttpResult iconHttpResult =
|
||||
new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
HttpResult iconHttpResult = new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://example.com/icon.png")).thenReturn(iconHttpResult);
|
||||
|
||||
Favicon result = faviconFetcher.fetch(feed);
|
||||
@@ -106,8 +104,7 @@ class YoutubeFaviconFetcherTest {
|
||||
{"items":[{"snippet":{"thumbnails":{"default":{"url":"https://example.com/icon.png"}}}}]}\
|
||||
"""
|
||||
.getBytes();
|
||||
HttpResult apiHttpResult =
|
||||
new HttpResult(apiResponse, "application/json", null, null, null, Duration.ZERO);
|
||||
HttpResult apiHttpResult = new HttpResult(apiResponse, "application/json", null, null, null, Duration.ZERO);
|
||||
Mockito.when(
|
||||
httpGetter.get(
|
||||
"https://www.googleapis.com/youtube/v3/channels?part=snippet&key=test-api-key&id=testChannelId"))
|
||||
@@ -118,8 +115,7 @@ class YoutubeFaviconFetcherTest {
|
||||
|
||||
byte[] iconBytes = new byte[1000];
|
||||
String contentType = "image/png";
|
||||
HttpResult iconHttpResult =
|
||||
new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
HttpResult iconHttpResult = new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://example.com/icon.png")).thenReturn(iconHttpResult);
|
||||
|
||||
Favicon result = faviconFetcher.fetch(feed);
|
||||
@@ -142,8 +138,7 @@ class YoutubeFaviconFetcherTest {
|
||||
"""
|
||||
.getBytes();
|
||||
HttpResult playlistHttpResult =
|
||||
new HttpResult(
|
||||
playlistResponse, "application/json", null, null, null, Duration.ZERO);
|
||||
new HttpResult(playlistResponse, "application/json", null, null, null, Duration.ZERO);
|
||||
Mockito.when(
|
||||
httpGetter.get(
|
||||
"https://www.googleapis.com/youtube/v3/playlists?part=snippet&key=test-api-key&id=testPlaylistId"))
|
||||
@@ -158,8 +153,7 @@ class YoutubeFaviconFetcherTest {
|
||||
"""
|
||||
.getBytes();
|
||||
HttpResult channelHttpResult =
|
||||
new HttpResult(
|
||||
channelResponse, "application/json", null, null, null, Duration.ZERO);
|
||||
new HttpResult(channelResponse, "application/json", null, null, null, Duration.ZERO);
|
||||
Mockito.when(
|
||||
httpGetter.get(
|
||||
"https://www.googleapis.com/youtube/v3/channels?part=snippet&key=test-api-key&id=testChannelId"))
|
||||
@@ -170,8 +164,7 @@ class YoutubeFaviconFetcherTest {
|
||||
|
||||
byte[] iconBytes = new byte[1000];
|
||||
String contentType = "image/png";
|
||||
HttpResult iconHttpResult =
|
||||
new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
HttpResult iconHttpResult = new HttpResult(iconBytes, contentType, null, null, null, Duration.ZERO);
|
||||
Mockito.when(httpGetter.get("https://example.com/icon.png")).thenReturn(iconHttpResult);
|
||||
|
||||
Favicon result = faviconFetcher.fetch(feed);
|
||||
@@ -204,8 +197,7 @@ class YoutubeFaviconFetcherTest {
|
||||
Mockito.when(config.googleAuthKey()).thenReturn(Optional.of("test-api-key"));
|
||||
|
||||
byte[] apiResponse = "{}".getBytes();
|
||||
HttpResult apiHttpResult =
|
||||
new HttpResult(apiResponse, "application/json", null, null, null, Duration.ZERO);
|
||||
HttpResult apiHttpResult = new HttpResult(apiResponse, "application/json", null, null, null, Duration.ZERO);
|
||||
Mockito.when(
|
||||
httpGetter.get(
|
||||
"https://www.googleapis.com/youtube/v3/channels?part=snippet&key=test-api-key&forUsername=testUser"))
|
||||
|
||||
@@ -44,18 +44,14 @@ class FeedFetcherTest {
|
||||
byte[] html = "html".getBytes();
|
||||
Mockito.when(getter.get(HttpGetter.HttpRequest.builder(htmlUrl).build()))
|
||||
.thenReturn(new HttpResult(html, "text/html", null, null, htmlUrl, Duration.ZERO));
|
||||
Mockito.when(parser.parse(htmlUrl, html))
|
||||
.thenThrow(new FeedParsingException("invalid feed"));
|
||||
Mockito.when(parser.parse(htmlUrl, html)).thenThrow(new FeedParsingException("invalid feed"));
|
||||
|
||||
String feedUrl = "https://bbb.com/feed";
|
||||
byte[] feed = "feed".getBytes();
|
||||
Mockito.when(getter.get(HttpGetter.HttpRequest.builder(feedUrl).build()))
|
||||
.thenReturn(
|
||||
new HttpResult(
|
||||
feed, "application/atom+xml", null, null, feedUrl, Duration.ZERO));
|
||||
.thenReturn(new HttpResult(feed, "application/atom+xml", null, null, feedUrl, Duration.ZERO));
|
||||
Mockito.when(parser.parse(feedUrl, feed))
|
||||
.thenReturn(
|
||||
new FeedParserResult("title", "link", "iconUrl", null, null, null, null));
|
||||
.thenReturn(new FeedParserResult("title", "link", "iconUrl", null, null, null, null));
|
||||
|
||||
Mockito.when(urlProvider.get(htmlUrl, new String(html))).thenReturn(List.of(feedUrl));
|
||||
|
||||
@@ -71,32 +67,13 @@ class FeedFetcherTest {
|
||||
byte[] content = "content".getBytes();
|
||||
String lastContentHash = Digests.sha1Hex(content);
|
||||
|
||||
Mockito.when(
|
||||
getter.get(
|
||||
HttpGetter.HttpRequest.builder(url)
|
||||
.lastModified(lastModified)
|
||||
.eTag(etag)
|
||||
.build()))
|
||||
.thenReturn(
|
||||
new HttpResult(
|
||||
content,
|
||||
"content-type",
|
||||
"last-modified-2",
|
||||
"etag-2",
|
||||
null,
|
||||
Duration.ZERO));
|
||||
Mockito.when(getter.get(HttpGetter.HttpRequest.builder(url).lastModified(lastModified).eTag(etag).build()))
|
||||
.thenReturn(new HttpResult(content, "content-type", "last-modified-2", "etag-2", null, Duration.ZERO));
|
||||
|
||||
NotModifiedException e =
|
||||
Assertions.assertThrows(
|
||||
NotModifiedException.class,
|
||||
() ->
|
||||
fetcher.fetch(
|
||||
url,
|
||||
false,
|
||||
lastModified,
|
||||
etag,
|
||||
Instant.now(),
|
||||
lastContentHash));
|
||||
() -> fetcher.fetch(url, false, lastModified, etag, Instant.now(), lastContentHash));
|
||||
|
||||
Assertions.assertEquals("last-modified-2", e.getNewLastModifiedHeader());
|
||||
Assertions.assertEquals("etag-2", e.getNewEtagHeader());
|
||||
|
||||
@@ -36,8 +36,7 @@ class FeedRefreshIntervalCalculatorTest {
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
Mockito.when(instantSource.instant()).thenReturn(NOW);
|
||||
Mockito.when(config.feedRefresh())
|
||||
.thenReturn(Mockito.mock(CommaFeedConfiguration.FeedRefresh.class));
|
||||
Mockito.when(config.feedRefresh()).thenReturn(Mockito.mock(CommaFeedConfiguration.FeedRefresh.class));
|
||||
Mockito.when(config.feedRefresh().interval()).thenReturn(DEFAULT_INTERVAL);
|
||||
Mockito.when(config.feedRefresh().maxInterval()).thenReturn(MAX_INTERVAL);
|
||||
Mockito.when(config.feedRefresh().errors()).thenReturn(errorHandling);
|
||||
@@ -55,24 +54,20 @@ class FeedRefreshIntervalCalculatorTest {
|
||||
void withoutValidFor(long averageEntryInterval) {
|
||||
// averageEntryInterval is ignored when empirical is disabled
|
||||
Instant result =
|
||||
calculator.onFetchSuccess(
|
||||
NOW.minus(Duration.ofDays(5)), averageEntryInterval, Duration.ZERO);
|
||||
calculator.onFetchSuccess(NOW.minus(Duration.ofDays(5)), averageEntryInterval, Duration.ZERO);
|
||||
Assertions.assertEquals(NOW.plus(DEFAULT_INTERVAL), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void withValidForGreaterThanMaxInterval() {
|
||||
Instant result =
|
||||
calculator.onFetchSuccess(
|
||||
NOW.minus(Duration.ofDays(5)), 1L, MAX_INTERVAL.plusDays(1));
|
||||
Instant result = calculator.onFetchSuccess(NOW.minus(Duration.ofDays(5)), 1L, MAX_INTERVAL.plusDays(1));
|
||||
Assertions.assertEquals(NOW.plus(MAX_INTERVAL), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void withValidForLowerThanMaxInterval() {
|
||||
Instant result =
|
||||
calculator.onFetchSuccess(
|
||||
NOW.minus(Duration.ofDays(5)), 1L, MAX_INTERVAL.minusSeconds(1));
|
||||
calculator.onFetchSuccess(NOW.minus(Duration.ofDays(5)), 1L, MAX_INTERVAL.minusSeconds(1));
|
||||
Assertions.assertEquals(NOW.plus(MAX_INTERVAL).minusSeconds(1), result);
|
||||
}
|
||||
}
|
||||
@@ -93,24 +88,19 @@ class FeedRefreshIntervalCalculatorTest {
|
||||
|
||||
@Test
|
||||
void with31DaysOldPublishedDate() {
|
||||
Instant result =
|
||||
calculator.onFetchSuccess(
|
||||
NOW.minus(Duration.ofDays(31)), 1L, Duration.ZERO);
|
||||
Instant result = calculator.onFetchSuccess(NOW.minus(Duration.ofDays(31)), 1L, Duration.ZERO);
|
||||
Assertions.assertEquals(NOW.plus(MAX_INTERVAL), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void with15DaysOldPublishedDate() {
|
||||
Instant result =
|
||||
calculator.onFetchSuccess(
|
||||
NOW.minus(Duration.ofDays(15)), 1L, Duration.ZERO);
|
||||
Instant result = calculator.onFetchSuccess(NOW.minus(Duration.ofDays(15)), 1L, Duration.ZERO);
|
||||
Assertions.assertEquals(NOW.plus(MAX_INTERVAL.dividedBy(2)), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void with8DaysOldPublishedDate() {
|
||||
Instant result =
|
||||
calculator.onFetchSuccess(NOW.minus(Duration.ofDays(8)), 1L, Duration.ZERO);
|
||||
Instant result = calculator.onFetchSuccess(NOW.minus(Duration.ofDays(8)), 1L, Duration.ZERO);
|
||||
Assertions.assertEquals(NOW.plus(MAX_INTERVAL.dividedBy(4)), result);
|
||||
}
|
||||
|
||||
@@ -120,33 +110,26 @@ class FeedRefreshIntervalCalculatorTest {
|
||||
void averageBetweenBounds() {
|
||||
Instant result =
|
||||
calculator.onFetchSuccess(
|
||||
NOW.minus(Duration.ofDays(5)),
|
||||
Duration.ofHours(4).toMillis(),
|
||||
Duration.ZERO);
|
||||
NOW.minus(Duration.ofDays(5)), Duration.ofHours(4).toMillis(), Duration.ZERO);
|
||||
Assertions.assertEquals(NOW.plus(Duration.ofHours(2)), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void averageBelowMinimum() {
|
||||
Instant result =
|
||||
calculator.onFetchSuccess(
|
||||
NOW.minus(Duration.ofDays(5)), 10L, Duration.ZERO);
|
||||
Instant result = calculator.onFetchSuccess(NOW.minus(Duration.ofDays(5)), 10L, Duration.ZERO);
|
||||
Assertions.assertEquals(NOW.plus(DEFAULT_INTERVAL), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void averageAboveMaximum() {
|
||||
Instant result =
|
||||
calculator.onFetchSuccess(
|
||||
NOW.minus(Duration.ofDays(5)), Long.MAX_VALUE, Duration.ZERO);
|
||||
calculator.onFetchSuccess(NOW.minus(Duration.ofDays(5)), Long.MAX_VALUE, Duration.ZERO);
|
||||
Assertions.assertEquals(NOW.plus(MAX_INTERVAL.dividedBy(4)), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void noAverage() {
|
||||
Instant result =
|
||||
calculator.onFetchSuccess(
|
||||
NOW.minus(Duration.ofDays(5)), null, Duration.ZERO);
|
||||
Instant result = calculator.onFetchSuccess(NOW.minus(Duration.ofDays(5)), null, Duration.ZERO);
|
||||
Assertions.assertEquals(NOW.plus(MAX_INTERVAL), result);
|
||||
}
|
||||
}
|
||||
@@ -162,9 +145,7 @@ class FeedRefreshIntervalCalculatorTest {
|
||||
@ValueSource(longs = {0, 1, 300, 86400000L})
|
||||
void withoutValidFor(long averageEntryInterval) {
|
||||
// averageEntryInterval is ignored when empirical is disabled
|
||||
Instant result =
|
||||
calculator.onFeedNotModified(
|
||||
NOW.minus(Duration.ofDays(5)), averageEntryInterval);
|
||||
Instant result = calculator.onFeedNotModified(NOW.minus(Duration.ofDays(5)), averageEntryInterval);
|
||||
Assertions.assertEquals(NOW.plus(DEFAULT_INTERVAL), result);
|
||||
}
|
||||
}
|
||||
@@ -206,30 +187,25 @@ class FeedRefreshIntervalCalculatorTest {
|
||||
@Test
|
||||
void averageBetweenBounds() {
|
||||
Instant result =
|
||||
calculator.onFeedNotModified(
|
||||
NOW.minus(Duration.ofDays(5)), Duration.ofHours(4).toMillis());
|
||||
calculator.onFeedNotModified(NOW.minus(Duration.ofDays(5)), Duration.ofHours(4).toMillis());
|
||||
Assertions.assertEquals(NOW.plus(Duration.ofHours(2)), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void averageBelowMinimum() {
|
||||
Instant result =
|
||||
calculator.onFeedNotModified(NOW.minus(Duration.ofDays(5)), 10L);
|
||||
Instant result = calculator.onFeedNotModified(NOW.minus(Duration.ofDays(5)), 10L);
|
||||
Assertions.assertEquals(NOW.plus(DEFAULT_INTERVAL), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void averageAboveMaximum() {
|
||||
Instant result =
|
||||
calculator.onFeedNotModified(
|
||||
NOW.minus(Duration.ofDays(5)), Long.MAX_VALUE);
|
||||
Instant result = calculator.onFeedNotModified(NOW.minus(Duration.ofDays(5)), Long.MAX_VALUE);
|
||||
Assertions.assertEquals(NOW.plus(MAX_INTERVAL.dividedBy(4)), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void noAverage() {
|
||||
Instant result =
|
||||
calculator.onFeedNotModified(NOW.minus(Duration.ofDays(5)), null);
|
||||
Instant result = calculator.onFeedNotModified(NOW.minus(Duration.ofDays(5)), null);
|
||||
Assertions.assertEquals(NOW.plus(MAX_INTERVAL), result);
|
||||
}
|
||||
}
|
||||
@@ -251,8 +227,7 @@ class FeedRefreshIntervalCalculatorTest {
|
||||
|
||||
@Test
|
||||
void highErrorCount() {
|
||||
Mockito.when(config.feedRefresh().errors().backoffInterval())
|
||||
.thenReturn(Duration.ofHours(1));
|
||||
Mockito.when(config.feedRefresh().errors().backoffInterval()).thenReturn(Duration.ofHours(1));
|
||||
|
||||
Instant result = calculator.onFetchError(5);
|
||||
Assertions.assertEquals(NOW.plus(Duration.ofHours(3)), result);
|
||||
@@ -260,8 +235,7 @@ class FeedRefreshIntervalCalculatorTest {
|
||||
|
||||
@Test
|
||||
void veryHighErrorCount() {
|
||||
Mockito.when(config.feedRefresh().errors().backoffInterval())
|
||||
.thenReturn(Duration.ofHours(1));
|
||||
Mockito.when(config.feedRefresh().errors().backoffInterval()).thenReturn(Duration.ofHours(1));
|
||||
|
||||
Instant result = calculator.onFetchError(100000);
|
||||
Assertions.assertEquals(NOW.plus(MAX_INTERVAL), result);
|
||||
|
||||
@@ -31,11 +31,9 @@ class FeedUtilsTest {
|
||||
Assertions.assertEquals("Test Entry", syndEntry.getTitle());
|
||||
Assertions.assertEquals("Author Name", syndEntry.getAuthor());
|
||||
Assertions.assertEquals(1, syndEntry.getContents().size());
|
||||
Assertions.assertEquals(
|
||||
"This is a test entry content.", syndEntry.getContents().getFirst().getValue());
|
||||
Assertions.assertEquals("This is a test entry content.", syndEntry.getContents().getFirst().getValue());
|
||||
Assertions.assertEquals(1, syndEntry.getEnclosures().size());
|
||||
Assertions.assertEquals(
|
||||
"http://example.com/enclosure.mp3", syndEntry.getEnclosures().getFirst().getUrl());
|
||||
Assertions.assertEquals("http://example.com/enclosure.mp3", syndEntry.getEnclosures().getFirst().getUrl());
|
||||
Assertions.assertEquals("audio/mpeg", syndEntry.getEnclosures().getFirst().getType());
|
||||
Assertions.assertEquals("http://example.com/test-entry", syndEntry.getLink());
|
||||
Assertions.assertEquals(Date.from(Instant.ofEpochSecond(1)), syndEntry.getPublishedDate());
|
||||
|
||||
@@ -12,13 +12,10 @@ class EncodingDetectorTest {
|
||||
Assertions.assertNull(encodingDetector.extractDeclaredEncoding("<?xml ?>".getBytes()));
|
||||
Assertions.assertNull(encodingDetector.extractDeclaredEncoding("<feed></feed>".getBytes()));
|
||||
Assertions.assertEquals(
|
||||
"UTF-8",
|
||||
encodingDetector.extractDeclaredEncoding("<?xml encoding=\"UTF-8\" ?>".getBytes()));
|
||||
"UTF-8", encodingDetector.extractDeclaredEncoding("<?xml encoding=\"UTF-8\" ?>".getBytes()));
|
||||
Assertions.assertEquals(
|
||||
"UTF-8",
|
||||
encodingDetector.extractDeclaredEncoding("<?xml encoding='UTF-8' ?>".getBytes()));
|
||||
"UTF-8", encodingDetector.extractDeclaredEncoding("<?xml encoding='UTF-8' ?>".getBytes()));
|
||||
Assertions.assertEquals(
|
||||
"UTF-8",
|
||||
encodingDetector.extractDeclaredEncoding("<?xml encoding='UTF-8'?>".getBytes()));
|
||||
"UTF-8", encodingDetector.extractDeclaredEncoding("<?xml encoding='UTF-8'?>".getBytes()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,38 +7,25 @@ class TextDirectionDetectorTest {
|
||||
|
||||
@Test
|
||||
void testEstimateDirection() {
|
||||
Assertions.assertEquals(TextDirectionDetector.Direction.LEFT_TO_RIGHT, TextDirectionDetector.detect(""));
|
||||
Assertions.assertEquals(TextDirectionDetector.Direction.LEFT_TO_RIGHT, TextDirectionDetector.detect(" "));
|
||||
Assertions.assertEquals(TextDirectionDetector.Direction.LEFT_TO_RIGHT, TextDirectionDetector.detect("! (...)"));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.LEFT_TO_RIGHT, TextDirectionDetector.detect(""));
|
||||
TextDirectionDetector.Direction.LEFT_TO_RIGHT, TextDirectionDetector.detect("Pure Ascii content"));
|
||||
Assertions.assertEquals(TextDirectionDetector.Direction.LEFT_TO_RIGHT, TextDirectionDetector.detect("-17.0%"));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.LEFT_TO_RIGHT, TextDirectionDetector.detect(" "));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.LEFT_TO_RIGHT,
|
||||
TextDirectionDetector.detect("! (...)"));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.LEFT_TO_RIGHT,
|
||||
TextDirectionDetector.detect("Pure Ascii content"));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.LEFT_TO_RIGHT,
|
||||
TextDirectionDetector.detect("-17.0%"));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.LEFT_TO_RIGHT,
|
||||
TextDirectionDetector.detect("http://foo/bar/"));
|
||||
TextDirectionDetector.Direction.LEFT_TO_RIGHT, TextDirectionDetector.detect("http://foo/bar/"));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.LEFT_TO_RIGHT,
|
||||
TextDirectionDetector.detect(
|
||||
"http://foo/bar/?s=\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0"
|
||||
+ "\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0"
|
||||
+ "\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0"));
|
||||
Assertions.assertEquals(TextDirectionDetector.Direction.RIGHT_TO_LEFT, TextDirectionDetector.detect("\u05d0"));
|
||||
Assertions.assertEquals(TextDirectionDetector.Direction.RIGHT_TO_LEFT, TextDirectionDetector.detect("\u05d0"));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.RIGHT_TO_LEFT,
|
||||
TextDirectionDetector.detect("\u05d0"));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.RIGHT_TO_LEFT,
|
||||
TextDirectionDetector.detect("\u05d0"));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.RIGHT_TO_LEFT,
|
||||
TextDirectionDetector.detect(
|
||||
"http://foo/bar/ \u05d0 http://foo2/bar2/ http://foo3/bar3/"));
|
||||
TextDirectionDetector.detect("http://foo/bar/ \u05d0 http://foo2/bar2/ http://foo3/bar3/"));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.RIGHT_TO_LEFT,
|
||||
TextDirectionDetector.detect(
|
||||
@@ -69,8 +56,7 @@ class TextDirectionDetectorTest {
|
||||
+ "\u05d9 \u05d1\u05d0\u05ea\u05e8"));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.RIGHT_TO_LEFT,
|
||||
TextDirectionDetector.detect(
|
||||
"CAPTCHA \u05de\u05e9\u05d5\u05db\u05dc\u05dc " + "\u05de\u05d3\u05d9?"));
|
||||
TextDirectionDetector.detect("CAPTCHA \u05de\u05e9\u05d5\u05db\u05dc\u05dc " + "\u05de\u05d3\u05d9?"));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.RIGHT_TO_LEFT,
|
||||
TextDirectionDetector.detect(
|
||||
@@ -86,12 +72,10 @@ class TextDirectionDetectorTest {
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.RIGHT_TO_LEFT,
|
||||
TextDirectionDetector.detect(
|
||||
"5710 5720 5730. \u05d4\u05d3\u05dc\u05ea. "
|
||||
+ "\u05d4\u05e0\u05e9\u05d9\u05e7\u05d4"));
|
||||
"5710 5720 5730. \u05d4\u05d3\u05dc\u05ea. " + "\u05d4\u05e0\u05e9\u05d9\u05e7\u05d4"));
|
||||
Assertions.assertEquals(
|
||||
TextDirectionDetector.Direction.RIGHT_TO_LEFT,
|
||||
TextDirectionDetector.detect(
|
||||
"\u05d4\u05d3\u05dc\u05ea http://www.google.com "
|
||||
+ "http://www.gmail.com"));
|
||||
"\u05d4\u05d3\u05dc\u05ea http://www.google.com " + "http://www.gmail.com"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,22 +13,19 @@ class XMLCleanerTest {
|
||||
@Test
|
||||
void removesWhitespaceBeforeXmlTag() {
|
||||
String xml = " \n\t<feed>content</feed>";
|
||||
Assertions.assertEquals(
|
||||
"<feed>content</feed>", xmlCleaner.removeCharactersBeforeFirstXmlTag(xml));
|
||||
Assertions.assertEquals("<feed>content</feed>", xmlCleaner.removeCharactersBeforeFirstXmlTag(xml));
|
||||
}
|
||||
|
||||
@Test
|
||||
void removesTextBeforeXmlTag() {
|
||||
String xml = "some text here<feed>content</feed>";
|
||||
Assertions.assertEquals(
|
||||
"<feed>content</feed>", xmlCleaner.removeCharactersBeforeFirstXmlTag(xml));
|
||||
Assertions.assertEquals("<feed>content</feed>", xmlCleaner.removeCharactersBeforeFirstXmlTag(xml));
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnsUnchangedWhenStartsWithXmlTag() {
|
||||
String xml = "<feed>content</feed>";
|
||||
Assertions.assertEquals(
|
||||
"<feed>content</feed>", xmlCleaner.removeCharactersBeforeFirstXmlTag(xml));
|
||||
Assertions.assertEquals("<feed>content</feed>", xmlCleaner.removeCharactersBeforeFirstXmlTag(xml));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -56,8 +53,7 @@ class XMLCleanerTest {
|
||||
void preservesMultipleXmlTags() {
|
||||
String xml = "garbage<feed><item>content</item></feed>";
|
||||
Assertions.assertEquals(
|
||||
"<feed><item>content</item></feed>",
|
||||
xmlCleaner.removeCharactersBeforeFirstXmlTag(xml));
|
||||
"<feed><item>content</item></feed>", xmlCleaner.removeCharactersBeforeFirstXmlTag(xml));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,38 +62,32 @@ class XMLCleanerTest {
|
||||
@Test
|
||||
void removesNullCharacter() {
|
||||
String xml = "<feed>content\u0000here</feed>";
|
||||
Assertions.assertEquals(
|
||||
"<feed>contenthere</feed>", xmlCleaner.removeInvalidXmlCharacters(xml));
|
||||
Assertions.assertEquals("<feed>contenthere</feed>", xmlCleaner.removeInvalidXmlCharacters(xml));
|
||||
}
|
||||
|
||||
@Test
|
||||
void removesInvalidControlCharacters() {
|
||||
String xml = "<feed>content\u0001\u0002\u0003here</feed>";
|
||||
Assertions.assertEquals(
|
||||
"<feed>contenthere</feed>", xmlCleaner.removeInvalidXmlCharacters(xml));
|
||||
Assertions.assertEquals("<feed>contenthere</feed>", xmlCleaner.removeInvalidXmlCharacters(xml));
|
||||
}
|
||||
|
||||
@Test
|
||||
void preservesValidXmlCharacters() {
|
||||
String xml = "<feed>content with\ttab\nand newline</feed>";
|
||||
Assertions.assertEquals(
|
||||
"<feed>content with\ttab\nand newline</feed>",
|
||||
xmlCleaner.removeInvalidXmlCharacters(xml));
|
||||
"<feed>content with\ttab\nand newline</feed>", xmlCleaner.removeInvalidXmlCharacters(xml));
|
||||
}
|
||||
|
||||
@Test
|
||||
void preservesUnicodeCharacters() {
|
||||
String xml = "<feed>café résumé 中文 العربية</feed>";
|
||||
Assertions.assertEquals(
|
||||
"<feed>café résumé 中文 العربية</feed>",
|
||||
xmlCleaner.removeInvalidXmlCharacters(xml));
|
||||
Assertions.assertEquals("<feed>café résumé 中文 العربية</feed>", xmlCleaner.removeInvalidXmlCharacters(xml));
|
||||
}
|
||||
|
||||
@Test
|
||||
void preservesEmojiCharacters() {
|
||||
String xml = "<feed>🎮💪✅</feed>";
|
||||
Assertions.assertEquals(
|
||||
"<feed>🎮💪✅</feed>", xmlCleaner.removeInvalidXmlCharacters(xml));
|
||||
Assertions.assertEquals("<feed>🎮💪✅</feed>", xmlCleaner.removeInvalidXmlCharacters(xml));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -141,31 +131,26 @@ class XMLCleanerTest {
|
||||
@Test
|
||||
void replacesMultipleOccurrencesOfSameEntity() {
|
||||
String source = " ";
|
||||
Assertions.assertEquals(
|
||||
"   ",
|
||||
xmlCleaner.replaceHtmlEntitiesWithNumericEntities(source));
|
||||
Assertions.assertEquals("   ", xmlCleaner.replaceHtmlEntitiesWithNumericEntities(source));
|
||||
}
|
||||
|
||||
@Test
|
||||
void preservesTextWithoutEntities() {
|
||||
String source = "<feed>regular content</feed>";
|
||||
Assertions.assertEquals(
|
||||
"<feed>regular content</feed>",
|
||||
xmlCleaner.replaceHtmlEntitiesWithNumericEntities(source));
|
||||
"<feed>regular content</feed>", xmlCleaner.replaceHtmlEntitiesWithNumericEntities(source));
|
||||
}
|
||||
|
||||
@Test
|
||||
void preservesNumericEntities() {
|
||||
String source = "´′";
|
||||
Assertions.assertEquals(
|
||||
"´′", xmlCleaner.replaceHtmlEntitiesWithNumericEntities(source));
|
||||
Assertions.assertEquals("´′", xmlCleaner.replaceHtmlEntitiesWithNumericEntities(source));
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacesCommonHtmlEntities() {
|
||||
String source = "&"";
|
||||
Assertions.assertEquals(
|
||||
"&"", xmlCleaner.replaceHtmlEntitiesWithNumericEntities(source));
|
||||
Assertions.assertEquals("&"", xmlCleaner.replaceHtmlEntitiesWithNumericEntities(source));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -193,15 +178,13 @@ class XMLCleanerTest {
|
||||
@Test
|
||||
void handlesEntityAtStartOfString() {
|
||||
String source = "&test";
|
||||
Assertions.assertEquals(
|
||||
"&test", xmlCleaner.replaceHtmlEntitiesWithNumericEntities(source));
|
||||
Assertions.assertEquals("&test", xmlCleaner.replaceHtmlEntitiesWithNumericEntities(source));
|
||||
}
|
||||
|
||||
@Test
|
||||
void handlesEntityAtEndOfString() {
|
||||
String source = "test&";
|
||||
Assertions.assertEquals(
|
||||
"test&", xmlCleaner.replaceHtmlEntitiesWithNumericEntities(source));
|
||||
Assertions.assertEquals("test&", xmlCleaner.replaceHtmlEntitiesWithNumericEntities(source));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -218,8 +201,7 @@ class XMLCleanerTest {
|
||||
void testRemoveDoctype() {
|
||||
String source = "<!DOCTYPE html><html><head></head><body></body></html>";
|
||||
Assertions.assertEquals(
|
||||
"<html><head></head><body></body></html>",
|
||||
xmlCleaner.removeDoctypeDeclarations(source));
|
||||
"<html><head></head><body></body></html>", xmlCleaner.removeDoctypeDeclarations(source));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -241,10 +223,8 @@ class XMLCleanerTest {
|
||||
|
||||
@Test
|
||||
void removesComplexDoctypeWithSystemId() {
|
||||
String source =
|
||||
"<!DOCTYPE html SYSTEM \"about:legacy-compat\"><html><body></body></html>";
|
||||
Assertions.assertEquals(
|
||||
"<html><body></body></html>", xmlCleaner.removeDoctypeDeclarations(source));
|
||||
String source = "<!DOCTYPE html SYSTEM \"about:legacy-compat\"><html><body></body></html>";
|
||||
Assertions.assertEquals("<html><body></body></html>", xmlCleaner.removeDoctypeDeclarations(source));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -276,8 +256,7 @@ class XMLCleanerTest {
|
||||
void preservesContentWithoutDoctype() {
|
||||
String source = "<html><body>No doctype here</body></html>";
|
||||
Assertions.assertEquals(
|
||||
"<html><body>No doctype here</body></html>",
|
||||
xmlCleaner.removeDoctypeDeclarations(source));
|
||||
"<html><body>No doctype here</body></html>", xmlCleaner.removeDoctypeDeclarations(source));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -111,9 +111,7 @@ class OPMLExporterTest {
|
||||
|
||||
private boolean containsFeed(List<Outline> outlines, String title, String url) {
|
||||
for (Outline o : outlines) {
|
||||
if ("rss".equals(o.getType())
|
||||
&& title.equals(o.getTitle())
|
||||
&& o.getAttributeValue("xmlUrl").equals(url)) {
|
||||
if ("rss".equals(o.getType()) && title.equals(o.getTitle()) && o.getAttributeValue("xmlUrl").equals(url)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,21 +36,16 @@ class OPMLImporterTest {
|
||||
testOpmlVersion("/opml/opml_noversion.xml");
|
||||
}
|
||||
|
||||
private void testOpmlVersion(String fileName)
|
||||
throws IOException, IllegalArgumentException, FeedException {
|
||||
private void testOpmlVersion(String fileName) throws IOException, IllegalArgumentException, FeedException {
|
||||
XMLCleaner xmlCleaner = Mockito.mock(XMLCleaner.class);
|
||||
FeedCategoryDAO feedCategoryDAO = Mockito.mock(FeedCategoryDAO.class);
|
||||
FeedSubscriptionService feedSubscriptionService =
|
||||
Mockito.mock(FeedSubscriptionService.class);
|
||||
FeedSubscriptionService feedSubscriptionService = Mockito.mock(FeedSubscriptionService.class);
|
||||
User user = Mockito.mock(User.class);
|
||||
|
||||
Mockito.when(xmlCleaner.clean(Mockito.anyString()))
|
||||
.thenAnswer(invocation -> invocation.getArgument(0));
|
||||
String xml =
|
||||
IOUtils.toString(getClass().getResourceAsStream(fileName), StandardCharsets.UTF_8);
|
||||
Mockito.when(xmlCleaner.clean(Mockito.anyString())).thenAnswer(invocation -> invocation.getArgument(0));
|
||||
String xml = IOUtils.toString(getClass().getResourceAsStream(fileName), StandardCharsets.UTF_8);
|
||||
|
||||
OPMLImporter importer =
|
||||
new OPMLImporter(xmlCleaner, feedCategoryDAO, feedSubscriptionService);
|
||||
OPMLImporter importer = new OPMLImporter(xmlCleaner, feedCategoryDAO, feedSubscriptionService);
|
||||
importer.importOpml(user, xml);
|
||||
|
||||
Mockito.verify(feedSubscriptionService)
|
||||
|
||||
@@ -23,8 +23,7 @@ class FeedEntryFilteringServiceTest {
|
||||
@BeforeEach
|
||||
void init() {
|
||||
config = Mockito.mock(CommaFeedConfiguration.class, Mockito.RETURNS_DEEP_STUBS);
|
||||
Mockito.when(config.feedRefresh().filteringExpressionEvaluationTimeout())
|
||||
.thenReturn(Duration.ofSeconds(30));
|
||||
Mockito.when(config.feedRefresh().filteringExpressionEvaluationTimeout()).thenReturn(Duration.ofSeconds(30));
|
||||
|
||||
service = new FeedEntryFilteringService(config);
|
||||
|
||||
@@ -75,16 +74,12 @@ class FeedEntryFilteringServiceTest {
|
||||
|
||||
@Test
|
||||
void andExpression() throws FeedEntryFilterException {
|
||||
Assertions.assertTrue(
|
||||
service.filterMatchesEntry(
|
||||
"author == \"Athou\" && url.contains(\"github\")", entry));
|
||||
Assertions.assertTrue(service.filterMatchesEntry("author == \"Athou\" && url.contains(\"github\")", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
void orExpression() throws FeedEntryFilterException {
|
||||
Assertions.assertTrue(
|
||||
service.filterMatchesEntry(
|
||||
"author == \"other\" || url.contains(\"github\")", entry));
|
||||
Assertions.assertTrue(service.filterMatchesEntry("author == \"other\" || url.contains(\"github\")", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -95,8 +90,7 @@ class FeedEntryFilteringServiceTest {
|
||||
@Test
|
||||
void incorrectExpressionThrowsException() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() -> service.filterMatchesEntry("not valid cel", entry));
|
||||
FeedEntryFilterException.class, () -> service.filterMatchesEntry("not valid cel", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -124,8 +118,7 @@ class FeedEntryFilteringServiceTest {
|
||||
FeedEntryContent content = entry.getContent();
|
||||
content.setCategories("tech, programming, java");
|
||||
entry.setContent(content);
|
||||
Assertions.assertTrue(
|
||||
service.filterMatchesEntry("categories.contains(\"programming\")", entry));
|
||||
Assertions.assertTrue(service.filterMatchesEntry("categories.contains(\"programming\")", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -145,8 +138,7 @@ class FeedEntryFilteringServiceTest {
|
||||
|
||||
@Test
|
||||
void caseInsensitiveContentMatchUsingLowerVariable() throws FeedEntryFilterException {
|
||||
Assertions.assertTrue(
|
||||
service.filterMatchesEntry("contentLower.contains(\"merge\")", entry));
|
||||
Assertions.assertTrue(service.filterMatchesEntry("contentLower.contains(\"merge\")", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -154,8 +146,7 @@ class FeedEntryFilteringServiceTest {
|
||||
FeedEntryContent content = entry.getContent();
|
||||
content.setCategories("Tech, Programming, Java");
|
||||
entry.setContent(content);
|
||||
Assertions.assertTrue(
|
||||
service.filterMatchesEntry("categoriesLower.contains(\"tech\")", entry));
|
||||
Assertions.assertTrue(service.filterMatchesEntry("categoriesLower.contains(\"tech\")", entry));
|
||||
}
|
||||
|
||||
@Nested
|
||||
@@ -165,36 +156,28 @@ class FeedEntryFilteringServiceTest {
|
||||
void sandboxBlocksSystemPropertyAccess() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() ->
|
||||
service.filterMatchesEntry(
|
||||
"java.lang.System.getProperty(\"user.home\")", entry));
|
||||
() -> service.filterMatchesEntry("java.lang.System.getProperty(\"user.home\")", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sandboxBlocksRuntimeExec() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() ->
|
||||
service.filterMatchesEntry(
|
||||
"java.lang.Runtime.getRuntime().exec(\"calc\")", entry));
|
||||
() -> service.filterMatchesEntry("java.lang.Runtime.getRuntime().exec(\"calc\")", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sandboxBlocksProcessBuilder() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() ->
|
||||
service.filterMatchesEntry(
|
||||
"new java.lang.ProcessBuilder(\"cmd\").start()", entry));
|
||||
() -> service.filterMatchesEntry("new java.lang.ProcessBuilder(\"cmd\").start()", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sandboxBlocksClassLoading() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() ->
|
||||
service.filterMatchesEntry(
|
||||
"java.lang.Class.forName(\"java.lang.Runtime\")", entry));
|
||||
() -> service.filterMatchesEntry("java.lang.Class.forName(\"java.lang.Runtime\")", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -208,9 +191,7 @@ class FeedEntryFilteringServiceTest {
|
||||
void sandboxBlocksFileAccess() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() ->
|
||||
service.filterMatchesEntry(
|
||||
"new java.io.File(\"/etc/passwd\").exists()", entry));
|
||||
() -> service.filterMatchesEntry("new java.io.File(\"/etc/passwd\").exists()", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -219,18 +200,14 @@ class FeedEntryFilteringServiceTest {
|
||||
FeedEntryFilterException.class,
|
||||
() ->
|
||||
service.filterMatchesEntry(
|
||||
"java.nio.file.Files.readString(java.nio.file.Paths.get(\"/etc/passwd\"))",
|
||||
entry));
|
||||
"java.nio.file.Files.readString(java.nio.file.Paths.get(\"/etc/passwd\"))", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sandboxBlocksNetworkAccess() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() ->
|
||||
service.filterMatchesEntry(
|
||||
"new java.net.URL(\"http://evil.com\").openConnection()",
|
||||
entry));
|
||||
() -> service.filterMatchesEntry("new java.net.URL(\"http://evil.com\").openConnection()", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -274,50 +251,42 @@ class FeedEntryFilteringServiceTest {
|
||||
@Test
|
||||
void sandboxBlocksMethodInvocationOnStrings() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() -> service.filterMatchesEntry("title.toCharArray()", entry));
|
||||
FeedEntryFilterException.class, () -> service.filterMatchesEntry("title.toCharArray()", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sandboxBlocksArbitraryJavaMethodCalls() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() -> service.filterMatchesEntry("title.getBytes()", entry));
|
||||
FeedEntryFilterException.class, () -> service.filterMatchesEntry("title.getBytes()", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sandboxOnlyAllowsDeclaredVariables() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() -> service.filterMatchesEntry("System", entry));
|
||||
Assertions.assertThrows(FeedEntryFilterException.class, () -> service.filterMatchesEntry("System", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sandboxBlocksConstructorCalls() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() -> service.filterMatchesEntry("new String(\"test\")", entry));
|
||||
FeedEntryFilterException.class, () -> service.filterMatchesEntry("new String(\"test\")", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sandboxBlocksStaticMethodCalls() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() -> service.filterMatchesEntry("String.valueOf(123)", entry));
|
||||
FeedEntryFilterException.class, () -> service.filterMatchesEntry("String.valueOf(123)", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sandboxBlocksLambdaExpressions() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() -> service.filterMatchesEntry("() -> true", entry));
|
||||
FeedEntryFilterException.class, () -> service.filterMatchesEntry("() -> true", entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sandboxBlocksObjectInstantiation() {
|
||||
Assertions.assertThrows(
|
||||
FeedEntryFilterException.class,
|
||||
() -> service.filterMatchesEntry("java.util.HashMap{}", entry));
|
||||
FeedEntryFilterException.class, () -> service.filterMatchesEntry("java.util.HashMap{}", entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,7 @@ class PasswordEncryptionServiceTest {
|
||||
|
||||
// make sure the encrypted password is always the same for a fixed salt
|
||||
Assertions.assertEquals(
|
||||
"8b4660158141d9f4f7865718b9a2b940a3e3cea9",
|
||||
HexFormat.of().formatHex(encryptedPassword));
|
||||
Assertions.assertTrue(
|
||||
passwordEncryptionService.authenticate(password, encryptedPassword, salt));
|
||||
"8b4660158141d9f4f7865718b9a2b940a3e3cea9", HexFormat.of().formatHex(encryptedPassword));
|
||||
Assertions.assertTrue(passwordEncryptionService.authenticate(password, encryptedPassword, salt));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,11 +48,9 @@ class PushNotificationServiceTest {
|
||||
HttpClientFactory httpClientFactory =
|
||||
new HttpClientFactory(config, Mockito.mock(com.commafeed.CommaFeedVersion.class));
|
||||
MetricRegistry metricRegistry = Mockito.mock(MetricRegistry.class);
|
||||
Mockito.when(metricRegistry.meter(Mockito.anyString()))
|
||||
.thenReturn(Mockito.mock(Meter.class));
|
||||
Mockito.when(metricRegistry.meter(Mockito.anyString())).thenReturn(Mockito.mock(Meter.class));
|
||||
|
||||
this.pushNotificationService =
|
||||
new PushNotificationService(httpClientFactory, metricRegistry, config);
|
||||
this.pushNotificationService = new PushNotificationService(httpClientFactory, metricRegistry, config);
|
||||
|
||||
this.userSettings = new PushNotificationUserSettings();
|
||||
|
||||
@@ -78,8 +76,7 @@ class PushNotificationServiceTest {
|
||||
.withBody("Test Entry"))
|
||||
.respond(HttpResponse.response().withStatusCode(200));
|
||||
|
||||
Assertions.assertDoesNotThrow(
|
||||
() -> pushNotificationService.notify(userSettings, subscription, entry));
|
||||
Assertions.assertDoesNotThrow(() -> pushNotificationService.notify(userSettings, subscription, entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -113,8 +110,7 @@ class PushNotificationServiceTest {
|
||||
""")))
|
||||
.respond(HttpResponse.response().withStatusCode(200));
|
||||
|
||||
Assertions.assertDoesNotThrow(
|
||||
() -> pushNotificationService.notify(userSettings, subscription, entry));
|
||||
Assertions.assertDoesNotThrow(() -> pushNotificationService.notify(userSettings, subscription, entry));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -124,8 +120,7 @@ class PushNotificationServiceTest {
|
||||
userSettings.setServerUrl("http://localhost:" + mockServerClient.getPort());
|
||||
userSettings.setTopic("test-topic");
|
||||
|
||||
Assertions.assertDoesNotThrow(
|
||||
() -> pushNotificationService.notify(userSettings, subscription, entry));
|
||||
Assertions.assertDoesNotThrow(() -> pushNotificationService.notify(userSettings, subscription, entry));
|
||||
mockServerClient.verifyZeroInteractions();
|
||||
}
|
||||
|
||||
|
||||
@@ -108,15 +108,12 @@ class UserServiceTest {
|
||||
Mockito.when(userDAO.findByName("test")).thenReturn(normalUser);
|
||||
Mockito.when(
|
||||
passwordEncryptionService.authenticate(
|
||||
Mockito.anyString(),
|
||||
Mockito.any(byte[].class),
|
||||
Mockito.any(byte[].class)))
|
||||
Mockito.anyString(), Mockito.any(byte[].class), Mockito.any(byte[].class)))
|
||||
.thenReturn(false);
|
||||
|
||||
userService.login("test", "password");
|
||||
|
||||
Mockito.verify(passwordEncryptionService)
|
||||
.authenticate("password", ENCRYPTED_PASSWORD, SALT);
|
||||
Mockito.verify(passwordEncryptionService).authenticate("password", ENCRYPTED_PASSWORD, SALT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -124,9 +121,7 @@ class UserServiceTest {
|
||||
Mockito.when(userDAO.findByName("test")).thenReturn(normalUser);
|
||||
Mockito.when(
|
||||
passwordEncryptionService.authenticate(
|
||||
Mockito.anyString(),
|
||||
Mockito.any(byte[].class),
|
||||
Mockito.any(byte[].class)))
|
||||
Mockito.anyString(), Mockito.any(byte[].class), Mockito.any(byte[].class)))
|
||||
.thenReturn(false);
|
||||
|
||||
Optional<User> authenticatedUser = userService.login("test", "password");
|
||||
@@ -139,9 +134,7 @@ class UserServiceTest {
|
||||
Mockito.when(userDAO.findByName("test")).thenReturn(normalUser);
|
||||
Mockito.when(
|
||||
passwordEncryptionService.authenticate(
|
||||
Mockito.anyString(),
|
||||
Mockito.any(byte[].class),
|
||||
Mockito.any(byte[].class)))
|
||||
Mockito.anyString(), Mockito.any(byte[].class), Mockito.any(byte[].class)))
|
||||
.thenReturn(true);
|
||||
Mockito.doNothing().when(postLoginActivities).executeFor(Mockito.any(User.class));
|
||||
|
||||
@@ -155,9 +148,7 @@ class UserServiceTest {
|
||||
Mockito.when(userDAO.findByName("test")).thenReturn(normalUser);
|
||||
Mockito.when(
|
||||
passwordEncryptionService.authenticate(
|
||||
Mockito.anyString(),
|
||||
Mockito.any(byte[].class),
|
||||
Mockito.any(byte[].class)))
|
||||
Mockito.anyString(), Mockito.any(byte[].class), Mockito.any(byte[].class)))
|
||||
.thenReturn(true);
|
||||
Mockito.doNothing().when(postLoginActivities).executeFor(Mockito.any(User.class));
|
||||
|
||||
|
||||
@@ -64,13 +64,7 @@ class DatabaseCleaningServiceTest {
|
||||
|
||||
service =
|
||||
new DatabaseCleaningService(
|
||||
config,
|
||||
unitOfWork,
|
||||
feedDAO,
|
||||
feedEntryDAO,
|
||||
feedEntryContentDAO,
|
||||
feedEntryStatusDAO,
|
||||
metrics);
|
||||
config, unitOfWork, feedDAO, feedEntryDAO, feedEntryContentDAO, feedEntryStatusDAO, metrics);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -97,13 +91,11 @@ class DatabaseCleaningServiceTest {
|
||||
|
||||
@Test
|
||||
void cleanContentsWithoutEntriesDeletesContents() {
|
||||
Mockito.when(feedEntryContentDAO.deleteWithoutEntries(Mockito.anyInt()))
|
||||
.thenReturn(50L, 30L, 0L);
|
||||
Mockito.when(feedEntryContentDAO.deleteWithoutEntries(Mockito.anyInt())).thenReturn(50L, 30L, 0L);
|
||||
|
||||
service.cleanContentsWithoutEntries();
|
||||
|
||||
Mockito.verify(feedEntryContentDAO, Mockito.times(3))
|
||||
.deleteWithoutEntries(Mockito.anyInt());
|
||||
Mockito.verify(feedEntryContentDAO, Mockito.times(3)).deleteWithoutEntries(Mockito.anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -133,13 +125,11 @@ class DatabaseCleaningServiceTest {
|
||||
void cleanEntriesOlderThanDeletesOldEntries() {
|
||||
Instant cutoff = LocalDate.now().minusDays(30).atStartOfDay().toInstant(ZoneOffset.UTC);
|
||||
|
||||
Mockito.when(feedEntryDAO.deleteEntriesOlderThan(cutoff, BATCH_SIZE, false))
|
||||
.thenReturn(100, 50, 0);
|
||||
Mockito.when(feedEntryDAO.deleteEntriesOlderThan(cutoff, BATCH_SIZE, false)).thenReturn(100, 50, 0);
|
||||
|
||||
service.cleanEntriesOlderThan(cutoff);
|
||||
|
||||
Mockito.verify(feedEntryDAO, Mockito.times(3))
|
||||
.deleteEntriesOlderThan(cutoff, BATCH_SIZE, false);
|
||||
Mockito.verify(feedEntryDAO, Mockito.times(3)).deleteEntriesOlderThan(cutoff, BATCH_SIZE, false);
|
||||
Mockito.verify(entriesDeletedMeter, Mockito.times(3)).mark(Mockito.anyLong());
|
||||
}
|
||||
|
||||
@@ -147,8 +137,7 @@ class DatabaseCleaningServiceTest {
|
||||
void cleanStatusesOlderThanDeletesOldStatuses() {
|
||||
Instant cutoff = LocalDate.now().minusDays(60).atStartOfDay().toInstant(ZoneOffset.UTC);
|
||||
|
||||
Mockito.when(feedEntryStatusDAO.deleteOldStatuses(cutoff, BATCH_SIZE))
|
||||
.thenReturn(200L, 100L, 0L);
|
||||
Mockito.when(feedEntryStatusDAO.deleteOldStatuses(cutoff, BATCH_SIZE)).thenReturn(200L, 100L, 0L);
|
||||
|
||||
service.cleanStatusesOlderThan(cutoff);
|
||||
|
||||
|
||||
@@ -25,8 +25,7 @@ class InPageReferenceFeedURLProviderTest {
|
||||
""";
|
||||
|
||||
Assertions.assertIterableEquals(
|
||||
List.of("http://example.com/feed.atom", "http://example.com/feed.rss"),
|
||||
provider.get(url, html));
|
||||
List.of("http://example.com/feed.atom", "http://example.com/feed.rss"), provider.get(url, html));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -18,8 +18,7 @@ class YoutubeFeedURLProviderTest {
|
||||
|
||||
@Test
|
||||
void doesNotmatchYoutubeChannelURL() {
|
||||
Assertions.assertTrue(
|
||||
provider.get("https://www.anothersite.com/channel/abc", null).isEmpty());
|
||||
Assertions.assertTrue(provider.get("https://www.anothersite.com/channel/abc", null).isEmpty());
|
||||
Assertions.assertTrue(provider.get("https://www.youtube.com/user/abc", null).isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,7 @@ class AuthentificationIT {
|
||||
Page page = context.newPage();
|
||||
page.navigate(getLoginPageUrl());
|
||||
PlaywrightTestUtils.login(page, TestConstants.ADMIN_USERNAME, "wrong_password");
|
||||
PlaywrightAssertions.assertThat(page.getByRole(AriaRole.ALERT))
|
||||
.containsText("Wrong username or password");
|
||||
PlaywrightAssertions.assertThat(page.getByRole(AriaRole.ALERT)).containsText("Wrong username or password");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -25,8 +25,7 @@ class InitialSetupIT {
|
||||
|
||||
page.getByPlaceholder("Admin User Name").fill(TestConstants.ADMIN_USERNAME);
|
||||
page.getByPlaceholder("Password").fill(TestConstants.ADMIN_PASSWORD);
|
||||
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Create Admin Account"))
|
||||
.click();
|
||||
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Create Admin Account")).click();
|
||||
|
||||
PlaywrightAssertions.assertThat(page).hasURL("http://localhost:8085/#/app/category/all");
|
||||
}
|
||||
|
||||
@@ -46,14 +46,12 @@ class ReadingIT {
|
||||
HttpResponse.response()
|
||||
.withBody(
|
||||
IOUtils.toString(
|
||||
getClass().getResource("/feed/rss.xml"),
|
||||
StandardCharsets.UTF_8))
|
||||
getClass().getResource("/feed/rss.xml"), StandardCharsets.UTF_8))
|
||||
.withDelay(TimeUnit.MILLISECONDS, 100));
|
||||
|
||||
PlaywrightTestUtils.initialSetup();
|
||||
RestAssured.authentication =
|
||||
RestAssured.preemptive()
|
||||
.basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -74,18 +72,13 @@ class ReadingIT {
|
||||
Locator sidebar = page.getByRole(AriaRole.NAVIGATION);
|
||||
Locator main = page.getByRole(AriaRole.MAIN);
|
||||
|
||||
PlaywrightAssertions.assertThat(main.getByText("You don't have any subscriptions yet."))
|
||||
.hasCount(1);
|
||||
PlaywrightAssertions.assertThat(main.getByText("You don't have any subscriptions yet.")).hasCount(1);
|
||||
|
||||
// subscribe
|
||||
header.getByRole(AriaRole.BUTTON, new Locator.GetByRoleOptions().setName("Subscribe"))
|
||||
.click();
|
||||
header.getByRole(AriaRole.BUTTON, new Locator.GetByRoleOptions().setName("Subscribe")).click();
|
||||
main.getByText("Feed URL *").fill("http://localhost:" + this.mockServerClient.getPort());
|
||||
main.getByRole(AriaRole.BUTTON, new Locator.GetByRoleOptions().setName("Next")).click();
|
||||
main.getByRole(
|
||||
AriaRole.BUTTON,
|
||||
new Locator.GetByRoleOptions().setName("Subscribe").setExact(true))
|
||||
.click();
|
||||
main.getByRole(AriaRole.BUTTON, new Locator.GetByRoleOptions().setName("Subscribe").setExact(true)).click();
|
||||
|
||||
// click on subscription
|
||||
sidebar.getByText(Pattern.compile("CommaFeed test feed\\d+")).click();
|
||||
|
||||
@@ -40,8 +40,7 @@ import java.util.Objects;
|
||||
@Getter
|
||||
public abstract class BaseIT {
|
||||
|
||||
private static final HttpRequest FEED_REQUEST =
|
||||
HttpRequest.request().withMethod("GET").withPath("/");
|
||||
private static final HttpRequest FEED_REQUEST = HttpRequest.request().withMethod("GET").withPath("/");
|
||||
|
||||
@Getter private MockServerClient mockServerClient;
|
||||
private Client client;
|
||||
@@ -62,14 +61,11 @@ public abstract class BaseIT {
|
||||
URL resource = Objects.requireNonNull(getClass().getResource("/feed/rss.xml"));
|
||||
this.mockServerClient
|
||||
.when(FEED_REQUEST)
|
||||
.respond(
|
||||
HttpResponse.response()
|
||||
.withBody(IOUtils.toString(resource, StandardCharsets.UTF_8)));
|
||||
.respond(HttpResponse.response().withBody(IOUtils.toString(resource, StandardCharsets.UTF_8)));
|
||||
|
||||
// remove when Quarkus supports Jackson 3
|
||||
RestAssured.config =
|
||||
RestAssured.config()
|
||||
.objectMapperConfig(new ObjectMapperConfig(ObjectMapperType.JACKSON_2));
|
||||
RestAssured.config().objectMapperConfig(new ObjectMapperConfig(ObjectMapperType.JACKSON_2));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -89,9 +85,7 @@ public abstract class BaseIT {
|
||||
URL resource = Objects.requireNonNull(getClass().getResource("/feed/rss_2.xml"));
|
||||
mockServerClient
|
||||
.when(FEED_REQUEST)
|
||||
.respond(
|
||||
HttpResponse.response()
|
||||
.withBody(IOUtils.toString(resource, StandardCharsets.UTF_8)));
|
||||
.respond(HttpResponse.response().withBody(IOUtils.toString(resource, StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
protected void initialSetup(String userName, String password) {
|
||||
@@ -124,9 +118,7 @@ public abstract class BaseIT {
|
||||
.extract()
|
||||
.headers()
|
||||
.getList(HttpHeaders.SET_COOKIE);
|
||||
return setCookieHeaders.stream()
|
||||
.flatMap(h -> HttpCookie.parse(h.getValue()).stream())
|
||||
.toList();
|
||||
return setCookieHeaders.stream().flatMap(h -> HttpCookie.parse(h.getValue()).stream()).toList();
|
||||
}
|
||||
|
||||
protected String createCategory(String name) {
|
||||
@@ -223,10 +215,7 @@ public abstract class BaseIT {
|
||||
|
||||
protected Entries getCategoryEntries(String categoryId, String keywords) {
|
||||
return RestAssured.given()
|
||||
.get(
|
||||
"rest/category/entries?id={id}&readType=all&keywords={keywords}",
|
||||
categoryId,
|
||||
keywords)
|
||||
.get("rest/category/entries?id={id}&readType=all&keywords={keywords}", categoryId, keywords)
|
||||
.then()
|
||||
.statusCode(HttpStatus.SC_OK)
|
||||
.extract()
|
||||
|
||||
@@ -14,11 +14,6 @@ class CompressionIT {
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"/rest/server/get", "/"})
|
||||
void servedWithCompression(String path) {
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.get(path)
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.header(HttpHeaders.CONTENT_ENCODING, "gzip");
|
||||
RestAssured.given().when().get(path).then().statusCode(200).header(HttpHeaders.CONTENT_ENCODING, "gzip");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,7 @@ class PushNotificationIT extends BaseIT {
|
||||
void setup() {
|
||||
initialSetup(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.authentication =
|
||||
RestAssured.preemptive()
|
||||
.basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -41,13 +40,11 @@ class PushNotificationIT extends BaseIT {
|
||||
@Test
|
||||
void receivedPushNotifications() throws IOException {
|
||||
// mock ntfy server
|
||||
HttpRequest ntfyPost =
|
||||
HttpRequest.request().withMethod("POST").withPath("/ntfy/integration-test");
|
||||
HttpRequest ntfyPost = HttpRequest.request().withMethod("POST").withPath("/ntfy/integration-test");
|
||||
getMockServerClient().when(ntfyPost).respond(HttpResponse.response().withStatusCode(200));
|
||||
|
||||
// enable push notifications
|
||||
Settings settings =
|
||||
RestAssured.given().get("rest/user/settings").then().extract().as(Settings.class);
|
||||
Settings settings = RestAssured.given().get("rest/user/settings").then().extract().as(Settings.class);
|
||||
settings.getPushNotificationSettings().setType(PushNotificationType.NTFY);
|
||||
settings.getPushNotificationSettings()
|
||||
.setServerUrl("http://localhost:" + getMockServerClient().getPort() + "/ntfy");
|
||||
@@ -84,7 +81,6 @@ class PushNotificationIT extends BaseIT {
|
||||
// await push notification for the two entries in the feed
|
||||
Awaitility.await()
|
||||
.atMost(Duration.ofSeconds(20))
|
||||
.untilAsserted(
|
||||
() -> getMockServerClient().verify(ntfyPost, VerificationTimes.exactly(2)));
|
||||
.untilAsserted(() -> getMockServerClient().verify(ntfyPost, VerificationTimes.exactly(2)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,9 +57,7 @@ class SecurityIT extends BaseIT {
|
||||
cookies.forEach(c -> Assertions.assertTrue(c.getMaxAge() > 0));
|
||||
|
||||
RestAssured.given()
|
||||
.header(
|
||||
HttpHeaders.COOKIE,
|
||||
cookies.stream().map(HttpCookie::toString).collect(Collectors.joining(";")))
|
||||
.header(HttpHeaders.COOKIE, cookies.stream().map(HttpCookie::toString).collect(Collectors.joining(";")))
|
||||
.get("rest/user/profile")
|
||||
.then()
|
||||
.statusCode(HttpStatus.SC_OK);
|
||||
@@ -71,11 +69,7 @@ class SecurityIT extends BaseIT {
|
||||
RestAssured.given()
|
||||
.auth()
|
||||
.none()
|
||||
.formParams(
|
||||
"j_username",
|
||||
TestConstants.ADMIN_USERNAME,
|
||||
"j_password",
|
||||
"wrong-password")
|
||||
.formParams("j_username", TestConstants.ADMIN_USERNAME, "j_password", "wrong-password")
|
||||
.post("j_security_check")
|
||||
.then()
|
||||
.statusCode(HttpStatus.SC_UNAUTHORIZED)
|
||||
@@ -396,9 +390,7 @@ class SecurityIT extends BaseIT {
|
||||
}
|
||||
|
||||
private String session(String userName, String password) {
|
||||
return login(userName, password).stream()
|
||||
.map(HttpCookie::toString)
|
||||
.collect(Collectors.joining(";"));
|
||||
return login(userName, password).stream().map(HttpCookie::toString).collect(Collectors.joining(";"));
|
||||
}
|
||||
|
||||
private UserModel profile(String session) {
|
||||
@@ -412,10 +404,6 @@ class SecurityIT extends BaseIT {
|
||||
}
|
||||
|
||||
private void assertSessionStatus(String session, int status) {
|
||||
RestAssured.given()
|
||||
.header(HttpHeaders.COOKIE, session)
|
||||
.get("rest/user/profile")
|
||||
.then()
|
||||
.statusCode(status);
|
||||
RestAssured.given().header(HttpHeaders.COOKIE, session).get("rest/user/profile").then().statusCode(status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,7 @@ class StaticFilesIT {
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"/", "/openapi"})
|
||||
void servedWithoutCache(String path) {
|
||||
RestAssured.given()
|
||||
.when()
|
||||
.get(path)
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.header("Cache-Control", "no-cache");
|
||||
RestAssured.given().when().get(path).then().statusCode(200).header("Cache-Control", "no-cache");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
||||
@@ -44,8 +44,7 @@ class WebSocketIT extends BaseIT {
|
||||
void setup() {
|
||||
initialSetup(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.authentication =
|
||||
RestAssured.preemptive()
|
||||
.basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -76,9 +75,7 @@ class WebSocketIT extends BaseIT {
|
||||
Awaitility.await().atMost(15, TimeUnit.SECONDS).untilTrue(connected);
|
||||
log.info("connected to {}", session.getRequestURI());
|
||||
|
||||
Awaitility.await()
|
||||
.atMost(15, TimeUnit.SECONDS)
|
||||
.until(() -> closeReasonRef.get() != null);
|
||||
Awaitility.await().atMost(15, TimeUnit.SECONDS).until(() -> closeReasonRef.get() != null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,8 +33,7 @@ class DatabaseCleaningIT extends BaseIT {
|
||||
void setup() {
|
||||
initialSetup(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.authentication =
|
||||
RestAssured.preemptive()
|
||||
.basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -85,8 +84,7 @@ class DatabaseCleaningIT extends BaseIT {
|
||||
// Verify the entry is starred
|
||||
Entries starredEntries = getCategoryEntries(CategoryREST.STARRED);
|
||||
Assertions.assertEquals(1, starredEntries.getEntries().size());
|
||||
Assertions.assertEquals(
|
||||
entryToStar.getId(), starredEntries.getEntries().getFirst().getId());
|
||||
Assertions.assertEquals(entryToStar.getId(), starredEntries.getEntries().getFirst().getId());
|
||||
|
||||
// Run cleanup with capacity of 0 (should delete all non-starred entries)
|
||||
// With keepStarredEntries=true (default), only non-starred entries are counted for
|
||||
@@ -99,14 +97,12 @@ class DatabaseCleaningIT extends BaseIT {
|
||||
// Verify starred entry is still present
|
||||
Entries starredEntriesAfter = getCategoryEntries(CategoryREST.STARRED);
|
||||
Assertions.assertEquals(1, starredEntriesAfter.getEntries().size());
|
||||
Assertions.assertEquals(
|
||||
entryToStar.getId(), starredEntriesAfter.getEntries().getFirst().getId());
|
||||
Assertions.assertEquals(entryToStar.getId(), starredEntriesAfter.getEntries().getFirst().getId());
|
||||
|
||||
// Verify the non-starred entry was deleted (only starred entry should remain)
|
||||
Entries entriesAfter = getFeedEntries(subscriptionId);
|
||||
Assertions.assertEquals(1, entriesAfter.getEntries().size());
|
||||
Assertions.assertEquals(
|
||||
entryToStar.getId(), entriesAfter.getEntries().getFirst().getId());
|
||||
Assertions.assertEquals(entryToStar.getId(), entriesAfter.getEntries().getFirst().getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -134,14 +130,12 @@ class DatabaseCleaningIT extends BaseIT {
|
||||
// Verify starred entry is still present
|
||||
Entries starredEntriesAfter = getCategoryEntries(CategoryREST.STARRED);
|
||||
Assertions.assertEquals(1, starredEntriesAfter.getEntries().size());
|
||||
Assertions.assertEquals(
|
||||
entryToStar.getId(), starredEntriesAfter.getEntries().getFirst().getId());
|
||||
Assertions.assertEquals(entryToStar.getId(), starredEntriesAfter.getEntries().getFirst().getId());
|
||||
|
||||
// Verify the non-starred entry was deleted
|
||||
Entries entriesAfter = getFeedEntries(subscriptionId);
|
||||
Assertions.assertEquals(1, entriesAfter.getEntries().size());
|
||||
Assertions.assertEquals(
|
||||
entryToStar.getId(), entriesAfter.getEntries().getFirst().getId());
|
||||
Assertions.assertEquals(entryToStar.getId(), entriesAfter.getEntries().getFirst().getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -183,15 +177,13 @@ class DatabaseCleaningIT extends BaseIT {
|
||||
starEntry(entry.getId(), subscriptionId);
|
||||
|
||||
// Verify entry is starred
|
||||
Assertions.assertEquals(
|
||||
1, getCategoryEntries(CategoryREST.STARRED).getEntries().size());
|
||||
Assertions.assertEquals(1, getCategoryEntries(CategoryREST.STARRED).getEntries().size());
|
||||
|
||||
// Unstar the entry
|
||||
unstarEntry(entry.getId(), subscriptionId);
|
||||
|
||||
// Verify entry is no longer starred
|
||||
Assertions.assertEquals(
|
||||
0, getCategoryEntries(CategoryREST.STARRED).getEntries().size());
|
||||
Assertions.assertEquals(0, getCategoryEntries(CategoryREST.STARRED).getEntries().size());
|
||||
|
||||
// Run cleanup for entries older than now
|
||||
Instant olderThan = Instant.now().plus(Duration.ofDays(1));
|
||||
@@ -212,27 +204,20 @@ class DatabaseCleaningIT extends BaseIT {
|
||||
|
||||
// verify we have 2 unread entries
|
||||
Entries entries = getFeedEntries(subscriptionId);
|
||||
Assertions.assertEquals(
|
||||
2, entries.getEntries().stream().filter(e -> !e.isRead()).count());
|
||||
Assertions.assertEquals(2, entries.getEntries().stream().filter(e -> !e.isRead()).count());
|
||||
|
||||
// set auto-mark as read
|
||||
FeedModificationRequest req = new FeedModificationRequest();
|
||||
req.setId(subscriptionId);
|
||||
req.setAutoMarkAsReadAfterDays(1);
|
||||
RestAssured.given()
|
||||
.body(req)
|
||||
.contentType(ContentType.JSON)
|
||||
.post("rest/feed/modify")
|
||||
.then()
|
||||
.statusCode(200);
|
||||
RestAssured.given().body(req).contentType(ContentType.JSON).post("rest/feed/modify").then().statusCode(200);
|
||||
|
||||
// run auto-mark as read
|
||||
databaseCleaningService.autoMarkAsRead();
|
||||
|
||||
// verify all entries are now read
|
||||
entries = getFeedEntries(subscriptionId);
|
||||
Assertions.assertEquals(
|
||||
0, entries.getEntries().stream().filter(e -> !e.isRead()).count());
|
||||
Assertions.assertEquals(0, entries.getEntries().stream().filter(e -> !e.isRead()).count());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@ class AdminIT extends BaseIT {
|
||||
void setup() {
|
||||
initialSetup(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.authentication =
|
||||
RestAssured.preemptive()
|
||||
.basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
||||
@@ -38,8 +38,7 @@ class CategoryIT extends BaseIT {
|
||||
void setup() {
|
||||
initialSetup(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.authentication =
|
||||
RestAssured.preemptive()
|
||||
.basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -70,8 +69,7 @@ class CategoryIT extends BaseIT {
|
||||
Assertions.assertEquals("test-category-1", root.getChildren().getFirst().getName());
|
||||
Assertions.assertEquals(1, root.getChildren().getFirst().getChildren().size());
|
||||
Assertions.assertEquals(
|
||||
"modified-category-2",
|
||||
root.getChildren().getFirst().getChildren().getFirst().getName());
|
||||
"modified-category-2", root.getChildren().getFirst().getChildren().getFirst().getName());
|
||||
|
||||
request = new CategoryModificationRequest();
|
||||
request.setId(Long.valueOf(category3Id));
|
||||
@@ -152,9 +150,7 @@ class CategoryIT extends BaseIT {
|
||||
@Test
|
||||
void all() {
|
||||
subscribeAndWaitForEntries(getFeedUrl());
|
||||
Assertions.assertTrue(
|
||||
getCategoryEntries(CategoryREST.ALL).getEntries().stream()
|
||||
.noneMatch(Entry::isRead));
|
||||
Assertions.assertTrue(getCategoryEntries(CategoryREST.ALL).getEntries().stream().noneMatch(Entry::isRead));
|
||||
|
||||
MarkRequest request = new MarkRequest();
|
||||
request.setId(CategoryREST.ALL);
|
||||
@@ -165,17 +161,14 @@ class CategoryIT extends BaseIT {
|
||||
.post("rest/category/mark")
|
||||
.then()
|
||||
.statusCode(200);
|
||||
Assertions.assertTrue(
|
||||
getCategoryEntries(CategoryREST.ALL).getEntries().stream()
|
||||
.allMatch(Entry::isRead));
|
||||
Assertions.assertTrue(getCategoryEntries(CategoryREST.ALL).getEntries().stream().allMatch(Entry::isRead));
|
||||
}
|
||||
|
||||
@Test
|
||||
void specificCategory() {
|
||||
String categoryId = createCategory("test-category");
|
||||
subscribeAndWaitForEntries(getFeedUrl(), categoryId);
|
||||
Assertions.assertTrue(
|
||||
getCategoryEntries(categoryId).getEntries().stream().noneMatch(Entry::isRead));
|
||||
Assertions.assertTrue(getCategoryEntries(categoryId).getEntries().stream().noneMatch(Entry::isRead));
|
||||
|
||||
MarkRequest request = new MarkRequest();
|
||||
request.setId(categoryId);
|
||||
@@ -186,8 +179,7 @@ class CategoryIT extends BaseIT {
|
||||
.post("rest/category/mark")
|
||||
.then()
|
||||
.statusCode(200);
|
||||
Assertions.assertTrue(
|
||||
getCategoryEntries(categoryId).getEntries().stream().allMatch(Entry::isRead));
|
||||
Assertions.assertTrue(getCategoryEntries(categoryId).getEntries().stream().allMatch(Entry::isRead));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,18 +225,14 @@ class CategoryIT extends BaseIT {
|
||||
@Test
|
||||
void starred() {
|
||||
Long subscriptionId = subscribeAndWaitForEntries(getFeedUrl());
|
||||
Assertions.assertEquals(
|
||||
0, getCategoryEntries(CategoryREST.STARRED).getEntries().size());
|
||||
Assertions.assertEquals(0, getCategoryEntries(CategoryREST.STARRED).getEntries().size());
|
||||
|
||||
Entry entry = getFeedEntries(subscriptionId).getEntries().getFirst();
|
||||
|
||||
StarRequest starRequest = new StarRequest();
|
||||
starRequest.setId(entry.getId());
|
||||
starRequest.setStarred(true);
|
||||
RestAssured.given()
|
||||
.body(starRequest)
|
||||
.contentType(ContentType.JSON)
|
||||
.post("rest/entry/star");
|
||||
RestAssured.given().body(starRequest).contentType(ContentType.JSON).post("rest/entry/star");
|
||||
|
||||
Entries starredEntries = getCategoryEntries(CategoryREST.STARRED);
|
||||
Assertions.assertEquals(1, starredEntries.getEntries().size());
|
||||
@@ -261,10 +249,7 @@ class CategoryIT extends BaseIT {
|
||||
TagRequest tagRequest = new TagRequest();
|
||||
tagRequest.setEntryId(Long.valueOf(entry.getId()));
|
||||
tagRequest.setTags(List.of("my-tag"));
|
||||
RestAssured.given()
|
||||
.body(tagRequest)
|
||||
.contentType(ContentType.JSON)
|
||||
.post("rest/entry/tag");
|
||||
RestAssured.given().body(tagRequest).contentType(ContentType.JSON).post("rest/entry/tag");
|
||||
|
||||
Entries taggedEntries = getTaggedEntries("my-tag");
|
||||
Assertions.assertEquals(1, taggedEntries.getEntries().size());
|
||||
@@ -274,9 +259,7 @@ class CategoryIT extends BaseIT {
|
||||
@Test
|
||||
void keywords() {
|
||||
subscribeAndWaitForEntries(getFeedUrl());
|
||||
Assertions.assertEquals(
|
||||
1,
|
||||
getCategoryEntries(CategoryREST.ALL, "Item 2 description").getEntries().size());
|
||||
Assertions.assertEquals(1, getCategoryEntries(CategoryREST.ALL, "Item 2 description").getEntries().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -48,8 +48,7 @@ class FeedIT extends BaseIT {
|
||||
void setup() {
|
||||
initialSetup(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.authentication =
|
||||
RestAssured.preemptive()
|
||||
.basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -130,22 +129,15 @@ class FeedIT extends BaseIT {
|
||||
void markWithoutDates() {
|
||||
long subscriptionId = subscribeAndWaitForEntries(getFeedUrl());
|
||||
markFeedEntries(subscriptionId, null, null);
|
||||
Assertions.assertTrue(
|
||||
getFeedEntries(subscriptionId).getEntries().stream().allMatch(Entry::isRead));
|
||||
Assertions.assertTrue(getFeedEntries(subscriptionId).getEntries().stream().allMatch(Entry::isRead));
|
||||
}
|
||||
|
||||
@Test
|
||||
void markOlderThan() {
|
||||
long subscriptionId = subscribeAndWaitForEntries(getFeedUrl());
|
||||
markFeedEntries(
|
||||
subscriptionId,
|
||||
LocalDate.of(2023, 12, 28).atStartOfDay().toInstant(ZoneOffset.UTC),
|
||||
null);
|
||||
markFeedEntries(subscriptionId, LocalDate.of(2023, 12, 28).atStartOfDay().toInstant(ZoneOffset.UTC), null);
|
||||
Assertions.assertEquals(
|
||||
1,
|
||||
getFeedEntries(subscriptionId).getEntries().stream()
|
||||
.filter(Entry::isRead)
|
||||
.count());
|
||||
1, getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isRead).count());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -155,8 +147,7 @@ class FeedIT extends BaseIT {
|
||||
|
||||
long subscriptionId = subscribeAndWaitForEntries(getFeedUrl());
|
||||
markFeedEntries(subscriptionId, null, threshold);
|
||||
Assertions.assertTrue(
|
||||
getFeedEntries(subscriptionId).getEntries().stream().noneMatch(Entry::isRead));
|
||||
Assertions.assertTrue(getFeedEntries(subscriptionId).getEntries().stream().noneMatch(Entry::isRead));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -167,17 +158,14 @@ class FeedIT extends BaseIT {
|
||||
Instant threshold = Instant.now().plus(Duration.ofSeconds(1));
|
||||
|
||||
markFeedEntries(subscriptionId, null, threshold);
|
||||
Assertions.assertTrue(
|
||||
getFeedEntries(subscriptionId).getEntries().stream().allMatch(Entry::isRead));
|
||||
Assertions.assertTrue(getFeedEntries(subscriptionId).getEntries().stream().allMatch(Entry::isRead));
|
||||
}
|
||||
|
||||
private void markFeedEntries(
|
||||
long subscriptionId, Instant olderThan, Instant insertedBefore) {
|
||||
private void markFeedEntries(long subscriptionId, Instant olderThan, Instant insertedBefore) {
|
||||
MarkRequest request = new MarkRequest();
|
||||
request.setId(String.valueOf(subscriptionId));
|
||||
request.setOlderThan(olderThan == null ? null : olderThan.toEpochMilli());
|
||||
request.setInsertedBefore(
|
||||
insertedBefore == null ? null : insertedBefore.toEpochMilli());
|
||||
request.setInsertedBefore(insertedBefore == null ? null : insertedBefore.toEpochMilli());
|
||||
|
||||
RestAssured.given()
|
||||
.body(request)
|
||||
@@ -202,9 +190,7 @@ class FeedIT extends BaseIT {
|
||||
|
||||
Awaitility.await()
|
||||
.atMost(Duration.ofSeconds(15))
|
||||
.until(
|
||||
() -> getSubscription(subscriptionId),
|
||||
f -> f.getLastRefresh().isAfter(threshold));
|
||||
.until(() -> getSubscription(subscriptionId), f -> f.getLastRefresh().isAfter(threshold));
|
||||
Assertions.assertEquals(2, getCategoryEntries(CategoryREST.ALL).getEntries().size());
|
||||
|
||||
Assertions.assertEquals(HttpStatus.SC_TOO_MANY_REQUESTS, forceRefreshAllFeeds());
|
||||
@@ -274,9 +260,7 @@ class FeedIT extends BaseIT {
|
||||
.response()
|
||||
.asByteArray();
|
||||
byte[] defaultFavicon =
|
||||
IOUtils.toByteArray(
|
||||
Objects.requireNonNull(
|
||||
getClass().getResource("/images/default_favicon.gif")));
|
||||
IOUtils.toByteArray(Objects.requireNonNull(getClass().getResource("/images/default_favicon.gif")));
|
||||
Assertions.assertArrayEquals(defaultFavicon, icon);
|
||||
}
|
||||
}
|
||||
@@ -297,8 +281,7 @@ class FeedIT extends BaseIT {
|
||||
}
|
||||
|
||||
void importOpml() {
|
||||
InputStream stream =
|
||||
Objects.requireNonNull(getClass().getResourceAsStream("/opml/opml_v2.0.xml"));
|
||||
InputStream stream = Objects.requireNonNull(getClass().getResourceAsStream("/opml/opml_v2.0.xml"));
|
||||
|
||||
RestAssured.given()
|
||||
.multiPart("file", "opml_v2.0.xml", stream, MediaType.MULTIPART_FORM_DATA)
|
||||
@@ -355,8 +338,7 @@ class FeedIT extends BaseIT {
|
||||
.as(Entries.class);
|
||||
Assertions.assertEquals(3, unreadEntries.getEntries().size());
|
||||
Assertions.assertTrue(
|
||||
unreadEntries.getEntries().stream()
|
||||
.noneMatch(e -> e.getTitle().toLowerCase().contains("item 4")),
|
||||
unreadEntries.getEntries().stream().noneMatch(e -> e.getTitle().toLowerCase().contains("item 4")),
|
||||
"Item 4 should be filtered out (marked as read)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,7 @@ class FeverIT extends BaseIT {
|
||||
void setup() {
|
||||
initialSetup(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.authentication =
|
||||
RestAssured.preemptive()
|
||||
.basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
|
||||
// create api key
|
||||
ProfileModificationRequest req = new ProfileModificationRequest();
|
||||
@@ -133,23 +132,11 @@ class FeverIT extends BaseIT {
|
||||
Long subscriptionId = subscribeAndWaitForEntries(getFeedUrl());
|
||||
Entry entry = getFeedEntries(subscriptionId).getEntries().getFirst();
|
||||
|
||||
client.execute(
|
||||
"_",
|
||||
new Param("mark", "item"),
|
||||
new Param("id", entry.getId()),
|
||||
new Param("as", "read"));
|
||||
Assertions.assertEquals(
|
||||
1,
|
||||
getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isRead).count());
|
||||
client.execute("_", new Param("mark", "item"), new Param("id", entry.getId()), new Param("as", "read"));
|
||||
Assertions.assertEquals(1, getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isRead).count());
|
||||
|
||||
client.execute(
|
||||
"_",
|
||||
new Param("mark", "item"),
|
||||
new Param("id", entry.getId()),
|
||||
new Param("as", "unread"));
|
||||
Assertions.assertEquals(
|
||||
0,
|
||||
getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isRead).count());
|
||||
client.execute("_", new Param("mark", "item"), new Param("id", entry.getId()), new Param("as", "unread"));
|
||||
Assertions.assertEquals(0, getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isRead).count());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -162,8 +149,7 @@ class FeverIT extends BaseIT {
|
||||
new Param("id", String.valueOf(subscriptionId)),
|
||||
new Param("as", "read"));
|
||||
|
||||
Assertions.assertTrue(
|
||||
getFeedEntries(subscriptionId).getEntries().stream().allMatch(Entry::isRead));
|
||||
Assertions.assertTrue(getFeedEntries(subscriptionId).getEntries().stream().allMatch(Entry::isRead));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -172,13 +158,9 @@ class FeverIT extends BaseIT {
|
||||
Long subscriptionId = subscribeAndWaitForEntries(getFeedUrl(), categoryId);
|
||||
|
||||
client.execute(
|
||||
"_",
|
||||
new Param("mark", "group"),
|
||||
new Param("id", String.valueOf(categoryId)),
|
||||
new Param("as", "read"));
|
||||
"_", new Param("mark", "group"), new Param("id", String.valueOf(categoryId)), new Param("as", "read"));
|
||||
|
||||
Assertions.assertTrue(
|
||||
getFeedEntries(subscriptionId).getEntries().stream().allMatch(Entry::isRead));
|
||||
Assertions.assertTrue(getFeedEntries(subscriptionId).getEntries().stream().allMatch(Entry::isRead));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -186,27 +168,13 @@ class FeverIT extends BaseIT {
|
||||
Long subscriptionId = subscribeAndWaitForEntries(getFeedUrl());
|
||||
Entry entry = getFeedEntries(subscriptionId).getEntries().getFirst();
|
||||
|
||||
client.execute(
|
||||
"_",
|
||||
new Param("mark", "item"),
|
||||
new Param("id", entry.getId()),
|
||||
new Param("as", "saved"));
|
||||
client.execute("_", new Param("mark", "item"), new Param("id", entry.getId()), new Param("as", "saved"));
|
||||
Assertions.assertEquals(
|
||||
1,
|
||||
getFeedEntries(subscriptionId).getEntries().stream()
|
||||
.filter(Entry::isStarred)
|
||||
.count());
|
||||
1, getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isStarred).count());
|
||||
|
||||
client.execute(
|
||||
"_",
|
||||
new Param("mark", "item"),
|
||||
new Param("id", entry.getId()),
|
||||
new Param("as", "unsaved"));
|
||||
client.execute("_", new Param("mark", "item"), new Param("id", entry.getId()), new Param("as", "unsaved"));
|
||||
Assertions.assertEquals(
|
||||
0,
|
||||
getFeedEntries(subscriptionId).getEntries().stream()
|
||||
.filter(Entry::isStarred)
|
||||
.count());
|
||||
0, getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isStarred).count());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -42,8 +42,7 @@ class GoogleReaderIT extends BaseIT {
|
||||
void setup() {
|
||||
initialSetup(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.authentication =
|
||||
RestAssured.preemptive()
|
||||
.basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
|
||||
// create api key
|
||||
ProfileModificationRequest req = new ProfileModificationRequest();
|
||||
@@ -144,59 +143,45 @@ class GoogleReaderIT extends BaseIT {
|
||||
@Test
|
||||
void subscriptionList() {
|
||||
subscribe(getFeedUrl());
|
||||
SubscriptionList list =
|
||||
client.get(BASE + "/reader/api/0/subscription/list").as(SubscriptionList.class);
|
||||
SubscriptionList list = client.get(BASE + "/reader/api/0/subscription/list").as(SubscriptionList.class);
|
||||
Assertions.assertEquals(1, list.getSubscriptions().size());
|
||||
Assertions.assertEquals(
|
||||
"my title for this feed", list.getSubscriptions().getFirst().getTitle());
|
||||
Assertions.assertEquals("my title for this feed", list.getSubscriptions().getFirst().getTitle());
|
||||
}
|
||||
|
||||
@Test
|
||||
void tagList() {
|
||||
createCategory("test-category");
|
||||
TagList tagList = client.get(BASE + "/reader/api/0/tag/list").as(TagList.class);
|
||||
Assertions.assertTrue(tagList.getTags().stream().anyMatch(t -> t.getId().equals("user/-/label/test-category")));
|
||||
Assertions.assertTrue(
|
||||
tagList.getTags().stream()
|
||||
.anyMatch(t -> t.getId().equals("user/-/label/test-category")));
|
||||
Assertions.assertTrue(
|
||||
tagList.getTags().stream()
|
||||
.anyMatch(t -> t.getId().equals("user/-/state/com.google/starred")));
|
||||
tagList.getTags().stream().anyMatch(t -> t.getId().equals("user/-/state/com.google/starred")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void unreadCount() {
|
||||
subscribeAndWaitForEntries(getFeedUrl());
|
||||
UnreadCounts counts =
|
||||
client.get(BASE + "/reader/api/0/unread-count").as(UnreadCounts.class);
|
||||
UnreadCounts counts = client.get(BASE + "/reader/api/0/unread-count").as(UnreadCounts.class);
|
||||
Assertions.assertTrue(
|
||||
counts.getUnreadCounts().stream()
|
||||
.anyMatch(c ->
|
||||
c.getId().equals("user/-/state/com.google/reading-list")
|
||||
&& c.getCount() == 2));
|
||||
.anyMatch(c -> c.getId().equals("user/-/state/com.google/reading-list") && c.getCount() == 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
void streamContents() {
|
||||
subscribeAndWaitForEntries(getFeedUrl());
|
||||
StreamContents contents =
|
||||
client.get(BASE + "/reader/api/0/stream/contents/reading-list")
|
||||
.as(StreamContents.class);
|
||||
client.get(BASE + "/reader/api/0/stream/contents/reading-list").as(StreamContents.class);
|
||||
Assertions.assertEquals(2, contents.getItems().size());
|
||||
Assertions.assertEquals("Item 2", contents.getItems().getFirst().getTitle());
|
||||
Assertions.assertTrue(
|
||||
contents.getItems()
|
||||
.getFirst()
|
||||
.getId()
|
||||
.matches("tag:google\\.com,2005:reader/item/[0-9a-f]{16}"));
|
||||
contents.getItems().getFirst().getId().matches("tag:google\\.com,2005:reader/item/[0-9a-f]{16}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void streamItemIds() {
|
||||
subscribeAndWaitForEntries(getFeedUrl());
|
||||
ItemRefs refs =
|
||||
client.get(
|
||||
BASE
|
||||
+ "/reader/api/0/stream/items/ids?s=user/-/state/com.google/reading-list")
|
||||
client.get(BASE + "/reader/api/0/stream/items/ids?s=user/-/state/com.google/reading-list")
|
||||
.as(ItemRefs.class);
|
||||
Assertions.assertEquals(2, refs.getItemRefs().size());
|
||||
}
|
||||
@@ -211,17 +196,13 @@ class GoogleReaderIT extends BaseIT {
|
||||
BASE + "/reader/api/0/edit-tag",
|
||||
Map.of("i", entry.getId(), "a", "user/-/state/com.google/read", "T", token));
|
||||
|
||||
Assertions.assertEquals(
|
||||
1,
|
||||
getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isRead).count());
|
||||
Assertions.assertEquals(1, getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isRead).count());
|
||||
|
||||
client.postForm(
|
||||
BASE + "/reader/api/0/edit-tag",
|
||||
Map.of("i", entry.getId(), "r", "user/-/state/com.google/read", "T", token));
|
||||
|
||||
Assertions.assertEquals(
|
||||
0,
|
||||
getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isRead).count());
|
||||
Assertions.assertEquals(0, getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isRead).count());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -232,12 +213,9 @@ class GoogleReaderIT extends BaseIT {
|
||||
Entry entry = getFeedEntries(subscriptionId).getEntries().getFirst();
|
||||
|
||||
client.postForm(
|
||||
BASE + "/reader/api/0/edit-tag",
|
||||
Map.of("i", entry.getId(), "a", "user/-/state/com.google/read"));
|
||||
BASE + "/reader/api/0/edit-tag", Map.of("i", entry.getId(), "a", "user/-/state/com.google/read"));
|
||||
|
||||
Assertions.assertEquals(
|
||||
1,
|
||||
getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isRead).count());
|
||||
Assertions.assertEquals(1, getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isRead).count());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -251,10 +229,7 @@ class GoogleReaderIT extends BaseIT {
|
||||
Map.of("i", entry.getId(), "a", "user/-/state/com.google/starred", "T", token));
|
||||
|
||||
Assertions.assertEquals(
|
||||
1,
|
||||
getFeedEntries(subscriptionId).getEntries().stream()
|
||||
.filter(Entry::isStarred)
|
||||
.count());
|
||||
1, getFeedEntries(subscriptionId).getEntries().stream().filter(Entry::isStarred).count());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -266,8 +241,7 @@ class GoogleReaderIT extends BaseIT {
|
||||
BASE + "/reader/api/0/mark-all-as-read",
|
||||
Map.of("s", "user/-/state/com.google/reading-list", "T", token));
|
||||
|
||||
Assertions.assertTrue(
|
||||
getFeedEntries(subscriptionId).getEntries().stream().allMatch(Entry::isRead));
|
||||
Assertions.assertTrue(getFeedEntries(subscriptionId).getEntries().stream().allMatch(Entry::isRead));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -276,24 +250,14 @@ class GoogleReaderIT extends BaseIT {
|
||||
|
||||
client.postForm(
|
||||
BASE + "/reader/api/0/subscription/edit",
|
||||
Map.of(
|
||||
"ac",
|
||||
"subscribe",
|
||||
"s",
|
||||
"feed/" + getFeedUrl(),
|
||||
"t",
|
||||
"new subscription",
|
||||
"T",
|
||||
token));
|
||||
Map.of("ac", "subscribe", "s", "feed/" + getFeedUrl(), "t", "new subscription", "T", token));
|
||||
|
||||
SubscriptionList list =
|
||||
client.get(BASE + "/reader/api/0/subscription/list").as(SubscriptionList.class);
|
||||
SubscriptionList list = client.get(BASE + "/reader/api/0/subscription/list").as(SubscriptionList.class);
|
||||
Assertions.assertEquals(1, list.getSubscriptions().size());
|
||||
String feedStreamId = list.getSubscriptions().getFirst().getId();
|
||||
|
||||
client.postForm(
|
||||
BASE + "/reader/api/0/subscription/edit",
|
||||
Map.of("ac", "unsubscribe", "s", feedStreamId, "T", token));
|
||||
BASE + "/reader/api/0/subscription/edit", Map.of("ac", "unsubscribe", "s", feedStreamId, "T", token));
|
||||
|
||||
list = client.get(BASE + "/reader/api/0/subscription/list").as(SubscriptionList.class);
|
||||
Assertions.assertTrue(list.getSubscriptions().isEmpty());
|
||||
@@ -302,10 +266,7 @@ class GoogleReaderIT extends BaseIT {
|
||||
private record GoogleReaderClient(String token) {
|
||||
|
||||
private RequestSpecification given() {
|
||||
return RestAssured.given()
|
||||
.auth()
|
||||
.none()
|
||||
.header("Authorization", "GoogleLogin auth=" + token);
|
||||
return RestAssured.given().auth().none().header("Authorization", "GoogleLogin auth=" + token);
|
||||
}
|
||||
|
||||
Response get(String path) {
|
||||
|
||||
@@ -15,12 +15,7 @@ class ServerIT extends BaseIT {
|
||||
@Test
|
||||
void getServerInfos() {
|
||||
ServerInfo serverInfos =
|
||||
RestAssured.given()
|
||||
.get("/rest/server/get")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.as(ServerInfo.class);
|
||||
RestAssured.given().get("/rest/server/get").then().statusCode(200).extract().as(ServerInfo.class);
|
||||
Assertions.assertTrue(serverInfos.isAllowRegistrations());
|
||||
Assertions.assertTrue(serverInfos.isSmtpEnabled());
|
||||
Assertions.assertTrue(serverInfos.isDemoAccountEnabled());
|
||||
|
||||
@@ -39,8 +39,7 @@ class UserIT extends BaseIT {
|
||||
void setup() {
|
||||
initialSetup(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.authentication =
|
||||
RestAssured.preemptive()
|
||||
.basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
|
||||
mailbox.clear();
|
||||
}
|
||||
@@ -52,8 +51,7 @@ class UserIT extends BaseIT {
|
||||
|
||||
@Test
|
||||
void resetPassword() {
|
||||
String session =
|
||||
login().stream().map(HttpCookie::toString).collect(Collectors.joining(";"));
|
||||
String session = login().stream().map(HttpCookie::toString).collect(Collectors.joining(";"));
|
||||
|
||||
PasswordResetRequest req = new PasswordResetRequest();
|
||||
req.setEmail("admin@commafeed.com");
|
||||
@@ -70,9 +68,7 @@ class UserIT extends BaseIT {
|
||||
|
||||
MailMessage message = mails.getFirst();
|
||||
Assertions.assertEquals("CommaFeed - Password recovery", message.getSubject());
|
||||
Assertions.assertTrue(
|
||||
message.getHtml()
|
||||
.startsWith("You asked for password recovery for account 'admin'"));
|
||||
Assertions.assertTrue(message.getHtml().startsWith("You asked for password recovery for account 'admin'"));
|
||||
Assertions.assertTrue(message.getHtml().contains("https://commafeed.example.com"));
|
||||
Assertions.assertEquals("admin@commafeed.com", message.getTo().getFirst());
|
||||
|
||||
@@ -116,8 +112,7 @@ class UserIT extends BaseIT {
|
||||
.then()
|
||||
.statusCode(401);
|
||||
|
||||
RestAssured.authentication =
|
||||
RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, newPassword);
|
||||
RestAssured.authentication = RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, newPassword);
|
||||
RestAssured.given().get("rest/user/settings").then().statusCode(200);
|
||||
}
|
||||
|
||||
@@ -156,14 +151,12 @@ class UserIT extends BaseIT {
|
||||
|
||||
Elements links = Jsoup.parse(html).select("a");
|
||||
Assertions.assertEquals(1, links.size());
|
||||
Assertions.assertTrue(
|
||||
links.getFirst().attr("href").startsWith("https://commafeed.example.com"));
|
||||
Assertions.assertTrue(links.getFirst().attr("href").startsWith("https://commafeed.example.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveSettings() {
|
||||
Settings settings =
|
||||
RestAssured.given().get("rest/user/settings").then().extract().as(Settings.class);
|
||||
Settings settings = RestAssured.given().get("rest/user/settings").then().extract().as(Settings.class);
|
||||
settings.setLanguage("test");
|
||||
RestAssured.given()
|
||||
.body(settings)
|
||||
@@ -172,8 +165,7 @@ class UserIT extends BaseIT {
|
||||
.then()
|
||||
.statusCode(200);
|
||||
|
||||
Settings updatedSettings =
|
||||
RestAssured.given().get("rest/user/settings").then().extract().as(Settings.class);
|
||||
Settings updatedSettings = RestAssured.given().get("rest/user/settings").then().extract().as(Settings.class);
|
||||
Assertions.assertEquals("test", updatedSettings.getLanguage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@ class CustomCodeIT extends BaseIT {
|
||||
void setup() {
|
||||
initialSetup(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.authentication =
|
||||
RestAssured.preemptive()
|
||||
.basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -34,12 +33,7 @@ class CustomCodeIT extends BaseIT {
|
||||
void test() {
|
||||
// get settings
|
||||
Settings settings =
|
||||
RestAssured.given()
|
||||
.get("rest/user/settings")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.extract()
|
||||
.as(Settings.class);
|
||||
RestAssured.given().get("rest/user/settings").then().statusCode(200).extract().as(Settings.class);
|
||||
|
||||
// update settings
|
||||
settings.setCustomJs("custom-js");
|
||||
@@ -52,11 +46,7 @@ class CustomCodeIT extends BaseIT {
|
||||
.statusCode(HttpStatus.SC_OK);
|
||||
|
||||
// check custom code servlets
|
||||
RestAssured.given()
|
||||
.get("custom_js.js")
|
||||
.then()
|
||||
.statusCode(HttpStatus.SC_OK)
|
||||
.body(CoreMatchers.is("custom-js"));
|
||||
RestAssured.given().get("custom_js.js").then().statusCode(HttpStatus.SC_OK).body(CoreMatchers.is("custom-js"));
|
||||
RestAssured.given()
|
||||
.get("custom_css.css")
|
||||
.then()
|
||||
|
||||
@@ -33,9 +33,7 @@ class LogoutIT extends BaseIT {
|
||||
RestAssured.given()
|
||||
.header(
|
||||
HttpHeaders.COOKIE,
|
||||
cookies.stream()
|
||||
.map(HttpCookie::toString)
|
||||
.collect(Collectors.joining(";")))
|
||||
cookies.stream().map(HttpCookie::toString).collect(Collectors.joining(";")))
|
||||
.redirects()
|
||||
.follow(false)
|
||||
.get("logout")
|
||||
@@ -46,8 +44,6 @@ class LogoutIT extends BaseIT {
|
||||
|
||||
List<String> setCookieHeaders = responseHeaders.getValues(HttpHeaders.SET_COOKIE);
|
||||
Assertions.assertTrue(
|
||||
setCookieHeaders.stream()
|
||||
.flatMap(c -> HttpCookie.parse(c).stream())
|
||||
.allMatch(c -> c.getMaxAge() == 0));
|
||||
setCookieHeaders.stream().flatMap(c -> HttpCookie.parse(c).stream()).allMatch(c -> c.getMaxAge() == 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@ class NextUnreadIT extends BaseIT {
|
||||
void setup() {
|
||||
initialSetup(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.authentication =
|
||||
RestAssured.preemptive()
|
||||
.basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
RestAssured.preemptive().basic(TestConstants.ADMIN_USERNAME, TestConstants.ADMIN_PASSWORD);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
||||
@@ -15,8 +15,7 @@ class CommaFeedPropertiesGeneratorTest {
|
||||
@Test
|
||||
void testGenerate() throws Exception {
|
||||
InputStream model = getClass().getResourceAsStream("/properties/quarkus-config-model.yaml");
|
||||
InputStream javadoc =
|
||||
getClass().getResourceAsStream("/properties/quarkus-config-javadoc.yaml");
|
||||
InputStream javadoc = getClass().getResourceAsStream("/properties/quarkus-config-javadoc.yaml");
|
||||
URL output = getClass().getResource("/properties/output.properties");
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
new CommaFeedPropertiesGenerator().generate(model, javadoc, baos);
|
||||
|
||||
Reference in New Issue
Block a user