mirror of
https://github.com/Athou/commafeed.git
synced 2026-03-21 21:37:29 +00:00
add playwright tests
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
package com.commafeed.e2e;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import com.commafeed.CommaFeedApplication;
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.microsoft.playwright.Locator;
|
||||
import com.microsoft.playwright.assertions.PlaywrightAssertions;
|
||||
|
||||
import io.dropwizard.testing.ResourceHelpers;
|
||||
import io.dropwizard.testing.junit5.DropwizardAppExtension;
|
||||
import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
|
||||
|
||||
@ExtendWith(DropwizardExtensionsSupport.class)
|
||||
class AuthentificationIT extends PlaywrightTestBase {
|
||||
|
||||
private static final DropwizardAppExtension<CommaFeedConfiguration> EXT = new DropwizardAppExtension<CommaFeedConfiguration>(
|
||||
CommaFeedApplication.class, ResourceHelpers.resourceFilePath("config.test.yml"));
|
||||
|
||||
@Test
|
||||
void loginFail() {
|
||||
page.navigate("http://localhost:" + EXT.getLocalPort());
|
||||
page.locator("[placeholder='User Name or E-mail']").fill("admin");
|
||||
page.locator("[placeholder='Password']").fill("wrong_password");
|
||||
page.locator("button:has-text('Log in')").click();
|
||||
PlaywrightAssertions.assertThat(page.locator("div[role='alert']")).containsText("wrong username or password");
|
||||
}
|
||||
|
||||
@Test
|
||||
void loginSuccess() {
|
||||
page.navigate("http://localhost:" + EXT.getLocalPort());
|
||||
PlaywrightTestUtils.login(page);
|
||||
PlaywrightAssertions.assertThat(page).hasURL("http://localhost:" + EXT.getLocalPort() + "/#/app/category/all");
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerFailPasswordTooSimple() {
|
||||
page.navigate("http://localhost:" + EXT.getLocalPort());
|
||||
page.locator("text=Sign up!").click();
|
||||
page.locator("[placeholder='User Name']").fill("user");
|
||||
page.locator("[placeholder='E-mail address']").fill("user@domain.com");
|
||||
page.locator("[placeholder='Password']").fill("pass");
|
||||
page.locator("button:has-text('Sign up')").click();
|
||||
|
||||
Locator alert = page.locator("div[role='alert']");
|
||||
PlaywrightAssertions.assertThat(alert).containsText("Password must be 8 or more characters in length.");
|
||||
PlaywrightAssertions.assertThat(alert).containsText("Password must contain 1 or more uppercase characters.");
|
||||
PlaywrightAssertions.assertThat(alert).containsText("Password must contain 1 or more digit characters.");
|
||||
PlaywrightAssertions.assertThat(alert).containsText("Password must contain 1 or more special characters.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerSuccess() {
|
||||
page.navigate("http://localhost:" + EXT.getLocalPort());
|
||||
page.locator("text=Sign up!").click();
|
||||
page.locator("[placeholder='User Name']").fill("user");
|
||||
page.locator("[placeholder='E-mail address']").fill("user@domain.com");
|
||||
page.locator("[placeholder='Password']").fill("MyPassword1!");
|
||||
page.locator("button:has-text('Sign up')").click();
|
||||
PlaywrightAssertions.assertThat(page).hasURL("http://localhost:" + EXT.getLocalPort() + "/#/app/category/all");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.commafeed.e2e;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
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 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) {
|
||||
}
|
||||
|
||||
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) throws Exception {
|
||||
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(),
|
||||
new SimpleDateFormat("yyyy-MM-dd--HH-mm-ss").format(new Date()));
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.commafeed.e2e;
|
||||
|
||||
import com.microsoft.playwright.Page;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
@UtilityClass
|
||||
public class PlaywrightTestUtils {
|
||||
|
||||
public static void login(Page page) {
|
||||
page.locator("[placeholder='User Name or E-mail']").fill("admin");
|
||||
page.locator("[placeholder='Password']").fill("admin");
|
||||
page.locator("button:has-text('Log in')").click();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.commafeed.e2e;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
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.model.HttpRequest;
|
||||
import org.mockserver.model.HttpResponse;
|
||||
|
||||
import com.commafeed.CommaFeedApplication;
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.microsoft.playwright.Locator;
|
||||
import com.microsoft.playwright.Locator.WaitForOptions;
|
||||
import com.microsoft.playwright.assertions.PlaywrightAssertions;
|
||||
|
||||
import io.dropwizard.testing.ResourceHelpers;
|
||||
import io.dropwizard.testing.junit5.DropwizardAppExtension;
|
||||
import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
|
||||
|
||||
@ExtendWith(DropwizardExtensionsSupport.class)
|
||||
@ExtendWith(MockServerExtension.class)
|
||||
class ReadingIT extends PlaywrightTestBase {
|
||||
|
||||
private static final DropwizardAppExtension<CommaFeedConfiguration> EXT = new DropwizardAppExtension<CommaFeedConfiguration>(
|
||||
CommaFeedApplication.class, ResourceHelpers.resourceFilePath("config.test.yml"));
|
||||
|
||||
private MockServerClient mockServerClient;
|
||||
|
||||
@BeforeEach
|
||||
void init(MockServerClient mockServerClient) throws IOException {
|
||||
this.mockServerClient = mockServerClient;
|
||||
this.mockServerClient.when(HttpRequest.request().withMethod("GET"))
|
||||
.respond(HttpResponse.response()
|
||||
.withBody(IOUtils.toString(getClass().getResource("/feed/rss.xml"), StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void scenario() {
|
||||
// login
|
||||
page.navigate("http://localhost:" + EXT.getLocalPort());
|
||||
PlaywrightTestUtils.login(page);
|
||||
PlaywrightAssertions.assertThat(page.locator("text=You don't have any subscriptions yet.")).hasCount(1);
|
||||
|
||||
// subscribe
|
||||
page.locator("[aria-label='Subscribe']").click();
|
||||
page.locator("text=Feed URL *").fill("http://localhost:" + this.mockServerClient.getPort());
|
||||
page.locator("button:has-text('Next')").click();
|
||||
page.locator("button:has-text('Subscribe')").nth(2).click();
|
||||
|
||||
// subscription has two unread entries
|
||||
Locator treeNode = page.locator("nav >> text=CommaFeed test feed2");
|
||||
treeNode.waitFor(new WaitForOptions().setTimeout(30000));
|
||||
PlaywrightAssertions.assertThat(treeNode).hasCount(1);
|
||||
|
||||
// click on subscription
|
||||
treeNode.click();
|
||||
Locator entries = page.locator("main >> .mantine-Paper-root");
|
||||
PlaywrightAssertions.assertThat(entries).hasCount(2);
|
||||
|
||||
// click on first entry
|
||||
page.locator("text='Item 1'").click();
|
||||
PlaywrightAssertions.assertThat(page.locator("text=Item 1 description")).hasCount(1);
|
||||
PlaywrightAssertions.assertThat(page.locator("text=Item 2 description")).hasCount(0);
|
||||
// only one unread entry now
|
||||
PlaywrightAssertions.assertThat(page.locator("nav >> text=CommaFeed test feed1")).hasCount(1);
|
||||
|
||||
// click on second entry
|
||||
page.locator("text=Item 2").click();
|
||||
PlaywrightAssertions.assertThat(page.locator("text=Item 1 description")).hasCount(0);
|
||||
PlaywrightAssertions.assertThat(page.locator("text=Item 2 description")).hasCount(1);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user