Skip to content

Commit

Permalink
[java] Update and fix test
Browse files Browse the repository at this point in the history
  • Loading branch information
pujagani committed Dec 19, 2024
1 parent 98d9693 commit d58c901
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 58 deletions.
51 changes: 34 additions & 17 deletions common/src/web/fedcm/fedcm.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
<!DOCTYPE html>
<script>
<html>
<head>
<title>FedCM Example</title>
</head>
<body>
<button id="triggerButton" onclick="triggerFedCm()">Trigger FedCM</button>
<div id="result"></div>

let configURL = `http://${location.host}/fedcm/fedcm.json`;
let promise = null;
<script>
// Use a relative path for the configURL
let configURL = `https://${location.host}/fedcm/config.json`;
console.log(configURL)
let result = null;

function triggerFedCm() {
console.log(configURL);
promise = navigator.credentials.get({
identity: {
providers: [{
configURL: configURL,
clientId: '1',
}]
}
});
return promise;
}

</script>
async function triggerFedCm() {
console.log("Config URL:", configURL);
try {
let promise = await navigator.credentials.get({
identity: {
providers: [{
configURL: configURL,
clientId: '1',
}]
}
});
result = promise;
document.getElementById('result').innerText = JSON.stringify(result);
} catch (error) {
console.error("FedCM Error:", error);
result = { error: error.message };
document.getElementById('result').innerText = JSON.stringify(result);
}
}
</script>
</body>
</html>
11 changes: 11 additions & 0 deletions common/src/web/fedcm/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>Login Page</h1>
<p>Login successful! This is a placeholder for the login process.</p>
<a href="/">Return to Home</a>
</body>
</html>
19 changes: 19 additions & 0 deletions common/src/web/fedcm/signin.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Sign In</title>
</head>
<body>
<h1>Sign In Page</h1>
<p>This is a placeholder for the sign-in page.</p>
<form action="/signin" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<br><br>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<br><br>
<button type="submit">Sign In</button>
</form>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public interface FederatedCredentialManagementDialog {
/** Returns the subtitle of the dialog or null if none. */
String getSubtitle();

void clickDialog();

/**
* Returns the accounts shown in the account chooser.
*
Expand Down
6 changes: 6 additions & 0 deletions java/src/org/openqa/selenium/remote/FedCmDialogImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ public String getDialogType() {
return (String) executeMethod.execute(DriverCommand.GET_FEDCM_DIALOG_TYPE, null);
}

@Override
public void clickDialog() {
executeMethod.execute(
DriverCommand.CLICK_DIALOG, Map.of("dialogButton", "ConfirmIdpLoginContinue"));
}

@Override
public String getTitle() {
Map<String, Object> result =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package org.openqa.selenium.environment.webserver;


import java.io.UncheckedIOException;
import java.util.Map;
import org.openqa.selenium.remote.http.Contents;
import org.openqa.selenium.remote.http.HttpHandler;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;

class FedCmConfigHandler implements HttpHandler {

@Override
public HttpResponse execute(HttpRequest req) throws UncheckedIOException {
HttpResponse response = new HttpResponse();
response.setHeader("Content-Type", "application/json");
response.setHeader("Cache-Control", "no-store");

response.setContent(
Contents.asJson(
Map.of(
"accounts_endpoint", "accounts.json",
"client_metadata_endpoint", "client_metadata.json",
"id_assertion_endpoint", "id_assertion.json",
"signin_url", "signin",
"login_url", "login")));

return response;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ public HandlersForTests(String hostname, int port, Path tempPageDir) {
.setContent(Contents.string("<h1>authorized</h1>", UTF_8)))
.with(new BasicAuthenticationFilter("test", "test")),
Route.get("/.well-known/web-identity").to(WellKnownWebIdentityHandler::new),
Route.get("/fedcm/config.json").to(FedCmConfigHandler::new),
Route.get("/echo").to(EchoHandler::new),
Route.get("/cookie").to(CookieHandler::new),
Route.post("/fedcm/id_assertion").to(FedCmIdAssertion::new),
Route.post("/fedcm/id_assertion.json").to(FedCmIdAssertion::new),
Route.get("/encoding").to(EncodingHandler::new),
Route.matching(req -> req.getUri().startsWith("/generated/"))
.to(() -> new GeneratedJsTestHandler("/generated")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public HttpResponse execute(HttpRequest req) throws UncheckedIOException {
HttpResponse response = new HttpResponse();
response.setHeader("Content-Type", "application/json");
response.setHeader("Cache-Control", "no-store");
String targetLocation = UrlPath.relativeToContext(req, "/fedcm/fedcm.json");
String targetLocation = UrlPath.relativeToContext(req, "https://idp.com");

response.setContent(Contents.string(String.format(RESPONSE_STRING, targetLocation), UTF_8));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,53 +19,59 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.assertj.core.api.InstanceOfAssertFactories.MAP;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.openqa.selenium.testing.drivers.Browser.CHROME;

import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.InvalidSelectorException;
import org.openqa.selenium.JavascriptException;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.By;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.environment.InProcessTestEnvironment;
import org.openqa.selenium.environment.webserver.AppServer;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.testing.JupiterTestBase;

import org.openqa.selenium.testing.NeedsSecureServer;

@NeedsSecureServer
class FederatedCredentialManagementTest extends JupiterTestBase {
class FederatedCredentialManagementTest {

private JavascriptExecutor jsAwareDriver;
private HasFederatedCredentialManagement fedcmDriver;
private WebDriver localDriver;
InProcessTestEnvironment environment = new InProcessTestEnvironment(true);
AppServer appServer = environment.getAppServer();

@BeforeEach
public void setup() {
ChromeOptions options = (ChromeOptions) CHROME.getCapabilities();
// options.setAcceptInsecureCerts(true);
options.setAcceptInsecureCerts(true);
options.addArguments(
String.format("host-resolver-rules=MAP localhost:443 localhost:%d", getSecurePort()));
options.addArguments("ignore-certificate-errors");
localDriver = seleniumExtension.createNewDriver(options);
options.addArguments("--enable-fedcm-without-well-known-enforcement");
localDriver = new ChromeDriver(options);

assumeThat(localDriver).isInstanceOf(HasFederatedCredentialManagement.class);
jsAwareDriver = (JavascriptExecutor) localDriver;
fedcmDriver = (HasFederatedCredentialManagement) localDriver;
localDriver.get(appServer.whereIsSecure("/fedcm/fedcm.html"));
}

private Object triggerFedCm() {
return jsAwareDriver.executeScript("triggerFedCm()");
@AfterEach
public void teardown() {
localDriver.quit();
appServer.stop();
}

private void waitForDialog() {
WebDriverWait wait = new WebDriverWait(localDriver, Duration.ofSeconds(5));
WebDriverWait wait = new WebDriverWait(localDriver, Duration.ofSeconds(20));
wait.until(
driver ->
((HasFederatedCredentialManagement) driver).getFederatedCredentialManagementDialog()
Expand All @@ -87,51 +93,85 @@ void testDismissDialog() {
fedcmDriver.setDelayEnabled(false);
assertNull(fedcmDriver.getFederatedCredentialManagementDialog());

Object response = triggerFedCm();
WebElement triggerButton = localDriver.findElement(By.id("triggerButton"));
triggerButton.click();

waitForDialog();

FederatedCredentialManagementDialog dialog =
fedcmDriver.getFederatedCredentialManagementDialog();

assertEquals("Sign in to localhost with localhost", dialog.getTitle());
assertEquals("AccountChooser", dialog.getDialogType());

assertThat(dialog.getTitle()).isEqualTo("Sign in to localhost with localhost");
assertThat(dialog.getDialogType()).isEqualTo("AccountChooser");
dialog.cancelDialog();

// Check that the dialog was indeed closed (i.e. the promise now resolves).
assertThrows(
JavascriptException.class,
() -> {
try {
jsAwareDriver.executeScript("await promise");
} catch (InvalidSelectorException ex) {
// Due to a bug in Chromedriver (https://crbug.com/1454586), we may
// get an invalid selector exception here instead of a JavascriptException.
// Turn it into a JavascriptException to make the test pass for now.
throw new JavascriptException(ex.getMessage(), ex);
}
});
// Check that the dialog was indeed closed. Unable to get the dialog type since the dialog was
// closed.
assertThrows(NoAlertPresentException.class, dialog::getDialogType);
}

@Test
void testSelectAccount() {
fedcmDriver.setDelayEnabled(false);
assertNull(fedcmDriver.getFederatedCredentialManagementDialog());

Object response = triggerFedCm();
WebElement triggerButton = localDriver.findElement(By.id("triggerButton"));
triggerButton.click();

waitForDialog();

FederatedCredentialManagementDialog dialog =
fedcmDriver.getFederatedCredentialManagementDialog();

assertEquals("Sign in to localhost with localhost", dialog.getTitle());
assertEquals("AccountChooser", dialog.getDialogType());
assertThat(dialog.getTitle()).isEqualTo("Sign in to localhost with localhost");
assertThat(dialog.getDialogType()).isEqualTo("AccountChooser");

dialog.selectAccount(0);
List<FederatedCredentialManagementAccount> accountList = dialog.getAccounts();
assertThat(accountList.size()).isEqualTo(2);
dialog.selectAccount(1);
}

@Test
void testGetAccounts() {
assertNull(fedcmDriver.getFederatedCredentialManagementDialog());

WebElement triggerButton = localDriver.findElement(By.id("triggerButton"));
triggerButton.click();

waitForDialog();

FederatedCredentialManagementDialog dialog =
fedcmDriver.getFederatedCredentialManagementDialog();

response = jsAwareDriver.executeScript("return await promise");
assertThat(response).asInstanceOf(MAP).containsEntry("token", "a token");
assertThat(dialog.getTitle()).isEqualTo("Sign in to localhost with localhost");
assertThat(dialog.getDialogType()).isEqualTo("AccountChooser");

List<FederatedCredentialManagementAccount> accountList = dialog.getAccounts();
assertThat(accountList.size()).isEqualTo(2);

FederatedCredentialManagementAccount account1 = accountList.get(0);

assertThat(account1.getName()).isEqualTo("John Doe");
assertThat(account1.getEmail()).isEqualTo("[email protected]");
assertThat(account1.getAccountid()).isEqualTo("1234");
assertThat(account1.getGivenName()).isEqualTo("John");
assertThat(account1.getIdpConfigUrl()).contains("/fedcm/config.json");
assertThat(account1.getPictureUrl()).isEqualTo("https://idp.example/profile/123");
assertThat(account1.getLoginState()).isEqualTo("SignUp");
assertThat(account1.getTermsOfServiceUrl())
.isEqualTo("https://rp.example/terms_of_service.html");
assertThat(account1.getPrivacyPolicyUrl()).isEqualTo("https://rp.example/privacy_policy.html");

FederatedCredentialManagementAccount account2 = accountList.get(1);

assertThat(account2.getName()).isEqualTo("Aisha Ahmad");
assertThat(account2.getEmail()).isEqualTo("[email protected]");
assertThat(account2.getAccountid()).isEqualTo("5678");
assertThat(account2.getGivenName()).isEqualTo("Aisha");
assertThat(account2.getIdpConfigUrl()).contains("/fedcm/config.json");
assertThat(account2.getPictureUrl()).isEqualTo("https://idp.example/profile/567");
assertThat(account2.getLoginState()).isEqualTo("SignUp");
assertThat(account2.getTermsOfServiceUrl())
.isEqualTo("https://rp.example/terms_of_service.html");
assertThat(account2.getPrivacyPolicyUrl()).isEqualTo("https://rp.example/privacy_policy.html");
}
}

0 comments on commit d58c901

Please sign in to comment.