forked from Archives/Athou_commafeed
WIP
This commit is contained in:
@@ -1,125 +0,0 @@
|
||||
package com.commafeed;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.mockserver.socket.PortFactory;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||
import org.testcontainers.containers.MariaDBContainer;
|
||||
import org.testcontainers.containers.MySQLContainer;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.commafeed.CommaFeedConfiguration.CacheType;
|
||||
|
||||
import io.dropwizard.testing.ConfigOverride;
|
||||
import io.dropwizard.testing.ResourceHelpers;
|
||||
import io.dropwizard.testing.junit5.DropwizardAppExtension;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
|
||||
public class CommaFeedDropwizardAppExtension extends DropwizardAppExtension<CommaFeedConfiguration> {
|
||||
private static final String TEST_DATABASE = System.getenv().getOrDefault("TEST_DATABASE", "h2");
|
||||
private static final boolean REDIS_ENABLED = Boolean.parseBoolean(System.getenv().getOrDefault("REDIS", "false"));
|
||||
|
||||
private static final ConfigOverride[] CONFIG_OVERRIDES;
|
||||
private static final List<String> DROP_ALL_STATEMENTS;
|
||||
static {
|
||||
List<ConfigOverride> overrides = new ArrayList<>();
|
||||
overrides.add(ConfigOverride.config("server.applicationConnectors[0].port", String.valueOf(PortFactory.findFreePort())));
|
||||
|
||||
Properties imageNames = readProperties("/docker-images.properties");
|
||||
|
||||
DatabaseConfiguration config = buildConfiguration(TEST_DATABASE, imageNames.getProperty(TEST_DATABASE));
|
||||
JdbcDatabaseContainer<?> container = config.container();
|
||||
if (container != null) {
|
||||
container.withDatabaseName("commafeed");
|
||||
container.withEnv("TZ", "UTC");
|
||||
container.start();
|
||||
|
||||
overrides.add(ConfigOverride.config("database.url", container.getJdbcUrl()));
|
||||
overrides.add(ConfigOverride.config("database.user", container.getUsername()));
|
||||
overrides.add(ConfigOverride.config("database.password", container.getPassword()));
|
||||
overrides.add(ConfigOverride.config("database.driverClass", container.getDriverClassName()));
|
||||
}
|
||||
|
||||
if (REDIS_ENABLED) {
|
||||
GenericContainer<?> redis = new GenericContainer<>(DockerImageName.parse(imageNames.getProperty("redis")))
|
||||
.withExposedPorts(6379);
|
||||
redis.start();
|
||||
|
||||
overrides.add(ConfigOverride.config("app.cache", "redis"));
|
||||
overrides.add(ConfigOverride.config("redis.host", redis.getHost()));
|
||||
overrides.add(ConfigOverride.config("redis.port", redis.getMappedPort(6379).toString()));
|
||||
}
|
||||
|
||||
CONFIG_OVERRIDES = overrides.toArray(new ConfigOverride[0]);
|
||||
DROP_ALL_STATEMENTS = config.dropAllStatements();
|
||||
}
|
||||
|
||||
public CommaFeedDropwizardAppExtension() {
|
||||
super(CommaFeedApplication.class, ResourceHelpers.resourceFilePath("config.test.yml"), CONFIG_OVERRIDES);
|
||||
}
|
||||
|
||||
private static DatabaseConfiguration buildConfiguration(String databaseName, String imageName) {
|
||||
if ("postgresql".equals(databaseName)) {
|
||||
JdbcDatabaseContainer<?> container = new PostgreSQLContainer<>(imageName).withTmpFs(Map.of("/var/lib/postgresql/data", "rw"));
|
||||
return new DatabaseConfiguration(container, List.of("DROP SCHEMA public CASCADE", "CREATE SCHEMA public"));
|
||||
} else if ("mysql".equals(databaseName)) {
|
||||
JdbcDatabaseContainer<?> container = new MySQLContainer<>(imageName).withTmpFs(Map.of("/var/lib/mysql", "rw"));
|
||||
return new DatabaseConfiguration(container, List.of("DROP DATABASE IF EXISTS commafeed", " CREATE DATABASE commafeed"));
|
||||
} else if ("mariadb".equals(databaseName)) {
|
||||
JdbcDatabaseContainer<?> container = new MariaDBContainer<>(imageName).withTmpFs(Map.of("/var/lib/mysql", "rw"));
|
||||
return new DatabaseConfiguration(container, List.of("DROP DATABASE IF EXISTS commafeed", " CREATE DATABASE commafeed"));
|
||||
} else {
|
||||
// h2
|
||||
return new DatabaseConfiguration(null, List.of("DROP ALL OBJECTS"));
|
||||
}
|
||||
}
|
||||
|
||||
private static Properties readProperties(String path) {
|
||||
Properties properties = new Properties();
|
||||
try (InputStream is = CommaFeedDropwizardAppExtension.class.getResourceAsStream(path)) {
|
||||
properties.load(is);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("could not read resource " + path, e);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void after() {
|
||||
super.after();
|
||||
|
||||
// clean database after each test
|
||||
DataSource dataSource = getConfiguration().getDataSourceFactory().build(new MetricRegistry(), "cleanup");
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
for (String statement : DROP_ALL_STATEMENTS) {
|
||||
connection.prepareStatement(statement).executeUpdate();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("could not cleanup database", e);
|
||||
}
|
||||
|
||||
// clean redis cache after each test
|
||||
if (getConfiguration().getApplicationSettings().getCache() == CacheType.REDIS) {
|
||||
try (JedisPool pool = getConfiguration().getRedisPoolFactory().build(); Jedis jedis = pool.getResource()) {
|
||||
jedis.flushAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private record DatabaseConfiguration(JdbcDatabaseContainer<?> container, List<String> dropAllStatements) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.commafeed;
|
||||
|
||||
import org.kohsuke.MetaInfServices;
|
||||
|
||||
import com.commafeed.backend.service.db.DatabaseStartupService;
|
||||
|
||||
import io.quarkus.liquibase.LiquibaseFactory;
|
||||
import io.quarkus.test.junit.callback.QuarkusTestBeforeEachCallback;
|
||||
import io.quarkus.test.junit.callback.QuarkusTestMethodContext;
|
||||
import jakarta.enterprise.inject.spi.CDI;
|
||||
import liquibase.Liquibase;
|
||||
import liquibase.exception.LiquibaseException;
|
||||
|
||||
/**
|
||||
* Resets database between tests
|
||||
*/
|
||||
@MetaInfServices
|
||||
public class DatabaseReset implements QuarkusTestBeforeEachCallback {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void beforeEach(QuarkusTestMethodContext context) {
|
||||
LiquibaseFactory liquibaseFactory = CDI.current().select(LiquibaseFactory.class).get();
|
||||
try (Liquibase liquibase = liquibaseFactory.createLiquibase()) {
|
||||
liquibase.dropAll();
|
||||
liquibase.update(liquibaseFactory.createContexts(), liquibaseFactory.createLabels());
|
||||
} catch (LiquibaseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
DatabaseStartupService databaseStartupService = CDI.current().select(DatabaseStartupService.class).get();
|
||||
databaseStartupService.populateInitialData();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,16 @@
|
||||
package com.commafeed.backend;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.hc.client5.http.ConnectTimeoutException;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.apache.hc.core5.http.HttpStatus;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -26,13 +28,13 @@ import org.mockserver.model.MediaType;
|
||||
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.commafeed.CommaFeedConfiguration.ApplicationSettings;
|
||||
import com.commafeed.CommaFeedVersion;
|
||||
import com.commafeed.backend.HttpGetter.HttpResponseException;
|
||||
import com.commafeed.backend.HttpGetter.HttpResult;
|
||||
import com.commafeed.backend.HttpGetter.NotModifiedException;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
import io.dropwizard.util.DataSize;
|
||||
import io.quarkus.runtime.configuration.MemorySize;
|
||||
|
||||
@ExtendWith(MockServerExtension.class)
|
||||
class HttpGetterTest {
|
||||
@@ -51,21 +53,17 @@ class HttpGetterTest {
|
||||
this.feedUrl = "http://localhost:" + this.mockServerClient.getPort() + "/";
|
||||
this.feedContent = IOUtils.toByteArray(Objects.requireNonNull(getClass().getResource("/feed/rss.xml")));
|
||||
|
||||
ApplicationSettings settings = new ApplicationSettings();
|
||||
settings.setUserAgent("http-getter-test");
|
||||
settings.setBackgroundThreads(3);
|
||||
settings.setMaxFeedResponseSize(DataSize.kilobytes(10));
|
||||
CommaFeedConfiguration config = Mockito.mock(CommaFeedConfiguration.class, Mockito.RETURNS_DEEP_STUBS);
|
||||
Mockito.when(config.feedRefresh().userAgent()).thenReturn(Optional.of("http-getter-test"));
|
||||
Mockito.when(config.feedRefresh().httpThreads()).thenReturn(3);
|
||||
Mockito.when(config.feedRefresh().maxResponseSize()).thenReturn(new MemorySize(new BigInteger("10000")));
|
||||
|
||||
CommaFeedConfiguration config = new CommaFeedConfiguration();
|
||||
config.setApplicationSettings(settings);
|
||||
|
||||
this.getter = new HttpGetter(config, Mockito.mock(MetricRegistry.class));
|
||||
this.getter = new HttpGetter(config, Mockito.mock(CommaFeedVersion.class), Mockito.mock(MetricRegistry.class));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(
|
||||
ints = { HttpStatus.UNAUTHORIZED_401, HttpStatus.FORBIDDEN_403, HttpStatus.NOT_FOUND_404,
|
||||
HttpStatus.INTERNAL_SERVER_ERROR_500 })
|
||||
ints = { HttpStatus.SC_UNAUTHORIZED, HttpStatus.SC_FORBIDDEN, HttpStatus.SC_NOT_FOUND, HttpStatus.SC_INTERNAL_SERVER_ERROR })
|
||||
void errorCodes(int code) {
|
||||
this.mockServerClient.when(HttpRequest.request().withMethod("GET")).respond(HttpResponse.response().withStatusCode(code));
|
||||
|
||||
@@ -93,8 +91,8 @@ class HttpGetterTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(
|
||||
ints = { HttpStatus.MOVED_PERMANENTLY_301, HttpStatus.MOVED_TEMPORARILY_302, HttpStatus.TEMPORARY_REDIRECT_307,
|
||||
HttpStatus.PERMANENT_REDIRECT_308 })
|
||||
ints = { HttpStatus.SC_MOVED_PERMANENTLY, HttpStatus.SC_MOVED_TEMPORARILY, HttpStatus.SC_TEMPORARY_REDIRECT,
|
||||
HttpStatus.SC_PERMANENT_REDIRECT })
|
||||
void followRedirects(int code) throws Exception {
|
||||
// first redirect
|
||||
this.mockServerClient.when(HttpRequest.request().withMethod("GET").withPath("/"))
|
||||
@@ -129,7 +127,7 @@ class HttpGetterTest {
|
||||
void connectTimeout() {
|
||||
// try to connect to a non-routable address
|
||||
// https://stackoverflow.com/a/904609
|
||||
Assertions.assertThrows(ConnectTimeoutException.class, () -> getter.getBinary("http://10.255.255.1", 2000));
|
||||
Assertions.assertThrows(ConnectTimeoutException.class, () -> getter.getBinary("http://10.255.255.1", 500));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -144,7 +142,7 @@ class HttpGetterTest {
|
||||
@Test
|
||||
void lastModifiedReturns304() {
|
||||
this.mockServerClient.when(HttpRequest.request().withMethod("GET").withHeader(HttpHeaders.IF_MODIFIED_SINCE, "123456"))
|
||||
.respond(HttpResponse.response().withStatusCode(HttpStatus.NOT_MODIFIED_304));
|
||||
.respond(HttpResponse.response().withStatusCode(HttpStatus.SC_NOT_MODIFIED));
|
||||
|
||||
Assertions.assertThrows(NotModifiedException.class, () -> getter.getBinary(this.feedUrl, "123456", null, TIMEOUT));
|
||||
}
|
||||
@@ -152,7 +150,7 @@ class HttpGetterTest {
|
||||
@Test
|
||||
void eTagReturns304() {
|
||||
this.mockServerClient.when(HttpRequest.request().withMethod("GET").withHeader(HttpHeaders.IF_NONE_MATCH, "78910"))
|
||||
.respond(HttpResponse.response().withStatusCode(HttpStatus.NOT_MODIFIED_304));
|
||||
.respond(HttpResponse.response().withStatusCode(HttpStatus.SC_NOT_MODIFIED));
|
||||
|
||||
Assertions.assertThrows(NotModifiedException.class, () -> getter.getBinary(this.feedUrl, null, "78910", TIMEOUT));
|
||||
}
|
||||
@@ -195,7 +193,7 @@ class HttpGetterTest {
|
||||
|
||||
@Test
|
||||
void largeFeedWithContentLengthHeader() {
|
||||
byte[] bytes = new byte[(int) DataSize.kilobytes(100).toBytes()];
|
||||
byte[] bytes = new byte[100000];
|
||||
Arrays.fill(bytes, (byte) 1);
|
||||
this.mockServerClient.when(HttpRequest.request().withMethod("GET")).respond(HttpResponse.response().withBody(bytes));
|
||||
|
||||
@@ -205,7 +203,7 @@ class HttpGetterTest {
|
||||
|
||||
@Test
|
||||
void largeFeedWithoutContentLengthHeader() {
|
||||
byte[] bytes = new byte[(int) DataSize.kilobytes(100).toBytes()];
|
||||
byte[] bytes = new byte[100000];
|
||||
Arrays.fill(bytes, (byte) 1);
|
||||
this.mockServerClient.when(HttpRequest.request().withMethod("GET"))
|
||||
.respond(HttpResponse.response()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.commafeed.backend.feed;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -28,7 +28,7 @@ class FeedFetcherTest {
|
||||
private HttpGetter getter;
|
||||
|
||||
@Mock
|
||||
private Set<FeedURLProvider> urlProviders;
|
||||
private List<FeedURLProvider> urlProviders;
|
||||
|
||||
private FeedFetcher fetcher;
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.commafeed.backend.service.db;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
class H2MigrationServiceTest {
|
||||
|
||||
@TempDir
|
||||
private Path root;
|
||||
|
||||
@Test
|
||||
void testMigrateIfNeeded() throws IOException {
|
||||
Path path = root.resolve("database.mv.db");
|
||||
Files.copy(Objects.requireNonNull(getClass().getResourceAsStream("/h2-migration/database-v2.1.214.mv.db")), path);
|
||||
|
||||
H2MigrationService service = new H2MigrationService();
|
||||
Assertions.assertEquals(2, service.getH2FileFormat(path));
|
||||
|
||||
service.migrateIfNeeded(path, "sa", "sa");
|
||||
Assertions.assertEquals(3, service.getH2FileFormat(path));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +1,35 @@
|
||||
package com.commafeed.e2e;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import com.commafeed.CommaFeedDropwizardAppExtension;
|
||||
import com.microsoft.playwright.Browser;
|
||||
import com.microsoft.playwright.Locator;
|
||||
import com.microsoft.playwright.Page;
|
||||
import com.microsoft.playwright.Playwright;
|
||||
import com.microsoft.playwright.assertions.PlaywrightAssertions;
|
||||
import com.microsoft.playwright.options.AriaRole;
|
||||
|
||||
import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
|
||||
@ExtendWith(DropwizardExtensionsSupport.class)
|
||||
class AuthentificationIT extends PlaywrightTestBase {
|
||||
@QuarkusTest
|
||||
class AuthentificationIT {
|
||||
|
||||
private static final CommaFeedDropwizardAppExtension EXT = new CommaFeedDropwizardAppExtension();
|
||||
private final Playwright playwright = Playwright.create();
|
||||
private final Browser browser = playwright.chromium().launch();
|
||||
|
||||
private Page page;
|
||||
|
||||
@BeforeEach
|
||||
void init() {
|
||||
page = browser.newContext().newPage();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanup() {
|
||||
playwright.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loginFail() {
|
||||
@@ -29,7 +44,7 @@ class AuthentificationIT extends PlaywrightTestBase {
|
||||
void loginSuccess() {
|
||||
page.navigate(getLoginPageUrl());
|
||||
PlaywrightTestUtils.login(page);
|
||||
PlaywrightAssertions.assertThat(page).hasURL("http://localhost:" + EXT.getLocalPort() + "/#/app/category/all");
|
||||
PlaywrightAssertions.assertThat(page).hasURL("http://localhost:8085/#/app/category/all");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -56,10 +71,10 @@ class AuthentificationIT extends PlaywrightTestBase {
|
||||
page.getByPlaceholder("E-mail address").fill("user@domain.com");
|
||||
page.getByPlaceholder("Password").fill("MyPassword1!");
|
||||
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Sign up")).click();
|
||||
PlaywrightAssertions.assertThat(page).hasURL("http://localhost:" + EXT.getLocalPort() + "/#/app/category/all");
|
||||
PlaywrightAssertions.assertThat(page).hasURL("http://localhost:8085/#/app/category/all");
|
||||
}
|
||||
|
||||
private String getLoginPageUrl() {
|
||||
return "http://localhost:" + EXT.getLocalPort() + "/#/login";
|
||||
return "http://localhost:8085/#/login";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
package com.commafeed.e2e;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.api.extension.TestWatcher;
|
||||
|
||||
import com.microsoft.playwright.Browser;
|
||||
import com.microsoft.playwright.Browser.NewContextOptions;
|
||||
import com.microsoft.playwright.BrowserContext;
|
||||
import com.microsoft.playwright.Page;
|
||||
import com.microsoft.playwright.Playwright;
|
||||
import com.microsoft.playwright.Tracing;
|
||||
|
||||
/**
|
||||
* Base class for all Playwright tests.
|
||||
*
|
||||
* <ul>
|
||||
* <li>Takes a screenshot on failure</li>
|
||||
* <li>Keeps the video on failure</li>
|
||||
* <li>Saves a trace file on failure</li>
|
||||
* </ul>
|
||||
*
|
||||
* inspired by https://github.com/microsoft/playwright-java/issues/503#issuecomment-872636373
|
||||
*
|
||||
*/
|
||||
@ExtendWith(PlaywrightTestBase.SaveArtifactsOnTestFailed.class)
|
||||
public abstract class PlaywrightTestBase {
|
||||
|
||||
private static Playwright playwright;
|
||||
private static Browser browser;
|
||||
|
||||
protected Page page;
|
||||
private BrowserContext context;
|
||||
|
||||
@BeforeAll
|
||||
static void initBrowser() {
|
||||
playwright = Playwright.create();
|
||||
browser = playwright.chromium().launch();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void closeBrowser() {
|
||||
playwright.close();
|
||||
}
|
||||
|
||||
protected void customizeNewContextOptions(NewContextOptions options) {
|
||||
// override in subclasses to customize the browser context
|
||||
}
|
||||
|
||||
protected static class SaveArtifactsOnTestFailed implements TestWatcher, BeforeEachCallback {
|
||||
|
||||
// defined in the config of maven-failsafe-plugin in pom.xml
|
||||
private final String buildDirectory = System.getProperty("buildDirectory", "target");
|
||||
private final String directory = buildDirectory + "/playwright-artifacts";
|
||||
|
||||
@Override
|
||||
public void beforeEach(ExtensionContext context) {
|
||||
PlaywrightTestBase testInstance = getTestInstance(context);
|
||||
|
||||
NewContextOptions newContextOptions = new Browser.NewContextOptions().setRecordVideoDir(Paths.get(directory));
|
||||
testInstance.customizeNewContextOptions(newContextOptions);
|
||||
testInstance.context = PlaywrightTestBase.browser.newContext(newContextOptions);
|
||||
testInstance.context.tracing().start(new Tracing.StartOptions().setScreenshots(true).setSnapshots(true));
|
||||
|
||||
testInstance.page = testInstance.context.newPage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testFailed(ExtensionContext context, Throwable cause) {
|
||||
PlaywrightTestBase testInstance = getTestInstance(context);
|
||||
|
||||
String fileName = getFileName(context);
|
||||
|
||||
saveScreenshot(testInstance, fileName);
|
||||
saveTrace(testInstance, fileName);
|
||||
|
||||
testInstance.context.close();
|
||||
|
||||
saveVideo(testInstance, fileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testAborted(ExtensionContext context, Throwable cause) {
|
||||
PlaywrightTestBase testInstance = getTestInstance(context);
|
||||
testInstance.context.close();
|
||||
testInstance.page.video().delete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testDisabled(ExtensionContext context, Optional<String> reason) {
|
||||
PlaywrightTestBase testInstance = getTestInstance(context);
|
||||
testInstance.context.close();
|
||||
testInstance.page.video().delete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testSuccessful(ExtensionContext context) {
|
||||
PlaywrightTestBase testInstance = getTestInstance(context);
|
||||
testInstance.context.close();
|
||||
testInstance.page.video().delete();
|
||||
}
|
||||
|
||||
private PlaywrightTestBase getTestInstance(ExtensionContext context) {
|
||||
return (PlaywrightTestBase) context.getRequiredTestInstance();
|
||||
}
|
||||
|
||||
private String getFileName(ExtensionContext context) {
|
||||
return String.format("%s.%s-%s", context.getRequiredTestClass().getSimpleName(), context.getRequiredTestMethod().getName(),
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd--HH-mm-ss").format(ZonedDateTime.now()));
|
||||
}
|
||||
|
||||
private void saveScreenshot(PlaywrightTestBase testInstance, String fileName) {
|
||||
byte[] screenshot = testInstance.page.screenshot();
|
||||
try {
|
||||
Files.write(Paths.get(directory, fileName + ".png"), screenshot);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveTrace(PlaywrightTestBase testInstance, String fileName) {
|
||||
testInstance.context.tracing().stop(new Tracing.StopOptions().setPath(Paths.get(directory, fileName + ".zip")));
|
||||
}
|
||||
|
||||
private void saveVideo(PlaywrightTestBase testInstance, String fileName) {
|
||||
testInstance.page.video().saveAs(Paths.get(directory, fileName + ".webm"));
|
||||
testInstance.page.video().delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,43 +6,51 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockserver.client.MockServerClient;
|
||||
import org.mockserver.junit.jupiter.MockServerExtension;
|
||||
import org.mockserver.integration.ClientAndServer;
|
||||
import org.mockserver.model.HttpRequest;
|
||||
import org.mockserver.model.HttpResponse;
|
||||
|
||||
import com.commafeed.CommaFeedDropwizardAppExtension;
|
||||
import com.microsoft.playwright.Browser;
|
||||
import com.microsoft.playwright.Locator;
|
||||
import com.microsoft.playwright.Page;
|
||||
import com.microsoft.playwright.Playwright;
|
||||
import com.microsoft.playwright.assertions.PlaywrightAssertions;
|
||||
import com.microsoft.playwright.options.AriaRole;
|
||||
|
||||
import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
|
||||
@ExtendWith(DropwizardExtensionsSupport.class)
|
||||
@ExtendWith(MockServerExtension.class)
|
||||
class ReadingIT extends PlaywrightTestBase {
|
||||
@QuarkusTest
|
||||
class ReadingIT {
|
||||
|
||||
private static final CommaFeedDropwizardAppExtension EXT = new CommaFeedDropwizardAppExtension();
|
||||
private final Playwright playwright = Playwright.create();
|
||||
private final Browser browser = playwright.chromium().launch();
|
||||
|
||||
private Page page;
|
||||
private MockServerClient mockServerClient;
|
||||
|
||||
@BeforeEach
|
||||
void init(MockServerClient mockServerClient) throws IOException {
|
||||
this.mockServerClient = mockServerClient;
|
||||
void init() throws IOException {
|
||||
this.page = browser.newContext().newPage();
|
||||
this.mockServerClient = ClientAndServer.startClientAndServer(0);
|
||||
this.mockServerClient.when(HttpRequest.request().withMethod("GET"))
|
||||
.respond(HttpResponse.response()
|
||||
.withBody(IOUtils.toString(getClass().getResource("/feed/rss.xml"), StandardCharsets.UTF_8))
|
||||
.withDelay(TimeUnit.MILLISECONDS, 100));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanup() {
|
||||
playwright.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void scenario() {
|
||||
// login
|
||||
page.navigate("http://localhost:" + EXT.getLocalPort());
|
||||
page.navigate("http://localhost:8085");
|
||||
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Log in")).click();
|
||||
PlaywrightTestUtils.login(page);
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package com.commafeed.frontend.auth;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import com.commafeed.backend.dao.UserDAO;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.service.UserService;
|
||||
import com.commafeed.backend.service.internal.PostLoginActivities;
|
||||
import com.commafeed.frontend.session.SessionHelper;
|
||||
|
||||
class SecurityCheckFactoryTest {
|
||||
|
||||
@Test
|
||||
void cookieLoginShouldPerformPostLoginActivities() {
|
||||
User userInSession = new User();
|
||||
UserDAO userDAO = Mockito.mock(UserDAO.class);
|
||||
Mockito.when(userDAO.findById(1L)).thenReturn(userInSession);
|
||||
|
||||
SessionHelper sessionHelper = Mockito.mock(SessionHelper.class);
|
||||
Mockito.when(sessionHelper.getLoggedInUserId()).thenReturn(Optional.of(1L));
|
||||
|
||||
PostLoginActivities postLoginActivities = Mockito.mock(PostLoginActivities.class);
|
||||
|
||||
UserService service = new UserService(null, null, null, null, null, null, null, postLoginActivities);
|
||||
|
||||
SecurityCheckFactory factory = new SecurityCheckFactory(userDAO, service, null, null, null, false);
|
||||
factory.cookieSessionLogin(sessionHelper);
|
||||
|
||||
Mockito.verify(postLoginActivities).executeFor(userInSession);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package com.commafeed.frontend.resource;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.model.UserRole.Role;
|
||||
import com.commafeed.backend.service.UserService;
|
||||
import com.commafeed.frontend.model.request.LoginRequest;
|
||||
import com.commafeed.frontend.model.request.RegistrationRequest;
|
||||
import com.commafeed.frontend.session.SessionHelper;
|
||||
|
||||
class UserRestTest {
|
||||
|
||||
@Test
|
||||
void loginShouldNotPopulateHttpSessionIfUnsuccessfull() {
|
||||
// Absent user
|
||||
Optional<User> absentUser = Optional.empty();
|
||||
|
||||
// Create UserService partial mock
|
||||
UserService service = Mockito.mock(UserService.class);
|
||||
Mockito.when(service.login("user", "password")).thenReturn(absentUser);
|
||||
|
||||
UserREST userREST = new UserREST(null, null, null, service, null, null, null);
|
||||
SessionHelper sessionHelper = Mockito.mock(SessionHelper.class);
|
||||
|
||||
LoginRequest req = new LoginRequest();
|
||||
req.setName("user");
|
||||
req.setPassword("password");
|
||||
|
||||
userREST.login(req, sessionHelper);
|
||||
|
||||
Mockito.verify(sessionHelper, Mockito.never()).setLoggedInUser(Mockito.any(User.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void loginShouldPopulateHttpSessionIfSuccessfull() {
|
||||
// Create a user
|
||||
User user = new User();
|
||||
|
||||
// Create UserService mock
|
||||
UserService service = Mockito.mock(UserService.class);
|
||||
Mockito.when(service.login("user", "password")).thenReturn(Optional.of(user));
|
||||
|
||||
LoginRequest req = new LoginRequest();
|
||||
req.setName("user");
|
||||
req.setPassword("password");
|
||||
|
||||
UserREST userREST = new UserREST(null, null, null, service, null, null, null);
|
||||
SessionHelper sessionHelper = Mockito.mock(SessionHelper.class);
|
||||
|
||||
userREST.login(req, sessionHelper);
|
||||
|
||||
Mockito.verify(sessionHelper).setLoggedInUser(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerShouldRegisterAndThenLogin() {
|
||||
// Create UserService mock
|
||||
UserService service = Mockito.mock(UserService.class);
|
||||
|
||||
RegistrationRequest req = new RegistrationRequest();
|
||||
req.setName("user");
|
||||
req.setPassword("password");
|
||||
req.setEmail("test@test.com");
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(service);
|
||||
|
||||
SessionHelper sessionHelper = Mockito.mock(SessionHelper.class);
|
||||
UserREST userREST = new UserREST(null, null, null, service, null, null, null);
|
||||
|
||||
userREST.registerUser(req, sessionHelper);
|
||||
|
||||
inOrder.verify(service).register("user", "password", "test@test.com", Collections.singletonList(Role.USER));
|
||||
inOrder.verify(service).login("user", "password");
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerShouldPopulateHttpSession() {
|
||||
// Create a user
|
||||
User user = new User();
|
||||
|
||||
// Create UserService mock
|
||||
UserService service = Mockito.mock(UserService.class);
|
||||
Mockito.when(service.register(Mockito.any(String.class), Mockito.any(String.class), Mockito.any(String.class),
|
||||
ArgumentMatchers.anyList())).thenReturn(user);
|
||||
Mockito.when(service.login(Mockito.any(String.class), Mockito.any(String.class))).thenReturn(Optional.of(user));
|
||||
|
||||
RegistrationRequest req = new RegistrationRequest();
|
||||
req.setName("user");
|
||||
req.setPassword("password");
|
||||
req.setEmail("test@test.com");
|
||||
|
||||
SessionHelper sessionHelper = Mockito.mock(SessionHelper.class);
|
||||
UserREST userREST = new UserREST(null, null, null, service, null, null, null);
|
||||
|
||||
userREST.registerUser(req, sessionHelper);
|
||||
|
||||
Mockito.verify(sessionHelper).setLoggedInUser(user);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.commafeed.frontend.session;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
|
||||
class SessionHelperTest {
|
||||
|
||||
@Test
|
||||
void gettingUserDoesNotCreateSession() {
|
||||
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||
|
||||
SessionHelper sessionHelper = new SessionHelper(request);
|
||||
sessionHelper.getLoggedInUserId();
|
||||
|
||||
Mockito.verify(request).getSession(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void gettingUserShouldNotReturnUserIfThereIsNoPreexistingHttpSession() {
|
||||
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||
Mockito.when(request.getSession(false)).thenReturn(null);
|
||||
|
||||
SessionHelper sessionHelper = new SessionHelper(request);
|
||||
Optional<Long> userId = sessionHelper.getLoggedInUserId();
|
||||
|
||||
Assertions.assertFalse(userId.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void gettingUserShouldNotReturnUserIfUserNotPresentInHttpSession() {
|
||||
HttpSession session = Mockito.mock(HttpSession.class);
|
||||
Mockito.when(session.getAttribute(SessionHelper.SESSION_KEY_USER_ID)).thenReturn(null);
|
||||
|
||||
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||
Mockito.when(request.getSession(false)).thenReturn(session);
|
||||
|
||||
SessionHelper sessionHelper = new SessionHelper(request);
|
||||
Optional<Long> userId = sessionHelper.getLoggedInUserId();
|
||||
|
||||
Assertions.assertFalse(userId.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void gettingUserShouldReturnUserIfUserPresentInHttpSession() {
|
||||
HttpSession session = Mockito.mock(HttpSession.class);
|
||||
Mockito.when(session.getAttribute(SessionHelper.SESSION_KEY_USER_ID)).thenReturn(1L);
|
||||
|
||||
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||
Mockito.when(request.getSession(false)).thenReturn(session);
|
||||
|
||||
SessionHelper sessionHelper = new SessionHelper(request);
|
||||
Optional<Long> userId = sessionHelper.getLoggedInUserId();
|
||||
|
||||
Assertions.assertTrue(userId.isPresent());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,84 +1,82 @@
|
||||
package com.commafeed.integration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.hc.core5.http.HttpStatus;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.glassfish.jersey.client.JerseyClientBuilder;
|
||||
import org.glassfish.jersey.media.multipart.MultiPartFeature;
|
||||
import org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJsonProvider;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockserver.client.MockServerClient;
|
||||
import org.mockserver.junit.jupiter.MockServerExtension;
|
||||
import org.mockserver.integration.ClientAndServer;
|
||||
import org.mockserver.model.HttpRequest;
|
||||
import org.mockserver.model.HttpResponse;
|
||||
|
||||
import com.commafeed.CommaFeedDropwizardAppExtension;
|
||||
import com.commafeed.JacksonCustomizer;
|
||||
import com.commafeed.frontend.model.Entries;
|
||||
import com.commafeed.frontend.model.Subscription;
|
||||
import com.commafeed.frontend.model.request.LoginRequest;
|
||||
import com.commafeed.frontend.model.request.SubscribeRequest;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.Header;
|
||||
import jakarta.ws.rs.client.Client;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.core.Form;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@ExtendWith(DropwizardExtensionsSupport.class)
|
||||
@ExtendWith(MockServerExtension.class)
|
||||
public abstract class BaseIT {
|
||||
|
||||
private static final HttpRequest FEED_REQUEST = HttpRequest.request().withMethod("GET").withPath("/");
|
||||
|
||||
private final CommaFeedDropwizardAppExtension extension = new CommaFeedDropwizardAppExtension() {
|
||||
@Override
|
||||
protected JerseyClientBuilder clientBuilder() {
|
||||
return configureClientBuilder(super.clientBuilder().register(MultiPartFeature.class));
|
||||
}
|
||||
};
|
||||
|
||||
private Client client;
|
||||
|
||||
private String feedUrl;
|
||||
|
||||
private String baseUrl;
|
||||
|
||||
private String apiBaseUrl;
|
||||
|
||||
private String webSocketUrl;
|
||||
|
||||
private MockServerClient mockServerClient;
|
||||
private Client client;
|
||||
private String feedUrl;
|
||||
private String baseUrl;
|
||||
private String apiBaseUrl;
|
||||
private String webSocketUrl;
|
||||
|
||||
protected JerseyClientBuilder configureClientBuilder(JerseyClientBuilder base) {
|
||||
return base;
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void init(MockServerClient mockServerClient) throws IOException {
|
||||
this.mockServerClient = mockServerClient;
|
||||
void init() throws IOException {
|
||||
this.mockServerClient = ClientAndServer.startClientAndServer(0);
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
new JacksonCustomizer().customize(mapper);
|
||||
this.client = configureClientBuilder(new JerseyClientBuilder().register(new JacksonJsonProvider(mapper))).build();
|
||||
this.feedUrl = "http://localhost:" + mockServerClient.getPort() + "/";
|
||||
this.baseUrl = "http://localhost:8085/";
|
||||
this.apiBaseUrl = this.baseUrl + "rest/";
|
||||
this.webSocketUrl = "ws://localhost:8085/ws";
|
||||
|
||||
URL resource = Objects.requireNonNull(getClass().getResource("/feed/rss.xml"));
|
||||
mockServerClient.when(FEED_REQUEST).respond(HttpResponse.response().withBody(IOUtils.toString(resource, StandardCharsets.UTF_8)));
|
||||
|
||||
this.client = extension.client();
|
||||
this.feedUrl = "http://localhost:" + mockServerClient.getPort() + "/";
|
||||
this.baseUrl = "http://localhost:" + extension.getLocalPort() + "/";
|
||||
this.apiBaseUrl = this.baseUrl + "rest/";
|
||||
this.webSocketUrl = "ws://localhost:" + extension.getLocalPort() + "/ws";
|
||||
this.mockServerClient.when(FEED_REQUEST)
|
||||
.respond(HttpResponse.response().withBody(IOUtils.toString(resource, StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanup() {
|
||||
this.client.close();
|
||||
if (this.mockServerClient != null) {
|
||||
this.mockServerClient.close();
|
||||
}
|
||||
|
||||
if (this.client != null) {
|
||||
this.client.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected void feedNowReturnsMoreEntries() throws IOException {
|
||||
@@ -88,14 +86,20 @@ public abstract class BaseIT {
|
||||
mockServerClient.when(FEED_REQUEST).respond(HttpResponse.response().withBody(IOUtils.toString(resource, StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
protected String login() {
|
||||
LoginRequest req = new LoginRequest();
|
||||
req.setName("admin");
|
||||
req.setPassword("admin");
|
||||
try (Response response = client.target(apiBaseUrl + "user/login").request().post(Entity.json(req))) {
|
||||
Assertions.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
return response.getCookies().get("JSESSIONID").getValue();
|
||||
}
|
||||
protected List<HttpCookie> login() {
|
||||
Form form = new Form();
|
||||
form.param("j_username", "admin");
|
||||
form.param("j_password", "admin");
|
||||
|
||||
List<Header> setCookieHeaders = RestAssured.given()
|
||||
.formParams("j_username", "admin", "j_password", "admin")
|
||||
.post(baseUrl + "j_security_check")
|
||||
.then()
|
||||
.statusCode(HttpStatus.SC_OK)
|
||||
.extract()
|
||||
.headers()
|
||||
.getList(HttpHeaders.SET_COOKIE);
|
||||
return setCookieHeaders.stream().flatMap(h -> HttpCookie.parse(h.getValue()).stream()).toList();
|
||||
}
|
||||
|
||||
protected Long subscribe(String feedUrl) {
|
||||
|
||||
@@ -2,25 +2,28 @@ package com.commafeed.integration;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.apache.hc.core5.http.HttpStatus;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.commafeed.frontend.model.Entries;
|
||||
import com.commafeed.frontend.model.UserModel;
|
||||
import com.commafeed.frontend.model.request.MarkRequest;
|
||||
import com.commafeed.frontend.model.request.ProfileModificationRequest;
|
||||
import com.commafeed.frontend.model.request.SubscribeRequest;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@QuarkusTest
|
||||
class SecurityIT extends BaseIT {
|
||||
|
||||
@Test
|
||||
void notLoggedIn() {
|
||||
try (Response response = getClient().target(getApiBaseUrl() + "user/profile").request().get()) {
|
||||
Assertions.assertEquals(HttpStatus.UNAUTHORIZED_401, response.getStatus());
|
||||
Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,18 +34,18 @@ class SecurityIT extends BaseIT {
|
||||
.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, auth)
|
||||
.get()) {
|
||||
Assertions.assertEquals(HttpStatus.UNAUTHORIZED_401, response.getStatus());
|
||||
Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void missingRole() {
|
||||
String auth = "Basic " + Base64.getEncoder().encodeToString("demo:demo".getBytes());
|
||||
try (Response response = getClient().target(getApiBaseUrl() + "admin/settings")
|
||||
try (Response response = getClient().target(getApiBaseUrl() + "admin/metrics")
|
||||
.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, auth)
|
||||
.get()) {
|
||||
Assertions.assertEquals(HttpStatus.FORBIDDEN_403, response.getStatus());
|
||||
Assertions.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,5 +87,16 @@ class SecurityIT extends BaseIT {
|
||||
.request()
|
||||
.get(Entries.class);
|
||||
Assertions.assertEquals("my title for this feed", entries.getName());
|
||||
|
||||
// mark entry as read and expect it won't work because it's not a GET request
|
||||
MarkRequest markRequest = new MarkRequest();
|
||||
markRequest.setId("1");
|
||||
markRequest.setRead(true);
|
||||
try (Response markResponse = getClient().target(getApiBaseUrl() + "entry/mark")
|
||||
.queryParam("apiKey", apiKey)
|
||||
.request()
|
||||
.post(Entity.json(markRequest))) {
|
||||
Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, markResponse.getStatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.commafeed.integration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -8,6 +9,7 @@ import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.awaitility.Awaitility;
|
||||
import org.glassfish.jersey.client.JerseyClientBuilder;
|
||||
@@ -17,6 +19,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.commafeed.frontend.model.request.FeedModificationRequest;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.websocket.ClientEndpointConfig;
|
||||
import jakarta.websocket.CloseReason;
|
||||
import jakarta.websocket.ContainerProvider;
|
||||
@@ -25,8 +28,10 @@ import jakarta.websocket.Endpoint;
|
||||
import jakarta.websocket.EndpointConfig;
|
||||
import jakarta.websocket.Session;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@QuarkusTest
|
||||
@Slf4j
|
||||
class WebSocketIT extends BaseIT {
|
||||
|
||||
@@ -49,18 +54,17 @@ class WebSocketIT extends BaseIT {
|
||||
public void onClose(Session session, CloseReason closeReason) {
|
||||
closeReasonRef.set(closeReason);
|
||||
}
|
||||
}, buildConfig("fake-session-id"), URI.create(getWebSocketUrl()))) {
|
||||
}, buildConfig(List.of()), URI.create(getWebSocketUrl()))) {
|
||||
Awaitility.await().atMost(15, TimeUnit.SECONDS).untilTrue(connected);
|
||||
log.info("connected to {}", session.getRequestURI());
|
||||
|
||||
Awaitility.await().atMost(15, TimeUnit.SECONDS).until(() -> closeReasonRef.get() != null);
|
||||
Assertions.assertEquals(CloseReason.CloseCodes.VIOLATED_POLICY, closeReasonRef.get().getCloseCode());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void subscribeAndGetsNotified() throws DeploymentException, IOException {
|
||||
String sessionId = login();
|
||||
List<HttpCookie> cookies = login();
|
||||
|
||||
AtomicBoolean connected = new AtomicBoolean();
|
||||
AtomicReference<String> messageRef = new AtomicReference<>();
|
||||
@@ -70,7 +74,7 @@ class WebSocketIT extends BaseIT {
|
||||
session.addMessageHandler(String.class, messageRef::set);
|
||||
connected.set(true);
|
||||
}
|
||||
}, buildConfig(sessionId), URI.create(getWebSocketUrl()))) {
|
||||
}, buildConfig(cookies), URI.create(getWebSocketUrl()))) {
|
||||
Awaitility.await().atMost(15, TimeUnit.SECONDS).untilTrue(connected);
|
||||
log.info("connected to {}", session.getRequestURI());
|
||||
|
||||
@@ -83,7 +87,7 @@ class WebSocketIT extends BaseIT {
|
||||
|
||||
@Test
|
||||
void notNotifiedForFilteredEntries() throws DeploymentException, IOException {
|
||||
String sessionId = login();
|
||||
List<HttpCookie> cookies = login();
|
||||
Long subscriptionId = subscribeAndWaitForEntries(getFeedUrl());
|
||||
|
||||
FeedModificationRequest req = new FeedModificationRequest();
|
||||
@@ -100,7 +104,7 @@ class WebSocketIT extends BaseIT {
|
||||
session.addMessageHandler(String.class, messageRef::set);
|
||||
connected.set(true);
|
||||
}
|
||||
}, buildConfig(sessionId), URI.create(getWebSocketUrl()))) {
|
||||
}, buildConfig(cookies), URI.create(getWebSocketUrl()))) {
|
||||
Awaitility.await().atMost(15, TimeUnit.SECONDS).untilTrue(connected);
|
||||
log.info("connected to {}", session.getRequestURI());
|
||||
|
||||
@@ -115,7 +119,7 @@ class WebSocketIT extends BaseIT {
|
||||
|
||||
@Test
|
||||
void pingPong() throws DeploymentException, IOException {
|
||||
String sessionId = login();
|
||||
List<HttpCookie> cookies = login();
|
||||
|
||||
AtomicBoolean connected = new AtomicBoolean();
|
||||
AtomicReference<String> messageRef = new AtomicReference<>();
|
||||
@@ -125,7 +129,7 @@ class WebSocketIT extends BaseIT {
|
||||
session.addMessageHandler(String.class, messageRef::set);
|
||||
connected.set(true);
|
||||
}
|
||||
}, buildConfig(sessionId), URI.create(getWebSocketUrl()))) {
|
||||
}, buildConfig(cookies), URI.create(getWebSocketUrl()))) {
|
||||
Awaitility.await().atMost(15, TimeUnit.SECONDS).untilTrue(connected);
|
||||
log.info("connected to {}", session.getRequestURI());
|
||||
|
||||
@@ -136,11 +140,12 @@ class WebSocketIT extends BaseIT {
|
||||
}
|
||||
}
|
||||
|
||||
private ClientEndpointConfig buildConfig(String sessionId) {
|
||||
private ClientEndpointConfig buildConfig(List<HttpCookie> cookies) {
|
||||
return ClientEndpointConfig.Builder.create().configurator(new ClientEndpointConfig.Configurator() {
|
||||
@Override
|
||||
public void beforeRequest(Map<String, List<String>> headers) {
|
||||
headers.put("Cookie", Collections.singletonList("JSESSIONID=" + sessionId));
|
||||
headers.put(HttpHeaders.COOKIE,
|
||||
Collections.singletonList(cookies.stream().map(HttpCookie::toString).collect(Collectors.joining(";"))));
|
||||
}
|
||||
}).build();
|
||||
}
|
||||
|
||||
@@ -9,14 +9,15 @@ import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.commafeed.CommaFeedConfiguration.ApplicationSettings;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.frontend.model.UserModel;
|
||||
import com.commafeed.frontend.model.request.IDRequest;
|
||||
import com.commafeed.integration.BaseIT;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
|
||||
@QuarkusTest
|
||||
class AdminIT extends BaseIT {
|
||||
|
||||
@Override
|
||||
@@ -24,12 +25,6 @@ class AdminIT extends BaseIT {
|
||||
return base.register(HttpAuthenticationFeature.basic("admin", "admin"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getApplicationSettings() {
|
||||
ApplicationSettings settings = getClient().target(getApiBaseUrl() + "admin/settings").request().get(ApplicationSettings.class);
|
||||
Assertions.assertTrue(settings.getAllowRegistrations());
|
||||
}
|
||||
|
||||
@Nested
|
||||
class Users {
|
||||
@Test
|
||||
|
||||
@@ -9,9 +9,8 @@ import java.time.ZoneOffset;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hc.core5.http.HttpStatus;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.glassfish.jersey.client.ClientProperties;
|
||||
import org.glassfish.jersey.client.JerseyClientBuilder;
|
||||
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
|
||||
@@ -30,10 +29,12 @@ import com.commafeed.frontend.model.request.IDRequest;
|
||||
import com.commafeed.frontend.model.request.MarkRequest;
|
||||
import com.commafeed.integration.BaseIT;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@QuarkusTest
|
||||
class FeedIT extends BaseIT {
|
||||
|
||||
@Override
|
||||
@@ -69,19 +70,19 @@ class FeedIT extends BaseIT {
|
||||
.property(ClientProperties.FOLLOW_REDIRECTS, Boolean.FALSE)
|
||||
.request()
|
||||
.get()) {
|
||||
Assertions.assertEquals(HttpStatus.TEMPORARY_REDIRECT_307, response.getStatus());
|
||||
Assertions.assertEquals(HttpStatus.SC_TEMPORARY_REDIRECT, response.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void unsubscribeFromUnknownFeed() {
|
||||
Assertions.assertEquals(HttpStatus.NOT_FOUND_404, unsubsribe(1L));
|
||||
Assertions.assertEquals(HttpStatus.SC_NOT_FOUND, unsubsribe(1L));
|
||||
}
|
||||
|
||||
@Test
|
||||
void unsubscribeFromKnownFeed() {
|
||||
long subscriptionId = subscribe(getFeedUrl());
|
||||
Assertions.assertEquals(HttpStatus.OK_200, unsubsribe(subscriptionId));
|
||||
Assertions.assertEquals(HttpStatus.SC_OK, unsubsribe(subscriptionId));
|
||||
}
|
||||
|
||||
private int unsubsribe(long subscriptionId) {
|
||||
@@ -212,20 +213,7 @@ class FeedIT extends BaseIT {
|
||||
void importExportOpml() throws IOException {
|
||||
importOpml();
|
||||
String opml = getClient().target(getApiBaseUrl() + "feed/export").request().get(String.class);
|
||||
String expextedOpml = """
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<opml version="1.0">
|
||||
<head>
|
||||
<title>admin subscriptions in CommaFeed</title>
|
||||
</head>
|
||||
<body>
|
||||
<outline text="out1" title="out1">
|
||||
<outline text="feed1" type="rss" title="feed1" xmlUrl="https://hostname.local/commafeed/feed1.xml" />
|
||||
</outline>
|
||||
</body>
|
||||
</opml>
|
||||
""";
|
||||
Assertions.assertEquals(StringUtils.normalizeSpace(expextedOpml), StringUtils.normalizeSpace(opml));
|
||||
Assertions.assertTrue(opml.contains("<title>admin subscriptions in CommaFeed</title>"));
|
||||
}
|
||||
|
||||
void importOpml() throws IOException {
|
||||
|
||||
@@ -12,9 +12,11 @@ import com.commafeed.frontend.model.request.ProfileModificationRequest;
|
||||
import com.commafeed.frontend.resource.fever.FeverResponse;
|
||||
import com.commafeed.integration.BaseIT;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.core.Form;
|
||||
|
||||
@QuarkusTest
|
||||
class FeverIT extends BaseIT {
|
||||
|
||||
private Long userId;
|
||||
@@ -26,7 +28,7 @@ class FeverIT extends BaseIT {
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void init() {
|
||||
void setup() {
|
||||
// create api key
|
||||
ProfileModificationRequest req = new ProfileModificationRequest();
|
||||
req.setCurrentPassword("admin");
|
||||
@@ -73,6 +75,7 @@ class FeverIT extends BaseIT {
|
||||
Form form = new Form();
|
||||
form.param("api_key", Digests.md5Hex("admin:" + apiKey));
|
||||
form.param(what, "1");
|
||||
|
||||
return getClient().target(getApiBaseUrl() + "fever/user/{userId}")
|
||||
.resolveTemplate("userId", userId)
|
||||
.request()
|
||||
|
||||
@@ -6,6 +6,9 @@ import org.junit.jupiter.api.Test;
|
||||
import com.commafeed.frontend.model.ServerInfo;
|
||||
import com.commafeed.integration.BaseIT;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
|
||||
@QuarkusTest
|
||||
class ServerIT extends BaseIT {
|
||||
|
||||
@Test
|
||||
@@ -16,7 +19,7 @@ class ServerIT extends BaseIT {
|
||||
Assertions.assertTrue(serverInfos.isDemoAccountEnabled());
|
||||
Assertions.assertTrue(serverInfos.isWebsocketEnabled());
|
||||
Assertions.assertEquals(900000, serverInfos.getWebsocketPingInterval());
|
||||
Assertions.assertEquals(10000, serverInfos.getTreeReloadInterval());
|
||||
Assertions.assertEquals(30000, serverInfos.getTreeReloadInterval());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,38 @@
|
||||
package com.commafeed.integration.rest;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
import com.commafeed.frontend.model.request.PasswordResetRequest;
|
||||
import com.commafeed.integration.BaseIT;
|
||||
import com.icegreen.greenmail.junit5.GreenMailExtension;
|
||||
import com.icegreen.greenmail.util.GreenMail;
|
||||
import com.icegreen.greenmail.util.ServerSetupTest;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.mail.internet.MimeMessage;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
|
||||
@QuarkusTest
|
||||
class UserIT extends BaseIT {
|
||||
|
||||
@Nested
|
||||
class PasswordReset {
|
||||
|
||||
@RegisterExtension
|
||||
static final GreenMailExtension GREEN_MAIL = new GreenMailExtension(ServerSetupTest.SMTP);
|
||||
private GreenMail greenMail;
|
||||
|
||||
@BeforeEach
|
||||
void init() {
|
||||
GREEN_MAIL.setUser("noreply@commafeed.com", "user", "pass");
|
||||
void setup() {
|
||||
this.greenMail = new GreenMail(ServerSetupTest.SMTP);
|
||||
this.greenMail.start();
|
||||
this.greenMail.setUser("noreply@commafeed.com", "user", "pass");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanup() {
|
||||
this.greenMail.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -34,7 +42,7 @@ class UserIT extends BaseIT {
|
||||
|
||||
getClient().target(getApiBaseUrl() + "user/passwordReset").request().post(Entity.json(req), Void.TYPE);
|
||||
|
||||
MimeMessage message = GREEN_MAIL.getReceivedMessages()[0];
|
||||
MimeMessage message = greenMail.getReceivedMessages()[0];
|
||||
Assertions.assertEquals("CommaFeed - Password recovery", message.getSubject());
|
||||
Assertions.assertTrue(message.getContent().toString().startsWith("You asked for password recovery for account 'admin'"));
|
||||
Assertions.assertEquals("CommaFeed <noreply@commafeed.com>", message.getFrom()[0].toString());
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.commafeed.integration.servlet;
|
||||
|
||||
import java.net.HttpCookie;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.glassfish.jersey.client.JerseyClientBuilder;
|
||||
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
@@ -8,10 +12,12 @@ import org.junit.jupiter.api.Test;
|
||||
import com.commafeed.frontend.model.Settings;
|
||||
import com.commafeed.integration.BaseIT;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@QuarkusTest
|
||||
class CustomCodeIT extends BaseIT {
|
||||
|
||||
@Override
|
||||
@@ -30,16 +36,16 @@ class CustomCodeIT extends BaseIT {
|
||||
getClient().target(getApiBaseUrl() + "user/settings").request().post(Entity.json(settings), Void.TYPE);
|
||||
|
||||
// check custom code servlets
|
||||
String cookie = login();
|
||||
List<HttpCookie> cookies = login();
|
||||
try (Response response = getClient().target(getBaseUrl() + "custom_js.js")
|
||||
.request()
|
||||
.header(HttpHeaders.COOKIE, "JSESSIONID=" + cookie)
|
||||
.header(HttpHeaders.COOKIE, cookies.stream().map(HttpCookie::toString).collect(Collectors.joining(";")))
|
||||
.get()) {
|
||||
Assertions.assertEquals("custom-js", response.readEntity(String.class));
|
||||
}
|
||||
try (Response response = getClient().target(getBaseUrl() + "custom_css.css")
|
||||
.request()
|
||||
.header(HttpHeaders.COOKIE, "JSESSIONID=" + cookie)
|
||||
.header(HttpHeaders.COOKIE, cookies.stream().map(HttpCookie::toString).collect(Collectors.joining(";")))
|
||||
.get()) {
|
||||
Assertions.assertEquals("custom-css", response.readEntity(String.class));
|
||||
}
|
||||
|
||||
@@ -1,32 +1,34 @@
|
||||
package com.commafeed.integration.servlet;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import java.net.HttpCookie;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.hc.core5.http.HttpStatus;
|
||||
import org.glassfish.jersey.client.ClientProperties;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.commafeed.frontend.model.UserModel;
|
||||
import com.commafeed.integration.BaseIT;
|
||||
|
||||
import jakarta.ws.rs.NotAuthorizedException;
|
||||
import jakarta.ws.rs.client.Invocation.Builder;
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@QuarkusTest
|
||||
class LogoutIT extends BaseIT {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
String cookie = login();
|
||||
List<HttpCookie> cookies = login();
|
||||
try (Response response = getClient().target(getBaseUrl() + "logout")
|
||||
.request()
|
||||
.header(HttpHeaders.COOKIE, "JSESSIONID=" + cookie)
|
||||
.header(HttpHeaders.COOKIE, cookies.stream().map(HttpCookie::toString).collect(Collectors.joining(";")))
|
||||
.property(ClientProperties.FOLLOW_REDIRECTS, Boolean.FALSE)
|
||||
.get()) {
|
||||
Assertions.assertEquals(HttpStatus.FOUND_302, response.getStatus());
|
||||
Assertions.assertEquals(HttpStatus.SC_TEMPORARY_REDIRECT, response.getStatus());
|
||||
List<String> setCookieHeaders = response.getStringHeaders().get(HttpHeaders.SET_COOKIE);
|
||||
Assertions.assertTrue(setCookieHeaders.stream().flatMap(c -> HttpCookie.parse(c).stream()).allMatch(c -> c.getMaxAge() == 0));
|
||||
}
|
||||
|
||||
Builder req = getClient().target(getApiBaseUrl() + "user/profile").request().header(HttpHeaders.COOKIE, "JSESSIONID=" + cookie);
|
||||
Assertions.assertThrows(NotAuthorizedException.class, () -> req.get(UserModel.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package com.commafeed.integration.servlet;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import java.net.HttpCookie;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.hc.core5.http.HttpStatus;
|
||||
import org.glassfish.jersey.client.ClientProperties;
|
||||
import org.glassfish.jersey.client.JerseyClientBuilder;
|
||||
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
|
||||
@@ -9,9 +13,11 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.commafeed.integration.BaseIT;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@QuarkusTest
|
||||
class NextUnreadIT extends BaseIT {
|
||||
|
||||
@Override
|
||||
@@ -23,13 +29,13 @@ class NextUnreadIT extends BaseIT {
|
||||
void test() {
|
||||
subscribeAndWaitForEntries(getFeedUrl());
|
||||
|
||||
String cookie = login();
|
||||
List<HttpCookie> cookies = login();
|
||||
Response response = getClient().target(getBaseUrl() + "next")
|
||||
.property(ClientProperties.FOLLOW_REDIRECTS, Boolean.FALSE)
|
||||
.request()
|
||||
.header(HttpHeaders.COOKIE, "JSESSIONID=" + cookie)
|
||||
.header(HttpHeaders.COOKIE, cookies.stream().map(HttpCookie::toString).collect(Collectors.joining(";")))
|
||||
.get();
|
||||
Assertions.assertEquals(HttpStatus.FOUND_302, response.getStatus());
|
||||
Assertions.assertEquals(HttpStatus.SC_TEMPORARY_REDIRECT, response.getStatus());
|
||||
Assertions.assertEquals("https://hostname.local/commafeed/2", response.getHeaderString(HttpHeaders.LOCATION));
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.commafeed.integration.BaseIT;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@QuarkusTest
|
||||
class RobotsTxtIT extends BaseIT {
|
||||
@Test
|
||||
void test() {
|
||||
|
||||
Reference in New Issue
Block a user