Enable WebAuthn tests for Account v3 (#28029)
* Re-enable WebAuthn testsuite * Remove reference to Account 2 in UI testsuites Fixes: #26080 Signed-off-by: Hynek Mlnarik <hmlnarik@redhat.com> --------- Signed-off-by: Hynek Mlnarik <hmlnarik@redhat.com>
This commit is contained in:
parent
4e7c2a5fa3
commit
9caac3814c
38 changed files with 142 additions and 182 deletions
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page;
|
||||
package org.keycloak.testsuite.ui.account3.page;
|
||||
|
||||
import org.keycloak.testsuite.auth.page.AuthRealm;
|
||||
|
||||
|
@ -44,6 +44,6 @@ public abstract class AbstractAccountPage extends AuthRealm {
|
|||
fragment = "/" + String.join("/", hashPath);
|
||||
}
|
||||
|
||||
return super.createUriBuilder().path("account/").fragment(fragment);
|
||||
return super.createUriBuilder().path("account/").path(fragment);
|
||||
}
|
||||
}
|
|
@ -15,13 +15,13 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page;
|
||||
package org.keycloak.testsuite.ui.account3.page;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.testsuite.ui.account2.page.fragment.ContentAlert;
|
||||
import org.keycloak.testsuite.ui.account2.page.fragment.ContinueCancelModal;
|
||||
import org.keycloak.testsuite.ui.account2.page.fragment.LoggedInPageHeader;
|
||||
import org.keycloak.testsuite.ui.account2.page.fragment.Sidebar;
|
||||
import org.keycloak.testsuite.ui.account3.page.fragment.ContentAlert;
|
||||
import org.keycloak.testsuite.ui.account3.page.fragment.ContinueCancelModal;
|
||||
import org.keycloak.testsuite.ui.account3.page.fragment.LoggedInPageHeader;
|
||||
import org.keycloak.testsuite.ui.account3.page.fragment.Sidebar;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
|
@ -34,9 +34,9 @@ import static org.keycloak.testsuite.util.UIUtils.getTextFromElement;
|
|||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public abstract class AbstractLoggedInPage extends AbstractAccountPage {
|
||||
public static final String ACCOUNT_SECURITY_ID = "security";
|
||||
public static final String ACCOUNT_SECURITY_ID = "account-security";
|
||||
|
||||
@FindBy(xpath = "//*[@id='main_react_container']//header")
|
||||
@FindBy(xpath = "//div[@id='app']//header[@class='pf-c-page__header']")
|
||||
private LoggedInPageHeader header;
|
||||
|
||||
@FindBy(id = "page-sidebar")
|
||||
|
@ -122,9 +122,4 @@ public abstract class AbstractLoggedInPage extends AbstractAccountPage {
|
|||
public void clickBrandLink() {
|
||||
clickLink(brandLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurrent() {
|
||||
return super.isCurrent() && getPageId().equals(sidebar().getActiveNavId());
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page;
|
||||
package org.keycloak.testsuite.ui.account3.page;
|
||||
|
||||
import org.keycloak.testsuite.util.UIUtils;
|
||||
import org.openqa.selenium.By;
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page;
|
||||
package org.keycloak.testsuite.ui.account3.page;
|
||||
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.NoSuchElementException;
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page;
|
||||
package org.keycloak.testsuite.ui.account3.page;
|
||||
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page;
|
||||
package org.keycloak.testsuite.ui.account3.page;
|
||||
|
||||
import org.jboss.arquillian.graphene.Graphene;
|
||||
import org.jboss.arquillian.graphene.fragment.Root;
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.testsuite.ui.account2.page;
|
||||
package org.keycloak.testsuite.ui.account3.page;
|
||||
|
||||
import org.keycloak.testsuite.util.UIUtils;
|
||||
import org.openqa.selenium.By;
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page;
|
||||
package org.keycloak.testsuite.ui.account3.page;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page;
|
||||
package org.keycloak.testsuite.ui.account3.page;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
@ -57,7 +57,7 @@ public class PersonalInfoPage extends AbstractLoggedInPage {
|
|||
|
||||
@Override
|
||||
public String getPageId() {
|
||||
return "personal-info";
|
||||
return "/";
|
||||
}
|
||||
|
||||
public void assertUsernameDisabled(boolean expected) {
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page;
|
||||
package org.keycloak.testsuite.ui.account3.page;
|
||||
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.NoSuchElementException;
|
||||
|
@ -38,7 +38,7 @@ public class SigningInPage extends AbstractLoggedInPage {
|
|||
|
||||
@Override
|
||||
public String getPageId() {
|
||||
return "signingin";
|
||||
return "signing-in";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -61,9 +61,9 @@ public class SigningInPage extends AbstractLoggedInPage {
|
|||
|
||||
public class CredentialType {
|
||||
private static final String NOT_SET_UP = "not-set-up";
|
||||
private static final String SET_UP = "set-up";
|
||||
private static final String TITLE = "cred-title";
|
||||
private static final String HELP = "cred-help";
|
||||
private static final String SET_UP_TEST_ID = "create";
|
||||
private static final String TITLE = "title";
|
||||
private static final String HELP = "help-text";
|
||||
|
||||
private final String type;
|
||||
|
||||
|
@ -75,13 +75,13 @@ public class SigningInPage extends AbstractLoggedInPage {
|
|||
return type;
|
||||
}
|
||||
|
||||
private WebElement getItemElement(String item) {
|
||||
String elementId = String.format("%s-%s", type, item);
|
||||
return driver.findElement(By.id(elementId));
|
||||
private WebElement getItemElementByTestId(String item) {
|
||||
String xpath = String.format("//*[@data-testid = '%s/%s']", type, item);
|
||||
return driver.findElement(By.xpath(xpath));
|
||||
}
|
||||
|
||||
public int getUserCredentialsCount() {
|
||||
String xpath = String.format("//li[starts-with(@id,'%s')]", type + "-" + UserCredential.ROW);
|
||||
String xpath = String.format("//*[@data-testid='%s/credential-list']//div[starts-with(@id,'cred-')]", type);
|
||||
return driver.findElements(By.xpath(xpath)).size();
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ public class SigningInPage extends AbstractLoggedInPage {
|
|||
boolean notSetUpLabelPresent;
|
||||
|
||||
try {
|
||||
notSetUpLabelPresent = getItemElement(NOT_SET_UP).isDisplayed();
|
||||
notSetUpLabelPresent = getItemElementByTestId(NOT_SET_UP).isDisplayed();
|
||||
}
|
||||
catch (NoSuchElementException e) {
|
||||
notSetUpLabelPresent = false;
|
||||
|
@ -113,12 +113,12 @@ public class SigningInPage extends AbstractLoggedInPage {
|
|||
}
|
||||
|
||||
public void clickSetUpLink() {
|
||||
clickLink(getItemElement(SET_UP));
|
||||
clickLink(getItemElementByTestId(SET_UP_TEST_ID));
|
||||
}
|
||||
|
||||
public boolean isSetUpLinkVisible() {
|
||||
try {
|
||||
return getItemElement(SET_UP).isDisplayed();
|
||||
return getItemElementByTestId(SET_UP_TEST_ID).isDisplayed();
|
||||
}
|
||||
catch (NoSuchElementException e) {
|
||||
return false;
|
||||
|
@ -127,7 +127,7 @@ public class SigningInPage extends AbstractLoggedInPage {
|
|||
|
||||
public boolean isNotSetUpLabelVisible() {
|
||||
try {
|
||||
return getItemElement(NOT_SET_UP).isDisplayed();
|
||||
return getItemElementByTestId(NOT_SET_UP).isDisplayed();
|
||||
}
|
||||
catch (NoSuchElementException e) {
|
||||
return false;
|
||||
|
@ -136,7 +136,7 @@ public class SigningInPage extends AbstractLoggedInPage {
|
|||
|
||||
public boolean isTitleVisible() {
|
||||
try {
|
||||
return getItemElement(TITLE).isDisplayed();
|
||||
return getItemElementByTestId(TITLE).isDisplayed();
|
||||
}
|
||||
catch (NoSuchElementException e) {
|
||||
return false;
|
||||
|
@ -144,28 +144,26 @@ public class SigningInPage extends AbstractLoggedInPage {
|
|||
}
|
||||
|
||||
public String getTitle() {
|
||||
return getTextFromElement(getItemElement(TITLE));
|
||||
return getTextFromElement(getItemElementByTestId(TITLE));
|
||||
}
|
||||
|
||||
public String getHelpText() {
|
||||
return getTextFromElement(getItemElement(HELP));
|
||||
return getTextFromElement(getItemElementByTestId(HELP));
|
||||
}
|
||||
}
|
||||
|
||||
public class UserCredential {
|
||||
private static final String ROW = "row";
|
||||
private static final String LABEL = "label";
|
||||
private static final String CREATED_AT = "created-at";
|
||||
private static final String CREDENTIAL_CREATED_AT = "Created ";
|
||||
private static final String UPDATE = "update";
|
||||
private static final String REMOVE = "remove";
|
||||
|
||||
private final String fullId;
|
||||
private final String id;
|
||||
private final CredentialType credentialType;
|
||||
|
||||
private UserCredential(String id, CredentialType credentialType) {
|
||||
this.fullId = id;
|
||||
this.id = id.substring(0,8);
|
||||
this.credentialType = credentialType;
|
||||
}
|
||||
|
||||
|
@ -178,8 +176,8 @@ public class SigningInPage extends AbstractLoggedInPage {
|
|||
}
|
||||
|
||||
private WebElement getItemElement(String item) {
|
||||
String elementId = String.format("%s-%s-%s", credentialType.getType(), item, id);
|
||||
return driver.findElement(By.id(elementId));
|
||||
String elementId = String.format("//*[@data-testid='%s/credential-list']//div[@id='cred-%s']//*[@data-testrole='%s']", credentialType.getType(), fullId, item);
|
||||
return driver.findElement(By.xpath(elementId));
|
||||
}
|
||||
|
||||
private boolean isItemDisplayed(String item) {
|
||||
|
@ -196,7 +194,7 @@ public class SigningInPage extends AbstractLoggedInPage {
|
|||
}
|
||||
|
||||
public String getUserLabel() {
|
||||
return getTextFromItem(LABEL);
|
||||
return getTextFromElement(getItemElement(LABEL));
|
||||
}
|
||||
|
||||
public boolean hasCreatedAt() {
|
||||
|
@ -209,10 +207,13 @@ public class SigningInPage extends AbstractLoggedInPage {
|
|||
}
|
||||
|
||||
public String getCreatedAtStr() {
|
||||
String lastCreatedAtText = getTextFromElement(
|
||||
driver.findElement(By.cssSelector("[id*='" + CREATED_AT + "'] strong")));
|
||||
String lastCreatedAtLabelXpath = String.format("//*[@data-testid='%s/credential-list']//div[@id='cred-%s']//*[@data-testrole='%s']/strong", credentialType.getType(), fullId, CREATED_AT);
|
||||
String lastCreatedAtLabel = getTextFromElement(driver.findElement(By.xpath(lastCreatedAtLabelXpath)));
|
||||
String lastCreateAtText = getTextFromItem(CREATED_AT);
|
||||
|
||||
return getTextFromItem(CREATED_AT).substring(lastCreatedAtText.length()).trim();
|
||||
return lastCreateAtText
|
||||
.substring(lastCreatedAtLabel.length(), lastCreateAtText.length() - 1) // remove label, drop last dot
|
||||
.trim();
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
|
@ -237,7 +238,7 @@ public class SigningInPage extends AbstractLoggedInPage {
|
|||
|
||||
public boolean isPresent() {
|
||||
try {
|
||||
return getItemElement(ROW).isDisplayed();
|
||||
return getItemElement(LABEL).isDisplayed();
|
||||
}
|
||||
catch (NoSuchElementException e) {
|
||||
return false;
|
|
@ -15,9 +15,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page;
|
||||
package org.keycloak.testsuite.ui.account3.page;
|
||||
|
||||
import org.keycloak.testsuite.ui.account2.page.fragment.WelcomeScreenHeader;
|
||||
import org.keycloak.testsuite.ui.account3.page.fragment.WelcomeScreenHeader;
|
||||
import org.keycloak.testsuite.util.URLUtils;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page.fragment;
|
||||
package org.keycloak.testsuite.ui.account3.page.fragment;
|
||||
|
||||
import org.jboss.arquillian.drone.api.annotation.Drone;
|
||||
import org.openqa.selenium.WebDriver;
|
|
@ -15,10 +15,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page.fragment;
|
||||
package org.keycloak.testsuite.ui.account3.page.fragment;
|
||||
|
||||
import org.jboss.arquillian.graphene.fragment.Root;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebElement;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -32,9 +30,6 @@ import static org.keycloak.testsuite.util.UIUtils.isElementVisible;
|
|||
public abstract class AbstractHeader extends AbstractFragmentWithMobileLayout {
|
||||
public static int MOBILE_WIDTH = 991;
|
||||
|
||||
@Root
|
||||
private WebElement headerRoot;
|
||||
|
||||
@Override
|
||||
protected int getMobileWidth() {
|
||||
return MOBILE_WIDTH;
|
||||
|
@ -60,32 +55,22 @@ public abstract class AbstractHeader extends AbstractFragmentWithMobileLayout {
|
|||
return getToolsBtnText(getReferrerLink());
|
||||
}
|
||||
|
||||
public abstract void clickMobileKebab();
|
||||
public abstract void clickOptions();
|
||||
|
||||
protected abstract WebElement getLogoutBtn ();
|
||||
|
||||
protected abstract WebElement getReferrerLink();
|
||||
|
||||
protected void clickToolsBtn(WebElement btn) {
|
||||
if (!isMobileLayout()) {
|
||||
clickLink(btn);
|
||||
}
|
||||
else {
|
||||
clickMobileKebab();
|
||||
clickLink(btn);
|
||||
}
|
||||
clickOptions();
|
||||
clickLink(btn);
|
||||
}
|
||||
|
||||
protected boolean isToolsBtnVisible(WebElement btn) {
|
||||
if (!isMobileLayout()) {
|
||||
return isElementVisible(btn);
|
||||
}
|
||||
else {
|
||||
clickMobileKebab();
|
||||
boolean ret = isElementVisible(btn);
|
||||
clickMobileKebab(); // hide the dropdown again
|
||||
return ret;
|
||||
}
|
||||
clickOptions();
|
||||
boolean ret = isElementVisible(btn);
|
||||
clickOptions(); // hide the dropdown again
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected void assertToolsBtnVisible(boolean expected, WebElement btn) {
|
||||
|
@ -95,15 +80,10 @@ public abstract class AbstractHeader extends AbstractFragmentWithMobileLayout {
|
|||
}
|
||||
|
||||
protected String getToolsBtnText(WebElement btn) {
|
||||
if (!isMobileLayout()) {
|
||||
return getTextFromElement(btn);
|
||||
}
|
||||
else {
|
||||
clickMobileKebab();
|
||||
String ret = getTextFromElement(btn);
|
||||
clickMobileKebab(); // hide the dropdown again
|
||||
return ret;
|
||||
}
|
||||
clickOptions();
|
||||
String ret = getTextFromElement(btn);
|
||||
clickOptions(); // hide the dropdown again
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected String getLocaleElementIdPrefix() {
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page.fragment;
|
||||
package org.keycloak.testsuite.ui.account3.page.fragment;
|
||||
|
||||
import org.jboss.arquillian.graphene.fragment.Root;
|
||||
import org.openqa.selenium.By;
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page.fragment;
|
||||
package org.keycloak.testsuite.ui.account3.page.fragment;
|
||||
|
||||
import org.jboss.arquillian.drone.api.annotation.Drone;
|
||||
import org.openqa.selenium.WebDriver;
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page.fragment;
|
||||
package org.keycloak.testsuite.ui.account3.page.fragment;
|
||||
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
@ -27,35 +27,27 @@ import static org.keycloak.testsuite.util.UIUtils.getTextFromElement;
|
|||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class LoggedInPageHeader extends AbstractHeader {
|
||||
@FindBy(id = "signOutButton")
|
||||
@FindBy(xpath = "//*[@data-testid='options']//a[text() = 'Sign out']")
|
||||
private WebElement logoutBtn;
|
||||
@FindBy(id = "signOutLink")
|
||||
@FindBy(xpath = "//*[@data-testid='options-kebab']//a[text() = 'Sign out']")
|
||||
private WebElement logoutBtnMobile;
|
||||
|
||||
@FindBy(id = "locale-dropdown-toggle")
|
||||
private WebElement localeBtn;
|
||||
@FindBy(id = "mobile-locale")
|
||||
private WebElement localeBtnMobile;
|
||||
|
||||
@FindBy(xpath = "//ul[@aria-labelledby='locale-dropdown-toggle']")
|
||||
private WebElement localeDropdown;
|
||||
@FindBy(xpath = "//section[@aria-labelledby='mobile-locale']")
|
||||
private WebElement localeDropdownMobile;
|
||||
|
||||
@FindBy(id = "referrerLink")
|
||||
private WebElement referrerLink;
|
||||
@FindBy(id = "referrerMobileLink")
|
||||
private WebElement referrerLinkMobile;
|
||||
|
||||
@FindBy(id = "landingMobileDropdown")
|
||||
private WebElement mobileKebab;
|
||||
@FindBy(xpath = "//*[@data-testid='options']")
|
||||
private WebElement options;
|
||||
@FindBy(xpath = "//*[@data-testid='options-kebab']")
|
||||
private WebElement optionsMobile;
|
||||
|
||||
@FindBy(id = "loggedInUser")
|
||||
private WebElement toolbarLoggedInUser;
|
||||
|
||||
@Override
|
||||
public void clickMobileKebab() {
|
||||
clickLink(mobileKebab);
|
||||
public void clickOptions() {
|
||||
clickLink(isMobileLayout() ? optionsMobile : options);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page.fragment;
|
||||
package org.keycloak.testsuite.ui.account3.page.fragment;
|
||||
|
||||
import org.jboss.arquillian.graphene.fragment.Root;
|
||||
import org.openqa.selenium.By;
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page.fragment;
|
||||
package org.keycloak.testsuite.ui.account3.page.fragment;
|
||||
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
@ -54,7 +54,7 @@ public class WelcomeScreenHeader extends AbstractHeader {
|
|||
private WebElement toolbarLoggedInUser;
|
||||
|
||||
@Override
|
||||
public void clickMobileKebab() {
|
||||
public void clickOptions() {
|
||||
clickLink(mobileKebab);
|
||||
}
|
||||
|
|
@ -15,14 +15,14 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2.page.utils;
|
||||
package org.keycloak.testsuite.ui.account3.page.utils;
|
||||
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
|
||||
import org.keycloak.testsuite.ui.account2.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.SigningInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.SigningInPage;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Before;
|
||||
|
@ -23,8 +23,8 @@ import org.keycloak.common.Profile;
|
|||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.ui.AbstractUiTest;
|
||||
import org.keycloak.testsuite.ui.account2.page.PageNotFound;
|
||||
import org.keycloak.testsuite.ui.account2.page.WelcomeScreen;
|
||||
import org.keycloak.testsuite.ui.account3.page.PageNotFound;
|
||||
import org.keycloak.testsuite.ui.account3.page.WelcomeScreen;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
|
@ -15,15 +15,15 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.ui.account2.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.ApplicationsPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.ApplicationsPage;
|
||||
import org.keycloak.testsuite.util.ClientBuilder;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
|
|
@ -15,11 +15,11 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.keycloak.testsuite.ui.account2.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.utils.SigningInPageUtils;
|
||||
import org.keycloak.testsuite.ui.account3.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.utils.SigningInPageUtils;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
@ -34,9 +34,9 @@ import org.keycloak.representations.idm.RoleRepresentation;
|
|||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.pages.PasswordPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.auth.page.login.DeleteAccountActionConfirmPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.PersonalInfoPage;
|
||||
|
||||
import static org.keycloak.testsuite.util.UIUtils.refreshPageAndWaitForLoad;
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Before;
|
||||
|
@ -27,8 +27,8 @@ import org.keycloak.models.UserModel;
|
|||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.ui.account2.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.DeviceActivityPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.DeviceActivityPage;
|
||||
import org.keycloak.testsuite.util.ClientBuilder;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Before;
|
||||
|
@ -24,9 +24,9 @@ import org.junit.Test;
|
|||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.credential.PasswordCredentialModel;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.ui.account2.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.SigningInPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.WelcomeScreen;
|
||||
import org.keycloak.testsuite.ui.account3.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.SigningInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.WelcomeScreen;
|
||||
import org.keycloak.testsuite.util.WaitUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
@ -40,8 +40,8 @@ import org.keycloak.storage.ldap.LDAPStorageProvider;
|
|||
import org.keycloak.storage.ldap.idm.model.LDAPObject;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.federation.ldap.LDAPTestContext;
|
||||
import org.keycloak.testsuite.ui.account2.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.SigningInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.SigningInPage;
|
||||
import org.keycloak.testsuite.util.LDAPRule;
|
||||
import org.keycloak.testsuite.util.LDAPTestUtils;
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.After;
|
||||
|
@ -30,8 +30,8 @@ import org.keycloak.representations.idm.RealmRepresentation;
|
|||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.social.google.GoogleIdentityProviderFactory;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.LinkedAccountsPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.LinkedAccountsPage;
|
||||
import org.keycloak.testsuite.util.ClientBuilder;
|
||||
|
||||
import java.util.Collections;
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
|
@ -21,8 +21,8 @@ import org.keycloak.representations.idm.RealmRepresentation;
|
|||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.PermissionTicketRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
import org.keycloak.testsuite.ui.account2.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.MyResourcesPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.MyResourcesPage;
|
||||
import org.keycloak.testsuite.util.ClientBuilder;
|
||||
import org.keycloak.testsuite.util.UserBuilder;
|
||||
import org.keycloak.util.JsonSerialization;
|
|
@ -15,16 +15,16 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.RoleScopeResource;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.testsuite.ui.account2.page.ForbiddenPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.SigningInPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.WelcomeScreen;
|
||||
import org.keycloak.testsuite.ui.account3.page.ForbiddenPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.SigningInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.WelcomeScreen;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
@ -36,8 +36,8 @@ import org.keycloak.representations.idm.RealmRepresentation;
|
|||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.forms.VerifyProfileTest;
|
||||
import org.keycloak.testsuite.ui.account2.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.util.UserBuilder;
|
||||
|
||||
/**
|
|
@ -15,15 +15,15 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.ui.account2.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.WelcomeScreen;
|
||||
import org.keycloak.testsuite.ui.account2.page.fragment.AbstractHeader;
|
||||
import org.keycloak.testsuite.ui.account3.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.WelcomeScreen;
|
||||
import org.keycloak.testsuite.ui.account3.page.fragment.AbstractHeader;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
|
@ -15,14 +15,14 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.ui.account2.page.DeviceActivityPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.DeviceActivityPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.PersonalInfoPage;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Before;
|
||||
|
@ -29,9 +29,9 @@ import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
|
|||
import org.keycloak.testsuite.admin.Users;
|
||||
import org.keycloak.testsuite.auth.page.login.OTPSetup;
|
||||
import org.keycloak.testsuite.auth.page.login.UpdatePassword;
|
||||
import org.keycloak.testsuite.ui.account2.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.SigningInPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.utils.SigningInPageUtils;
|
||||
import org.keycloak.testsuite.ui.account3.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.SigningInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.utils.SigningInPageUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
|
@ -41,8 +41,8 @@ import static org.hamcrest.CoreMatchers.not;
|
|||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.keycloak.models.UserModel.RequiredAction.CONFIGURE_TOTP;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||
import static org.keycloak.testsuite.ui.account2.page.utils.SigningInPageUtils.assertUserCredential;
|
||||
import static org.keycloak.testsuite.ui.account2.page.utils.SigningInPageUtils.testSetUpLink;
|
||||
import static org.keycloak.testsuite.ui.account3.page.utils.SigningInPageUtils.assertUserCredential;
|
||||
import static org.keycloak.testsuite.ui.account3.page.utils.SigningInPageUtils.testSetUpLink;
|
||||
import static org.keycloak.testsuite.util.UIUtils.refreshPageAndWaitForLoad;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.pause;
|
||||
|
|
@ -15,12 +15,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.testsuite.ui.account2.page.DeviceActivityPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.DeviceActivityPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.PersonalInfoPage;
|
||||
|
||||
/**
|
||||
* Basic sanity check for Account Console
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.keycloak.testsuite.util.UIUtils.refreshPageAndWaitForLoad;
|
||||
|
@ -36,8 +36,8 @@ import org.keycloak.representations.idm.UserRepresentation;
|
|||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.auth.page.login.UpdateEmailPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.PersonalInfoPage;
|
||||
|
||||
@EnableFeature(Profile.Feature.UPDATE_EMAIL)
|
||||
public class UpdateEmailTest extends BaseAccountPageTest {
|
|
@ -15,16 +15,16 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.ui.account2;
|
||||
package org.keycloak.testsuite.ui.account3;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.ui.account2.page.ApplicationsPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.DeviceActivityPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.LinkedAccountsPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.MyResourcesPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.ApplicationsPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.DeviceActivityPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.LinkedAccountsPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.MyResourcesPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.PersonalInfoPage;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
|
|
@ -25,7 +25,6 @@ import org.keycloak.authentication.authenticators.browser.WebAuthnAuthenticatorF
|
|||
import org.keycloak.authentication.authenticators.browser.WebAuthnPasswordlessAuthenticatorFactory;
|
||||
import org.keycloak.authentication.requiredactions.WebAuthnPasswordlessRegisterFactory;
|
||||
import org.keycloak.authentication.requiredactions.WebAuthnRegisterFactory;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.models.AuthenticationExecutionModel;
|
||||
import org.keycloak.models.credential.WebAuthnCredentialModel;
|
||||
import org.keycloak.representations.idm.AuthenticationExecutionRepresentation;
|
||||
|
@ -33,11 +32,9 @@ import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
|
|||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.RequiredActionProviderSimpleRepresentation;
|
||||
import org.keycloak.testsuite.AbstractAuthTest;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.arquillian.annotation.DisableFeature;
|
||||
import org.keycloak.testsuite.page.AbstractPatternFlyAlert;
|
||||
import org.keycloak.testsuite.ui.account2.page.SigningInPage;
|
||||
import org.keycloak.testsuite.ui.account2.page.utils.SigningInPageUtils;
|
||||
import org.keycloak.testsuite.ui.account3.page.SigningInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.utils.SigningInPageUtils;
|
||||
import org.keycloak.testsuite.updaters.RealmAttributeUpdater;
|
||||
import org.keycloak.testsuite.util.FlowUtil;
|
||||
import org.keycloak.testsuite.webauthn.AbstractWebAuthnVirtualTest;
|
||||
|
@ -57,9 +54,6 @@ import static org.keycloak.models.AuthenticationExecutionModel.Requirement.REQUI
|
|||
import static org.keycloak.testsuite.util.BrowserDriverUtil.isDriverFirefox;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
||||
|
||||
// Enable ACCOUNT3 feature once https://github.com/keycloak/keycloak/issues/26080 is resolved
|
||||
@EnableFeature(value = Profile.Feature.ACCOUNT2, skipRestart = true)
|
||||
@DisableFeature(value = Profile.Feature.ACCOUNT3, skipRestart = true)
|
||||
public abstract class AbstractWebAuthnAccountTest extends AbstractAuthTest implements UseVirtualAuthenticators {
|
||||
|
||||
@Page
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
package org.keycloak.testsuite.webauthn.account;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Test;
|
||||
import org.junit.Ignore;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
|
@ -27,9 +26,8 @@ import org.keycloak.authentication.requiredactions.WebAuthnRegisterFactory;
|
|||
import org.keycloak.models.credential.WebAuthnCredentialModel;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
|
||||
import org.keycloak.testsuite.ui.account2.page.SigningInPage;
|
||||
import org.keycloak.testsuite.ui.account3.page.SigningInPage;
|
||||
import org.keycloak.testsuite.webauthn.pages.WebAuthnAuthenticatorsList;
|
||||
import org.keycloak.testsuite.webauthn.pages.WebAuthnLoginPage;
|
||||
import org.keycloak.theme.DateTimeFormatterUtil;
|
||||
|
||||
import java.io.Closeable;
|
||||
|
@ -51,8 +49,8 @@ import static org.hamcrest.CoreMatchers.notNullValue;
|
|||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.keycloak.testsuite.ui.account2.page.utils.SigningInPageUtils.assertUserCredential;
|
||||
import static org.keycloak.testsuite.ui.account2.page.utils.SigningInPageUtils.testSetUpLink;
|
||||
import static org.keycloak.testsuite.ui.account3.page.utils.SigningInPageUtils.assertUserCredential;
|
||||
import static org.keycloak.testsuite.ui.account3.page.utils.SigningInPageUtils.testSetUpLink;
|
||||
import static org.keycloak.testsuite.util.UIUtils.refreshPageAndWaitForLoad;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
||||
|
||||
|
|
Loading…
Reference in a new issue