Best Selenium code snippet using org.openqa.selenium.RetrySessionRequestException
Source:SauceNode.java
...27import org.openqa.selenium.Capabilities;28import org.openqa.selenium.ImmutableCapabilities;29import org.openqa.selenium.NoSuchSessionException;30import org.openqa.selenium.PersistentCapabilities;31import org.openqa.selenium.RetrySessionRequestException;32import org.openqa.selenium.WebDriverException;33import org.openqa.selenium.concurrent.Regularly;34import org.openqa.selenium.events.EventBus;35import org.openqa.selenium.grid.data.Availability;36import org.openqa.selenium.grid.data.CreateSessionRequest;37import org.openqa.selenium.grid.data.CreateSessionResponse;38import org.openqa.selenium.grid.data.NodeDrainComplete;39import org.openqa.selenium.grid.data.NodeDrainStarted;40import org.openqa.selenium.grid.data.NodeHeartBeatEvent;41import org.openqa.selenium.grid.data.NodeId;42import org.openqa.selenium.grid.data.NodeStatus;43import org.openqa.selenium.grid.data.Session;44import org.openqa.selenium.grid.data.SessionClosedEvent;45import org.openqa.selenium.grid.data.Slot;46import org.openqa.selenium.grid.data.SlotId;47import org.openqa.selenium.grid.jmx.JMXHelper;48import org.openqa.selenium.grid.jmx.ManagedAttribute;49import org.openqa.selenium.grid.jmx.ManagedService;50import org.openqa.selenium.grid.node.ActiveSession;51import org.openqa.selenium.grid.node.HealthCheck;52import org.openqa.selenium.grid.node.Node;53import org.openqa.selenium.grid.node.SessionFactory;54import org.openqa.selenium.grid.node.config.NodeOptions;55import org.openqa.selenium.grid.node.docker.DockerAssetsPath;56import org.openqa.selenium.grid.node.local.LocalNode;57import org.openqa.selenium.grid.node.local.SessionSlot;58import org.openqa.selenium.grid.security.Secret;59import org.openqa.selenium.internal.Debug;60import org.openqa.selenium.internal.Either;61import org.openqa.selenium.internal.Require;62import org.openqa.selenium.io.TemporaryFilesystem;63import org.openqa.selenium.io.Zip;64import org.openqa.selenium.json.Json;65import org.openqa.selenium.remote.SessionId;66import org.openqa.selenium.remote.http.HttpMethod;67import org.openqa.selenium.remote.http.HttpRequest;68import org.openqa.selenium.remote.http.HttpResponse;69import org.openqa.selenium.remote.tracing.AttributeKey;70import org.openqa.selenium.remote.tracing.EventAttribute;71import org.openqa.selenium.remote.tracing.EventAttributeValue;72import org.openqa.selenium.remote.tracing.Span;73import org.openqa.selenium.remote.tracing.Status;74import org.openqa.selenium.remote.tracing.Tracer;75import java.io.File;76import java.io.IOException;77import java.io.InputStreamReader;78import java.io.UncheckedIOException;79import java.net.URI;80import java.net.URISyntaxException;81import java.nio.file.Files;82import java.nio.file.Paths;83import java.nio.file.StandardCopyOption;84import java.time.Duration;85import java.time.Instant;86import java.util.Collections;87import java.util.HashMap;88import java.util.List;89import java.util.Map;90import java.util.Optional;91import java.util.Set;92import java.util.UUID;93import java.util.concurrent.ExecutionException;94import java.util.concurrent.atomic.AtomicInteger;95import java.util.logging.Level;96import java.util.logging.Logger;97import java.util.stream.Collectors;98@ManagedService(objectName = "com.saucelabs.grid:type=Node,name=SauceNode",99 description = "SauceNode running the webdriver sessions and uploading results to Sauce.")100public class SauceNode extends Node {101 private static final Logger LOG = Logger.getLogger(LocalNode.class.getName());102 private final EventBus bus;103 private final URI externalUri;104 private final URI gridUri;105 private final Duration heartbeatPeriod;106 private final HealthCheck healthCheck;107 private final int maxSessionCount;108 private final List<SessionSlot> factories;109 private final Cache<SessionId, SessionSlot> currentSessions;110 private final Cache<SessionId, TemporaryFilesystem> tempFileSystems;111 private final AtomicInteger pendingSessions = new AtomicInteger();112 private SauceNode(113 Tracer tracer,114 EventBus bus,115 URI uri,116 URI gridUri,117 HealthCheck healthCheck,118 int maxSessionCount,119 Ticker ticker,120 Duration sessionTimeout,121 Duration heartbeatPeriod,122 List<SessionSlot> factories,123 Secret registrationSecret) {124 super(tracer, new NodeId(UUID.randomUUID()), uri, registrationSecret);125 this.bus = Require.nonNull("Event bus", bus);126 this.externalUri = Require.nonNull("Remote node URI", uri);127 this.gridUri = Require.nonNull("Grid URI", gridUri);128 this.maxSessionCount = Math.min(Require.positive("Max session count", maxSessionCount), factories.size());129 this.heartbeatPeriod = heartbeatPeriod;130 this.factories = ImmutableList.copyOf(factories);131 Require.nonNull("Registration secret", registrationSecret);132 this.healthCheck = healthCheck == null ?133 () -> new HealthCheck.Result(134 isDraining() ? DRAINING : UP,135 String.format("%s is %s", uri, isDraining() ? "draining" : "up")) :136 healthCheck;137 this.currentSessions = CacheBuilder.newBuilder()138 .expireAfterAccess(sessionTimeout)139 .ticker(ticker)140 .removalListener((RemovalListener<SessionId, SessionSlot>) notification -> {141 // Attempt to stop the session142 LOG.log(Debug.getDebugLogLevel(), "Stopping session {0}", notification.getKey().toString());143 SessionSlot slot = notification.getValue();144 if (!slot.isAvailable()) {145 slot.stop();146 }147 })148 .build();149 this.tempFileSystems = CacheBuilder.newBuilder()150 .expireAfterAccess(sessionTimeout)151 .ticker(ticker)152 .removalListener((RemovalListener<SessionId, TemporaryFilesystem>) notification -> {153 TemporaryFilesystem tempFS = notification.getValue();154 tempFS.deleteTemporaryFiles();155 tempFS.deleteBaseDir();156 })157 .build();158 Regularly sessionCleanup = new Regularly("Session Cleanup Node: " + externalUri);159 sessionCleanup.submit(currentSessions::cleanUp, Duration.ofSeconds(30), Duration.ofSeconds(30));160 Regularly tmpFileCleanup = new Regularly("TempFile Cleanup Node: " + externalUri);161 tmpFileCleanup.submit(tempFileSystems::cleanUp, Duration.ofSeconds(30), Duration.ofSeconds(30));162 Regularly regularHeartBeat = new Regularly("Heartbeat Node: " + externalUri);163 regularHeartBeat.submit(() -> bus.fire(new NodeHeartBeatEvent(getStatus())), heartbeatPeriod,164 heartbeatPeriod);165 bus.addListener(SessionClosedEvent.listener(id -> {166 // Listen to session terminated events so we know when to fire the NodeDrainComplete event167 if (this.isDraining()) {168 int done = pendingSessions.decrementAndGet();169 if (done <= 0) {170 LOG.info("Firing node drain complete message");171 bus.fire(new NodeDrainComplete(this.getId()));172 }173 }174 }));175 Runtime.getRuntime().addShutdownHook(new Thread(this::stopAllSessions));176 new JMXHelper().register(this);177 }178 public static SauceNode.Builder builder(179 Tracer tracer,180 EventBus bus,181 URI uri,182 URI gridUri,183 Secret registrationSecret) {184 return new SauceNode.Builder(tracer, bus, uri, gridUri, registrationSecret);185 }186 @Override187 public boolean isReady() {188 return bus.isReady();189 }190 @VisibleForTesting191 public int getCurrentSessionCount() {192 // It seems wildly unlikely we'll overflow an int193 return Math.toIntExact(currentSessions.size());194 }195 @ManagedAttribute(name = "MaxSessions")196 public int getMaxSessionCount() {197 return maxSessionCount;198 }199 @ManagedAttribute(name = "Status")200 public Availability getAvailability() {201 return isDraining() ? DRAINING : UP;202 }203 @ManagedAttribute(name = "TotalSlots")204 public int getTotalSlots() {205 return factories.size();206 }207 @ManagedAttribute(name = "UsedSlots")208 public long getUsedSlots() {209 return factories.stream().filter(sessionSlot -> !sessionSlot.isAvailable()).count();210 }211 @ManagedAttribute(name = "Load")212 public float getLoad() {213 long inUse = factories.stream().filter(sessionSlot -> !sessionSlot.isAvailable()).count();214 return inUse / (float) maxSessionCount * 100f;215 }216 @ManagedAttribute(name = "RemoteNodeUri")217 public URI getExternalUri() {218 return this.getUri();219 }220 @ManagedAttribute(name = "GridUri")221 public URI getGridUri() {222 return this.gridUri;223 }224 @ManagedAttribute(name = "NodeId")225 public String getNodeId() {226 return getId().toString();227 }228 @Override229 public boolean isSupporting(Capabilities capabilities) {230 return factories.parallelStream().anyMatch(factory -> factory.test(capabilities));231 }232 @Override233 public Either<WebDriverException, CreateSessionResponse> newSession(CreateSessionRequest sessionRequest) {234 Require.nonNull("Session request", sessionRequest);235 try (Span span = tracer.getCurrentContext().createSpan("node.new_session")) {236 Map<String, EventAttributeValue> attributeMap = new HashMap<>();237 attributeMap238 .put(AttributeKey.LOGGER_CLASS.getKey(), EventAttribute.setValue(getClass().getName()));239 LOG.fine("Creating new session using span: " + span);240 attributeMap.put("session.request.capabilities",241 EventAttribute.setValue(sessionRequest.getDesiredCapabilities().toString()));242 attributeMap.put("session.request.downstreamdialect",243 EventAttribute.setValue(sessionRequest.getDownstreamDialects().toString()));244 int currentSessionCount = getCurrentSessionCount();245 span.setAttribute("current.session.count", currentSessionCount);246 attributeMap.put("current.session.count", EventAttribute.setValue(currentSessionCount));247 if (getCurrentSessionCount() >= maxSessionCount) {248 span.setAttribute("error", true);249 span.setStatus(Status.RESOURCE_EXHAUSTED);250 attributeMap.put("max.session.count", EventAttribute.setValue(maxSessionCount));251 span.addEvent("Max session count reached", attributeMap);252 return Either.left(new RetrySessionRequestException("Max session count reached."));253 }254 if (isDraining()) {255 span.setStatus(Status.UNAVAILABLE.withDescription("The node is draining. Cannot accept new sessions."));256 return Either.left(257 new RetrySessionRequestException("The node is draining. Cannot accept new sessions."));258 }259 // Identify possible slots to use as quickly as possible to enable concurrent session starting260 SessionSlot slotToUse = null;261 synchronized(factories) {262 for (SessionSlot factory : factories) {263 if (!factory.isAvailable() || !factory.test(sessionRequest.getDesiredCapabilities())) {264 continue;265 }266 factory.reserve();267 slotToUse = factory;268 break;269 }270 }271 if (slotToUse == null) {272 span.setAttribute("error", true);273 span.setStatus(Status.NOT_FOUND);274 span.addEvent("No slot matched capabilities ", attributeMap);275 return Either.left(276 new RetrySessionRequestException("No slot matched the requested capabilities."));277 }278 Either<WebDriverException, ActiveSession> possibleSession = slotToUse.apply(sessionRequest);279 if (possibleSession.isRight()) {280 ActiveSession session = possibleSession.right();281 currentSessions.put(session.getId(), slotToUse);282 SessionId sessionId = session.getId();283 Capabilities caps = session.getCapabilities();284 SESSION_ID.accept(span, sessionId);285 CAPABILITIES.accept(span, caps);286 String downstream = session.getDownstreamDialect().toString();287 String upstream = session.getUpstreamDialect().toString();288 String sessionUri = session.getUri().toString();289 span.setAttribute(AttributeKey.DOWNSTREAM_DIALECT.getKey(), downstream);290 span.setAttribute(AttributeKey.UPSTREAM_DIALECT.getKey(), upstream);...
Source:LocalNode.java
...25import org.openqa.selenium.Capabilities;26import org.openqa.selenium.ImmutableCapabilities;27import org.openqa.selenium.NoSuchSessionException;28import org.openqa.selenium.PersistentCapabilities;29import org.openqa.selenium.RetrySessionRequestException;30import org.openqa.selenium.WebDriverException;31import org.openqa.selenium.concurrent.Regularly;32import org.openqa.selenium.events.EventBus;33import org.openqa.selenium.grid.data.Availability;34import org.openqa.selenium.grid.data.CreateSessionRequest;35import org.openqa.selenium.grid.data.CreateSessionResponse;36import org.openqa.selenium.grid.data.NodeAddedEvent;37import org.openqa.selenium.grid.data.NodeDrainComplete;38import org.openqa.selenium.grid.data.NodeDrainStarted;39import org.openqa.selenium.grid.data.NodeHeartBeatEvent;40import org.openqa.selenium.grid.data.NodeId;41import org.openqa.selenium.grid.data.NodeStatus;42import org.openqa.selenium.grid.data.Session;43import org.openqa.selenium.grid.data.SessionClosedEvent;44import org.openqa.selenium.grid.data.Slot;45import org.openqa.selenium.grid.data.SlotId;46import org.openqa.selenium.grid.jmx.JMXHelper;47import org.openqa.selenium.grid.jmx.ManagedAttribute;48import org.openqa.selenium.grid.jmx.ManagedService;49import org.openqa.selenium.grid.node.ActiveSession;50import org.openqa.selenium.grid.node.HealthCheck;51import org.openqa.selenium.grid.node.Node;52import org.openqa.selenium.grid.node.SessionFactory;53import org.openqa.selenium.grid.node.config.NodeOptions;54import org.openqa.selenium.grid.security.Secret;55import org.openqa.selenium.internal.Either;56import org.openqa.selenium.internal.Require;57import org.openqa.selenium.io.TemporaryFilesystem;58import org.openqa.selenium.io.Zip;59import org.openqa.selenium.json.Json;60import org.openqa.selenium.remote.SessionId;61import org.openqa.selenium.remote.http.HttpRequest;62import org.openqa.selenium.remote.http.HttpResponse;63import org.openqa.selenium.remote.tracing.AttributeKey;64import org.openqa.selenium.remote.tracing.EventAttribute;65import org.openqa.selenium.remote.tracing.EventAttributeValue;66import org.openqa.selenium.remote.tracing.Span;67import org.openqa.selenium.remote.tracing.Status;68import org.openqa.selenium.remote.tracing.Tracer;69import java.io.File;70import java.io.IOException;71import java.io.UncheckedIOException;72import java.net.URI;73import java.net.URISyntaxException;74import java.time.Clock;75import java.time.Duration;76import java.time.Instant;77import java.util.HashMap;78import java.util.List;79import java.util.Map;80import java.util.Optional;81import java.util.Set;82import java.util.UUID;83import java.util.concurrent.ExecutionException;84import java.util.concurrent.atomic.AtomicBoolean;85import java.util.concurrent.atomic.AtomicInteger;86import java.util.logging.Logger;87import java.util.stream.Collectors;88import static com.google.common.collect.ImmutableSet.toImmutableSet;89import static org.openqa.selenium.grid.data.Availability.DRAINING;90import static org.openqa.selenium.grid.data.Availability.UP;91import static org.openqa.selenium.grid.node.CapabilityResponseEncoder.getEncoder;92import static org.openqa.selenium.remote.HttpSessionId.getSessionId;93import static org.openqa.selenium.remote.RemoteTags.CAPABILITIES;94import static org.openqa.selenium.remote.RemoteTags.SESSION_ID;95import static org.openqa.selenium.remote.http.Contents.asJson;96import static org.openqa.selenium.remote.http.Contents.string;97import static org.openqa.selenium.remote.http.HttpMethod.DELETE;98@ManagedService(objectName = "org.seleniumhq.grid:type=Node,name=LocalNode",99 description = "Node running the webdriver sessions.")100public class LocalNode extends Node {101 private static final Json JSON = new Json();102 private static final Logger LOG = Logger.getLogger(LocalNode.class.getName());103 private final EventBus bus;104 private final URI externalUri;105 private final URI gridUri;106 private final Duration heartbeatPeriod;107 private final HealthCheck healthCheck;108 private final int maxSessionCount;109 private final List<SessionSlot> factories;110 private final Cache<SessionId, SessionSlot> currentSessions;111 private final Cache<SessionId, TemporaryFilesystem> tempFileSystems;112 private final Regularly regularly;113 private final AtomicInteger pendingSessions = new AtomicInteger();114 private final AtomicBoolean heartBeatStarted = new AtomicBoolean(false);115 private LocalNode(116 Tracer tracer,117 EventBus bus,118 URI uri,119 URI gridUri,120 HealthCheck healthCheck,121 int maxSessionCount,122 Ticker ticker,123 Duration sessionTimeout,124 Duration heartbeatPeriod,125 List<SessionSlot> factories,126 Secret registrationSecret) {127 super(tracer, new NodeId(UUID.randomUUID()), uri, registrationSecret);128 this.bus = Require.nonNull("Event bus", bus);129 this.externalUri = Require.nonNull("Remote node URI", uri);130 this.gridUri = Require.nonNull("Grid URI", gridUri);131 this.maxSessionCount = Math.min(Require.positive("Max session count", maxSessionCount), factories.size());132 this.heartbeatPeriod = heartbeatPeriod;133 this.factories = ImmutableList.copyOf(factories);134 Require.nonNull("Registration secret", registrationSecret);135 this.healthCheck = healthCheck == null ?136 () -> new HealthCheck.Result(137 isDraining() ? DRAINING : UP,138 String.format("%s is %s", uri, isDraining() ? "draining" : "up")) :139 healthCheck;140 this.currentSessions = CacheBuilder.newBuilder()141 .expireAfterAccess(sessionTimeout)142 .ticker(ticker)143 .removalListener((RemovalListener<SessionId, SessionSlot>) notification -> {144 // If we were invoked explicitly, then return: we know what we're doing.145 if (!notification.wasEvicted()) {146 return;147 }148 killSession(notification.getValue());149 })150 .build();151 this.tempFileSystems = CacheBuilder.newBuilder()152 .expireAfterAccess(sessionTimeout)153 .ticker(ticker)154 .removalListener((RemovalListener<SessionId, TemporaryFilesystem>) notification -> {155 TemporaryFilesystem tempFS = notification.getValue();156 tempFS.deleteTemporaryFiles();157 tempFS.deleteBaseDir();158 })159 .build();160 this.regularly = new Regularly("Local Node: " + externalUri);161 regularly.submit(currentSessions::cleanUp, Duration.ofSeconds(30), Duration.ofSeconds(30));162 regularly.submit(tempFileSystems::cleanUp, Duration.ofSeconds(30), Duration.ofSeconds(30));163 bus.addListener(NodeAddedEvent.listener(nodeId -> {164 if (getId().equals(nodeId)) {165 // Lets avoid to create more than one "Regularly" when the Node registers again.166 if (!heartBeatStarted.getAndSet(true)) {167 regularly.submit(168 () -> bus.fire(new NodeHeartBeatEvent(getStatus())), heartbeatPeriod, heartbeatPeriod);169 }170 }171 }));172 bus.addListener(SessionClosedEvent.listener(id -> {173 try {174 this.stop(id);175 } catch (NoSuchSessionException ignore) {176 }177 if (this.isDraining()) {178 int done = pendingSessions.decrementAndGet();179 if (done <= 0) {180 LOG.info("Firing node drain complete message");181 bus.fire(new NodeDrainComplete(this.getId()));182 }183 }184 }));185 new JMXHelper().register(this);186 }187 public static Builder builder(188 Tracer tracer,189 EventBus bus,190 URI uri,191 URI gridUri,192 Secret registrationSecret) {193 return new Builder(tracer, bus, uri, gridUri, registrationSecret);194 }195 @Override196 public boolean isReady() {197 return bus.isReady();198 }199 @VisibleForTesting200 @ManagedAttribute(name = "CurrentSessions")201 public int getCurrentSessionCount() {202 // It seems wildly unlikely we'll overflow an int203 return Math.toIntExact(currentSessions.size());204 }205 @ManagedAttribute(name = "MaxSessions")206 public int getMaxSessionCount() {207 return maxSessionCount;208 }209 @ManagedAttribute(name = "Status")210 public Availability getAvailability() {211 return isDraining() ? DRAINING : UP;212 }213 @ManagedAttribute(name = "TotalSlots")214 public int getTotalSlots() {215 return factories.size();216 }217 @ManagedAttribute(name = "UsedSlots")218 public long getUsedSlots() {219 return factories.stream().filter(sessionSlot -> !sessionSlot.isAvailable()).count();220 }221 @ManagedAttribute(name = "Load")222 public float getLoad() {223 long inUse = factories.stream().filter(sessionSlot -> !sessionSlot.isAvailable()).count();224 return inUse / (float) maxSessionCount * 100f;225 }226 @ManagedAttribute(name = "RemoteNodeUri")227 public URI getExternalUri() {228 return this.getUri();229 }230 @ManagedAttribute(name = "GridUri")231 public URI getGridUri() {232 return this.gridUri;233 }234 @ManagedAttribute(name = "NodeId")235 public String getNodeId() {236 return getId().toString();237 }238 @Override239 public boolean isSupporting(Capabilities capabilities) {240 return factories.parallelStream().anyMatch(factory -> factory.test(capabilities));241 }242 @Override243 public Either<WebDriverException, CreateSessionResponse> newSession(CreateSessionRequest sessionRequest) {244 Require.nonNull("Session request", sessionRequest);245 try (Span span = tracer.getCurrentContext().createSpan("node.new_session")) {246 Map<String, EventAttributeValue> attributeMap = new HashMap<>();247 attributeMap248 .put(AttributeKey.LOGGER_CLASS.getKey(), EventAttribute.setValue(getClass().getName()));249 attributeMap.put("session.request.capabilities",250 EventAttribute.setValue(sessionRequest.getDesiredCapabilities().toString()));251 attributeMap.put("session.request.downstreamdialect",252 EventAttribute.setValue(sessionRequest.getDownstreamDialects().toString()));253 int currentSessionCount = getCurrentSessionCount();254 span.setAttribute("current.session.count", currentSessionCount);255 attributeMap.put("current.session.count", EventAttribute.setValue(currentSessionCount));256 if (getCurrentSessionCount() >= maxSessionCount) {257 span.setAttribute("error", true);258 span.setStatus(Status.RESOURCE_EXHAUSTED);259 attributeMap.put("max.session.count", EventAttribute.setValue(maxSessionCount));260 span.addEvent("Max session count reached", attributeMap);261 return Either.left(new RetrySessionRequestException("Max session count reached."));262 }263 if (isDraining()) {264 span.setStatus(Status.UNAVAILABLE.withDescription("The node is draining. Cannot accept new sessions."));265 return Either.left(266 new RetrySessionRequestException("The node is draining. Cannot accept new sessions."));267 }268 // Identify possible slots to use as quickly as possible to enable concurrent session starting269 SessionSlot slotToUse = null;270 synchronized (factories) {271 for (SessionSlot factory : factories) {272 if (!factory.isAvailable() || !factory.test(sessionRequest.getDesiredCapabilities())) {273 continue;274 }275 factory.reserve();276 slotToUse = factory;277 break;278 }279 }280 if (slotToUse == null) {281 span.setAttribute("error", true);282 span.setStatus(Status.NOT_FOUND);283 span.addEvent("No slot matched the requested capabilities. ", attributeMap);284 return Either.left(285 new RetrySessionRequestException("No slot matched the requested capabilities."));286 }287 Either<WebDriverException, ActiveSession> possibleSession = slotToUse.apply(sessionRequest);288 if (possibleSession.isRight()) {289 ActiveSession session = possibleSession.right();290 currentSessions.put(session.getId(), slotToUse);291 SessionId sessionId = session.getId();292 Capabilities caps = session.getCapabilities();293 SESSION_ID.accept(span, sessionId);294 CAPABILITIES.accept(span, caps);295 String downstream = session.getDownstreamDialect().toString();296 String upstream = session.getUpstreamDialect().toString();297 String sessionUri = session.getUri().toString();298 span.setAttribute(AttributeKey.DOWNSTREAM_DIALECT.getKey(), downstream);299 span.setAttribute(AttributeKey.UPSTREAM_DIALECT.getKey(), upstream);...
Source:DockerSessionFactory.java
...17package org.openqa.selenium.grid.docker;18import org.openqa.selenium.Capabilities;19import org.openqa.selenium.Dimension;20import org.openqa.selenium.ImmutableCapabilities;21import org.openqa.selenium.RetrySessionRequestException;22import org.openqa.selenium.SessionNotCreatedException;23import org.openqa.selenium.TimeoutException;24import org.openqa.selenium.WebDriverException;25import org.openqa.selenium.docker.Container;26import org.openqa.selenium.docker.ContainerConfig;27import org.openqa.selenium.docker.ContainerInfo;28import org.openqa.selenium.docker.Docker;29import org.openqa.selenium.docker.Image;30import org.openqa.selenium.docker.Port;31import org.openqa.selenium.grid.data.CreateSessionRequest;32import org.openqa.selenium.grid.node.ActiveSession;33import org.openqa.selenium.grid.node.SessionFactory;34import org.openqa.selenium.internal.Either;35import org.openqa.selenium.internal.Require;36import org.openqa.selenium.json.Json;37import org.openqa.selenium.net.PortProber;38import org.openqa.selenium.remote.Command;39import org.openqa.selenium.remote.Dialect;40import org.openqa.selenium.remote.DriverCommand;41import org.openqa.selenium.remote.ProtocolHandshake;42import org.openqa.selenium.remote.Response;43import org.openqa.selenium.remote.SessionId;44import org.openqa.selenium.remote.http.HttpClient;45import org.openqa.selenium.remote.http.HttpRequest;46import org.openqa.selenium.remote.http.HttpResponse;47import org.openqa.selenium.remote.tracing.AttributeKey;48import org.openqa.selenium.remote.tracing.EventAttribute;49import org.openqa.selenium.remote.tracing.EventAttributeValue;50import org.openqa.selenium.remote.tracing.Span;51import org.openqa.selenium.remote.tracing.Status;52import org.openqa.selenium.remote.tracing.Tracer;53import org.openqa.selenium.support.ui.FluentWait;54import org.openqa.selenium.support.ui.Wait;55import java.io.IOException;56import java.io.UncheckedIOException;57import java.net.MalformedURLException;58import java.net.URI;59import java.net.URL;60import java.nio.charset.Charset;61import java.nio.file.Files;62import java.nio.file.Paths;63import java.time.Duration;64import java.time.Instant;65import java.util.Arrays;66import java.util.Collections;67import java.util.HashMap;68import java.util.Map;69import java.util.Objects;70import java.util.Optional;71import java.util.TimeZone;72import java.util.logging.Level;73import java.util.logging.Logger;74import static java.util.Optional.ofNullable;75import static org.openqa.selenium.docker.ContainerConfig.image;76import static org.openqa.selenium.remote.Dialect.W3C;77import static org.openqa.selenium.remote.http.Contents.string;78import static org.openqa.selenium.remote.http.HttpMethod.GET;79import static org.openqa.selenium.remote.tracing.Tags.EXCEPTION;80public class DockerSessionFactory implements SessionFactory {81 private static final Logger LOG = Logger.getLogger(DockerSessionFactory.class.getName());82 private final Tracer tracer;83 private final HttpClient.Factory clientFactory;84 private final Docker docker;85 private final URI dockerUri;86 private final Image browserImage;87 private final Capabilities stereotype;88 private final Image videoImage;89 private final DockerAssetsPath assetsPath;90 private final String networkName;91 private final boolean runningInDocker;92 public DockerSessionFactory(93 Tracer tracer,94 HttpClient.Factory clientFactory,95 Docker docker,96 URI dockerUri,97 Image browserImage,98 Capabilities stereotype,99 Image videoImage,100 DockerAssetsPath assetsPath,101 String networkName,102 boolean runningInDocker) {103 this.tracer = Require.nonNull("Tracer", tracer);104 this.clientFactory = Require.nonNull("HTTP client", clientFactory);105 this.docker = Require.nonNull("Docker command", docker);106 this.dockerUri = Require.nonNull("Docker URI", dockerUri);107 this.browserImage = Require.nonNull("Docker browser image", browserImage);108 this.networkName = Require.nonNull("Docker network name", networkName);109 this.stereotype = ImmutableCapabilities.copyOf(110 Require.nonNull("Stereotype", stereotype));111 this.videoImage = videoImage;112 this.assetsPath = assetsPath;113 this.runningInDocker = runningInDocker;114 }115 @Override116 public boolean test(Capabilities capabilities) {117 return stereotype.getCapabilityNames().stream()118 .map(119 name ->120 Objects.equals(stereotype.getCapability(name), capabilities.getCapability(name)))121 .reduce(Boolean::logicalAnd)122 .orElse(false);123 }124 @Override125 public Either<WebDriverException, ActiveSession> apply(CreateSessionRequest sessionRequest) {126 LOG.info("Starting session for " + sessionRequest.getDesiredCapabilities());127 int port = runningInDocker ? 4444 : PortProber.findFreePort();128 try (Span span = tracer.getCurrentContext().createSpan("docker_session_factory.apply")) {129 Map<String, EventAttributeValue> attributeMap = new HashMap<>();130 attributeMap.put(AttributeKey.LOGGER_CLASS.getKey(),131 EventAttribute.setValue(this.getClass().getName()));132 String logMessage = runningInDocker ? "Creating container..." :133 "Creating container, mapping container port 4444 to " + port;134 LOG.info(logMessage);135 Container container = createBrowserContainer(port, sessionRequest.getDesiredCapabilities());136 container.start();137 ContainerInfo containerInfo = container.inspect();138 String containerIp = containerInfo.getIp();139 URL remoteAddress = getUrl(port, containerIp);140 HttpClient client = clientFactory.createClient(remoteAddress);141 attributeMap.put("docker.browser.image", EventAttribute.setValue(browserImage.toString()));142 attributeMap.put("container.port", EventAttribute.setValue(port));143 attributeMap.put("container.id", EventAttribute.setValue(container.getId().toString()));144 attributeMap.put("container.ip", EventAttribute.setValue(containerIp));145 attributeMap.put("docker.server.url", EventAttribute.setValue(remoteAddress.toString()));146 LOG.info(147 String.format("Waiting for server to start (container id: %s, url %s)",148 container.getId(),149 remoteAddress));150 try {151 waitForServerToStart(client, Duration.ofMinutes(1));152 } catch (TimeoutException e) {153 span.setAttribute("error", true);154 span.setStatus(Status.CANCELLED);155 EXCEPTION.accept(attributeMap, e);156 attributeMap.put(AttributeKey.EXCEPTION_MESSAGE.getKey(),157 EventAttribute.setValue(158 "Unable to connect to docker server. Stopping container: " +159 e.getMessage()));160 span.addEvent(AttributeKey.EXCEPTION_EVENT.getKey(), attributeMap);161 container.stop(Duration.ofMinutes(1));162 String message = String.format(163 "Unable to connect to docker server (container id: %s)", container.getId());164 LOG.warning(message);165 return Either.left(new RetrySessionRequestException(message));166 }167 LOG.info(String.format("Server is ready (container id: %s)", container.getId()));168 Command command = new Command(169 null,170 DriverCommand.NEW_SESSION(sessionRequest.getDesiredCapabilities()));171 ProtocolHandshake.Result result;172 Response response;173 try {174 result = new ProtocolHandshake().createSession(client, command);175 response = result.createResponse();176 attributeMap.put(AttributeKey.DRIVER_RESPONSE.getKey(),177 EventAttribute.setValue(response.toString()));178 } catch (IOException | RuntimeException e) {179 span.setAttribute("error", true);...
Source:LocalDistributor.java
...18import com.google.common.collect.ImmutableSet;19import org.openqa.selenium.Beta;20import org.openqa.selenium.Capabilities;21import org.openqa.selenium.ImmutableCapabilities;22import org.openqa.selenium.RetrySessionRequestException;23import org.openqa.selenium.SessionNotCreatedException;24import org.openqa.selenium.WebDriverException;25import org.openqa.selenium.concurrent.Regularly;26import org.openqa.selenium.events.EventBus;27import org.openqa.selenium.grid.config.Config;28import org.openqa.selenium.grid.data.CreateSessionRequest;29import org.openqa.selenium.grid.data.CreateSessionResponse;30import org.openqa.selenium.grid.data.DistributorStatus;31import org.openqa.selenium.grid.data.NewSessionErrorResponse;32import org.openqa.selenium.grid.data.NewSessionRejectedEvent;33import org.openqa.selenium.grid.data.NewSessionRequestEvent;34import org.openqa.selenium.grid.data.NewSessionResponse;35import org.openqa.selenium.grid.data.NewSessionResponseEvent;36import org.openqa.selenium.grid.data.NodeAddedEvent;37import org.openqa.selenium.grid.data.NodeDrainComplete;38import org.openqa.selenium.grid.data.NodeHeartBeatEvent;39import org.openqa.selenium.grid.data.NodeId;40import org.openqa.selenium.grid.data.NodeStatus;41import org.openqa.selenium.grid.data.NodeStatusEvent;42import org.openqa.selenium.grid.data.RequestId;43import org.openqa.selenium.grid.data.Slot;44import org.openqa.selenium.grid.data.SlotId;45import org.openqa.selenium.grid.distributor.Distributor;46import org.openqa.selenium.grid.distributor.config.DistributorOptions;47import org.openqa.selenium.grid.distributor.selector.DefaultSlotSelector;48import org.openqa.selenium.grid.log.LoggingOptions;49import org.openqa.selenium.grid.node.HealthCheck;50import org.openqa.selenium.grid.node.Node;51import org.openqa.selenium.grid.node.remote.RemoteNode;52import org.openqa.selenium.grid.security.Secret;53import org.openqa.selenium.grid.security.SecretOptions;54import org.openqa.selenium.grid.server.EventBusOptions;55import org.openqa.selenium.grid.server.NetworkOptions;56import org.openqa.selenium.grid.sessionmap.SessionMap;57import org.openqa.selenium.grid.sessionmap.config.SessionMapOptions;58import org.openqa.selenium.grid.sessionqueue.NewSessionQueuer;59import org.openqa.selenium.grid.sessionqueue.config.NewSessionQueuerOptions;60import org.openqa.selenium.internal.Either;61import org.openqa.selenium.internal.Require;62import org.openqa.selenium.remote.http.HttpClient;63import org.openqa.selenium.remote.http.HttpRequest;64import org.openqa.selenium.remote.tracing.AttributeKey;65import org.openqa.selenium.remote.tracing.EventAttribute;66import org.openqa.selenium.remote.tracing.EventAttributeValue;67import org.openqa.selenium.remote.tracing.Span;68import org.openqa.selenium.remote.tracing.Tracer;69import org.openqa.selenium.status.HasReadyState;70import java.time.Duration;71import java.util.ArrayList;72import java.util.HashMap;73import java.util.List;74import java.util.Map;75import java.util.Optional;76import java.util.Queue;77import java.util.Set;78import java.util.concurrent.ConcurrentHashMap;79import java.util.concurrent.ConcurrentLinkedQueue;80import java.util.concurrent.Executors;81import java.util.concurrent.ScheduledExecutorService;82import java.util.concurrent.ThreadFactory;83import java.util.concurrent.TimeUnit;84import java.util.concurrent.locks.Lock;85import java.util.concurrent.locks.ReadWriteLock;86import java.util.concurrent.locks.ReentrantReadWriteLock;87import java.util.logging.Level;88import java.util.logging.Logger;89import static com.google.common.collect.ImmutableSet.toImmutableSet;90import static org.openqa.selenium.grid.data.Availability.DOWN;91import static org.openqa.selenium.grid.data.Availability.DRAINING;92import static org.openqa.selenium.remote.tracing.HttpTracing.newSpanAsChildOf;93public class LocalDistributor extends Distributor {94 private static final Logger LOG = Logger.getLogger(LocalDistributor.class.getName());95 private final Tracer tracer;96 private final EventBus bus;97 private final HttpClient.Factory clientFactory;98 private final SessionMap sessions;99 private final Secret registrationSecret;100 private final Regularly hostChecker = new Regularly("distributor host checker");101 private final Map<NodeId, Runnable> allChecks = new HashMap<>();102 private final Queue<RequestId> requestIds = new ConcurrentLinkedQueue<>();103 private final ScheduledExecutorService executorService;104 private final Duration healthcheckInterval;105 private final ReadWriteLock lock = new ReentrantReadWriteLock(/* fair */ true);106 private final GridModel model;107 private final Map<NodeId, Node> nodes;108 private final NewSessionQueuer sessionRequests;109 public LocalDistributor(110 Tracer tracer,111 EventBus bus,112 HttpClient.Factory clientFactory,113 SessionMap sessions,114 NewSessionQueuer sessionRequests,115 Secret registrationSecret,116 Duration healthcheckInterval) {117 super(tracer, clientFactory, new DefaultSlotSelector(), sessions, registrationSecret);118 this.tracer = Require.nonNull("Tracer", tracer);119 this.bus = Require.nonNull("Event bus", bus);120 this.clientFactory = Require.nonNull("HTTP client factory", clientFactory);121 this.sessions = Require.nonNull("Session map", sessions);122 this.model = new GridModel(bus);123 this.nodes = new ConcurrentHashMap<>();124 this.sessionRequests = Require.nonNull("New Session Request Queue", sessionRequests);125 this.registrationSecret = Require.nonNull("Registration secret", registrationSecret);126 this.healthcheckInterval = Require.nonNull("Health check interval", healthcheckInterval);127 bus.addListener(NodeStatusEvent.listener(this::register));128 bus.addListener(NodeStatusEvent.listener(model::refresh));129 bus.addListener(NodeHeartBeatEvent.listener(nodeStatus -> {130 if (nodes.containsKey(nodeStatus.getId())) {131 model.touch(nodeStatus.getId());132 } else {133 register(nodeStatus);134 }135 }));136 bus.addListener(NodeDrainComplete.listener(this::remove));137 bus.addListener(NewSessionRequestEvent.listener(requestIds::offer));138 Regularly regularly = new Regularly("Local Distributor");139 regularly.submit(model::purgeDeadNodes, Duration.ofSeconds(30), Duration.ofSeconds(30));140 Thread shutdownHook = new Thread(this::callExecutorShutdown);141 Runtime.getRuntime().addShutdownHook(shutdownHook);142 NewSessionRunnable runnable = new NewSessionRunnable();143 ThreadFactory threadFactory = r -> {144 Thread thread = new Thread(r);145 thread.setName("New Session Creation");146 thread.setDaemon(true);147 return thread;148 };149 executorService = Executors.newSingleThreadScheduledExecutor(threadFactory);150 executorService.scheduleAtFixedRate(runnable, 0, 1000, TimeUnit.MILLISECONDS);151 }152 public static Distributor create(Config config) {153 Tracer tracer = new LoggingOptions(config).getTracer();154 EventBus bus = new EventBusOptions(config).getEventBus();155 DistributorOptions distributorOptions = new DistributorOptions(config);156 HttpClient.Factory clientFactory = new NetworkOptions(config).getHttpClientFactory(tracer);157 SessionMap sessions = new SessionMapOptions(config).getSessionMap();158 SecretOptions secretOptions = new SecretOptions(config);159 NewSessionQueuer sessionRequests =160 new NewSessionQueuerOptions(config).getSessionQueuer(161 "org.openqa.selenium.grid.sessionqueue.remote.RemoteNewSessionQueuer");162 return new LocalDistributor(163 tracer,164 bus,165 clientFactory,166 sessions,167 sessionRequests,168 secretOptions.getRegistrationSecret(),169 distributorOptions.getHealthCheckInterval());170 }171 @Override172 public boolean isReady() {173 try {174 return ImmutableSet.of(bus, sessions).parallelStream()175 .map(HasReadyState::isReady)176 .reduce(true, Boolean::logicalAnd);177 } catch (RuntimeException e) {178 return false;179 }180 }181 private void register(NodeStatus status) {182 Require.nonNull("Node", status);183 Lock writeLock = lock.writeLock();184 writeLock.lock();185 try {186 if (nodes.containsKey(status.getId())) {187 return;188 }189 Set<Capabilities> capabilities = status.getSlots().stream()190 .map(Slot::getStereotype)191 .map(ImmutableCapabilities::copyOf)192 .collect(toImmutableSet());193 // A new node! Add this as a remote node, since we've not called add194 RemoteNode remoteNode = new RemoteNode(195 tracer,196 clientFactory,197 status.getId(),198 status.getUri(),199 registrationSecret,200 capabilities);201 add(remoteNode);202 } finally {203 writeLock.unlock();204 }205 }206 @Override207 public LocalDistributor add(Node node) {208 Require.nonNull("Node", node);209 LOG.info(String.format("Added node %s at %s.", node.getId(), node.getUri()));210 nodes.put(node.getId(), node);211 model.add(node.getStatus());212 // Extract the health check213 Runnable runnableHealthCheck = asRunnableHealthCheck(node);214 allChecks.put(node.getId(), runnableHealthCheck);215 hostChecker.submit(runnableHealthCheck, healthcheckInterval, Duration.ofSeconds(30));216 bus.fire(new NodeAddedEvent(node.getId()));217 return this;218 }219 private Runnable asRunnableHealthCheck(Node node) {220 HealthCheck healthCheck = node.getHealthCheck();221 NodeId id = node.getId();222 return () -> {223 HealthCheck.Result result;224 try {225 result = healthCheck.check();226 } catch (Exception e) {227 LOG.log(Level.WARNING, "Unable to process node " + id, e);228 result = new HealthCheck.Result(DOWN, "Unable to run healthcheck. Assuming down");229 }230 Lock writeLock = lock.writeLock();231 writeLock.lock();232 try {233 model.setAvailability(id, result.getAvailability());234 } finally {235 writeLock.unlock();236 }237 };238 }239 @Override240 public boolean drain(NodeId nodeId) {241 Node node = nodes.get(nodeId);242 if (node == null) {243 LOG.info("Asked to drain unregistered node " + nodeId);244 return false;245 }246 Lock writeLock = lock.writeLock();247 writeLock.lock();248 try {249 node.drain();250 model.setAvailability(nodeId, DRAINING);251 } finally {252 writeLock.unlock();253 }254 return node.isDraining();255 }256 public void remove(NodeId nodeId) {257 Lock writeLock = lock.writeLock();258 writeLock.lock();259 try {260 model.remove(nodeId);261 Runnable runnable = allChecks.remove(nodeId);262 if (runnable != null) {263 hostChecker.remove(runnable);264 }265 } finally {266 writeLock.unlock();267 }268 }269 @Override270 public DistributorStatus getStatus() {271 Lock readLock = this.lock.readLock();272 readLock.lock();273 try {274 return new DistributorStatus(model.getSnapshot());275 } finally {276 readLock.unlock();277 }278 }279 @Beta280 public void refresh() {281 List<Runnable> allHealthChecks = new ArrayList<>();282 Lock readLock = this.lock.readLock();283 readLock.lock();284 try {285 allHealthChecks.addAll(allChecks.values());286 } finally {287 readLock.unlock();288 }289 allHealthChecks.parallelStream().forEach(Runnable::run);290 }291 @Override292 protected Set<NodeStatus> getAvailableNodes() {293 Lock readLock = this.lock.readLock();294 readLock.lock();295 try {296 return model.getSnapshot().stream()297 .filter(node -> !DOWN.equals(node.getAvailability()))298 .collect(toImmutableSet());299 } finally {300 readLock.unlock();301 }302 }303 @Override304 protected Either<SessionNotCreatedException, CreateSessionResponse> reserve(SlotId slotId, CreateSessionRequest request) {305 Require.nonNull("Slot ID", slotId);306 Require.nonNull("New Session request", request);307 Lock writeLock = this.lock.writeLock();308 writeLock.lock();309 try {310 Node node = nodes.get(slotId.getOwningNodeId());311 if (node == null) {312 return Either.left(new RetrySessionRequestException(313 "Unable to find node. Try a different node"));314 }315 model.reserve(slotId);316 Either<WebDriverException, CreateSessionResponse> response = node.newSession(request);317 if (response.isRight()) {318 model.setSession(slotId, response.right().getSession());319 return Either.right(response.right());320 } else {321 model.setSession(slotId, null);322 WebDriverException exception = response.left();323 if (exception instanceof RetrySessionRequestException) {324 return Either.left(new RetrySessionRequestException(exception.getMessage()));325 } else {326 return Either.left(new SessionNotCreatedException(exception.getMessage()));327 }328 }329 } finally {330 writeLock.unlock();331 }332 }333 public void callExecutorShutdown() {334 LOG.info("Shutting down Distributor executor service");335 executorService.shutdownNow();336 }337 public class NewSessionRunnable implements Runnable {338 @Override339 public void run() {340 Lock writeLock = lock.writeLock();341 writeLock.lock();342 try {343 if (!requestIds.isEmpty()) {344 Set<NodeStatus> availableNodes = ImmutableSet.copyOf(getAvailableNodes());345 boolean hasCapacity = availableNodes.stream()346 .anyMatch(NodeStatus::hasCapacity);347 if (hasCapacity) {348 RequestId reqId = requestIds.poll();349 if (reqId != null) {350 Optional<HttpRequest> optionalHttpRequest = sessionRequests.remove(reqId);351 // Check if polling the queue did not return null352 if (optionalHttpRequest.isPresent()) {353 handleNewSessionRequest(optionalHttpRequest.get(), reqId);354 } else {355 fireSessionRejectedEvent(356 "Unable to poll request from the new session request queue.",357 reqId);358 }359 }360 }361 }362 } finally {363 writeLock.unlock();364 }365 }366 private void handleNewSessionRequest(HttpRequest sessionRequest, RequestId reqId) {367 try (Span span = newSpanAsChildOf(tracer, sessionRequest, "distributor.poll_queue")) {368 Map<String, EventAttributeValue> attributeMap = new HashMap<>();369 attributeMap.put(370 AttributeKey.LOGGER_CLASS.getKey(),371 EventAttribute.setValue(getClass().getName()));372 span.setAttribute(AttributeKey.REQUEST_ID.getKey(), reqId.toString());373 attributeMap.put(374 AttributeKey.REQUEST_ID.getKey(),375 EventAttribute.setValue(reqId.toString()));376 attributeMap.put("request", EventAttribute.setValue(sessionRequest.toString()));377 Either<SessionNotCreatedException, CreateSessionResponse> response =378 newSession(sessionRequest);379 if (response.isRight()) {380 CreateSessionResponse sessionResponse = response.right();381 NewSessionResponse newSessionResponse =382 new NewSessionResponse(383 reqId,384 sessionResponse.getSession(),385 sessionResponse.getDownstreamEncodedResponse());386 bus.fire(new NewSessionResponseEvent(newSessionResponse));387 } else {388 SessionNotCreatedException exception = response.left();389 if (exception instanceof RetrySessionRequestException) {390 boolean retried = sessionRequests.retryAddToQueue(sessionRequest, reqId);391 attributeMap.put("request.retry_add", EventAttribute.setValue(retried));392 span.addEvent("Retry adding to front of queue. No slot available.", attributeMap);393 if (!retried) {394 span.addEvent("Retry adding to front of queue failed.", attributeMap);395 fireSessionRejectedEvent(exception.getMessage(), reqId);396 }397 } else {398 fireSessionRejectedEvent(exception.getMessage(), reqId);399 }400 }401 }402 }403 private void fireSessionRejectedEvent(String message, RequestId reqId) {...
Source:RemoteNode.java
...28import com.google.common.collect.ImmutableMap;29import com.google.common.collect.ImmutableSet;30import org.openqa.selenium.Capabilities;31import org.openqa.selenium.NoSuchSessionException;32import org.openqa.selenium.RetrySessionRequestException;33import org.openqa.selenium.SessionNotCreatedException;34import org.openqa.selenium.WebDriverException;35import org.openqa.selenium.grid.data.CreateSessionRequest;36import org.openqa.selenium.grid.data.CreateSessionResponse;37import org.openqa.selenium.grid.data.NodeId;38import org.openqa.selenium.grid.data.NodeStatus;39import org.openqa.selenium.grid.data.Session;40import org.openqa.selenium.grid.node.HealthCheck;41import org.openqa.selenium.grid.node.Node;42import org.openqa.selenium.grid.security.AddSecretFilter;43import org.openqa.selenium.grid.security.Secret;44import org.openqa.selenium.grid.web.Values;45import org.openqa.selenium.internal.Either;46import org.openqa.selenium.internal.Require;47import org.openqa.selenium.json.Json;48import org.openqa.selenium.json.JsonInput;49import org.openqa.selenium.remote.SessionId;50import org.openqa.selenium.remote.http.Filter;51import org.openqa.selenium.remote.http.HttpClient;52import org.openqa.selenium.remote.http.HttpHandler;53import org.openqa.selenium.remote.http.HttpRequest;54import org.openqa.selenium.remote.http.HttpResponse;55import org.openqa.selenium.remote.tracing.HttpTracing;56import org.openqa.selenium.remote.tracing.Tracer;57import java.io.IOException;58import java.io.Reader;59import java.io.UncheckedIOException;60import java.net.URI;61import java.util.Collection;62import java.util.Map;63import java.util.Objects;64import java.util.Optional;65import java.util.Set;66public class RemoteNode extends Node {67 public static final Json JSON = new Json();68 private final HttpHandler client;69 private final URI externalUri;70 private final Set<Capabilities> capabilities;71 private final HealthCheck healthCheck;72 private final Filter addSecret;73 public RemoteNode(74 Tracer tracer,75 HttpClient.Factory clientFactory,76 NodeId id,77 URI externalUri,78 Secret registrationSecret,79 Collection<Capabilities> capabilities) {80 super(tracer, id, externalUri, registrationSecret);81 this.externalUri = Require.nonNull("External URI", externalUri);82 this.capabilities = ImmutableSet.copyOf(capabilities);83 this.client = Require.nonNull("HTTP client factory", clientFactory).createClient(fromUri(externalUri));84 this.healthCheck = new RemoteCheck();85 Require.nonNull("Registration secret", registrationSecret);86 this.addSecret = new AddSecretFilter(registrationSecret);87 }88 @Override89 public boolean isReady() {90 try {91 return client.execute(new HttpRequest(GET, "/readyz")).isSuccessful();92 } catch (Exception e) {93 return false;94 }95 }96 @Override97 public boolean isSupporting(Capabilities capabilities) {98 return this.capabilities.stream()99 .anyMatch(caps -> caps.getCapabilityNames().stream()100 .allMatch(name -> Objects.equals(101 caps.getCapability(name),102 capabilities.getCapability(name))));103 }104 @Override105 public Either<WebDriverException, CreateSessionResponse> newSession(106 CreateSessionRequest sessionRequest) {107 Require.nonNull("Capabilities for session", sessionRequest);108 HttpRequest req = new HttpRequest(POST, "/se/grid/node/session");109 HttpTracing.inject(tracer, tracer.getCurrentContext(), req);110 req.setContent(asJson(sessionRequest));111 HttpResponse httpResponse = client.with(addSecret).execute(req);112 Optional<Map<String, Object>> maybeResponse =113 Optional.ofNullable(Values.get(httpResponse, Map.class));114 if (maybeResponse.isPresent()) {115 Map<String, Object> response = maybeResponse.get();116 if (response.containsKey("sessionResponse")) {117 String rawResponse = JSON.toJson(response.get("sessionResponse"));118 CreateSessionResponse sessionResponse = JSON.toType(rawResponse, CreateSessionResponse.class);119 return Either.right(sessionResponse);120 } else {121 String rawException = JSON.toJson(response.get("exception"));122 Map<String, Object> exception = JSON.toType(rawException, Map.class);123 String errorType = (String) exception.get("error");124 String errorMessage = (String) exception.get("message");125 if (RetrySessionRequestException.class.getName().contentEquals(errorType)) {126 return Either.left(new RetrySessionRequestException(errorMessage));127 } else {128 return Either.left(new SessionNotCreatedException(errorMessage));129 }130 }131 }132 return Either.left(new SessionNotCreatedException("Error while mapping response from Node"));133 }134 @Override135 public boolean isSessionOwner(SessionId id) {136 Require.nonNull("Session ID", id);137 HttpRequest req = new HttpRequest(GET, "/se/grid/node/owner/" + id);138 HttpTracing.inject(tracer, tracer.getCurrentContext(), req);139 HttpResponse res = client.with(addSecret).execute(req);140 return Boolean.TRUE.equals(Values.get(res, Boolean.class));...
Source:LocalNodeTest.java
...21import org.junit.Test;22import org.openqa.selenium.Capabilities;23import org.openqa.selenium.ImmutableCapabilities;24import org.openqa.selenium.NoSuchSessionException;25import org.openqa.selenium.RetrySessionRequestException;26import org.openqa.selenium.WebDriverException;27import org.openqa.selenium.events.EventBus;28import org.openqa.selenium.events.local.GuavaEventBus;29import org.openqa.selenium.grid.data.CreateSessionRequest;30import org.openqa.selenium.grid.data.CreateSessionResponse;31import org.openqa.selenium.grid.data.NodeStatus;32import org.openqa.selenium.grid.data.Session;33import org.openqa.selenium.grid.node.Node;34import org.openqa.selenium.grid.security.Secret;35import org.openqa.selenium.grid.testing.EitherAssert;36import org.openqa.selenium.grid.testing.TestSessionFactory;37import org.openqa.selenium.internal.Either;38import org.openqa.selenium.remote.HttpSessionId;39import org.openqa.selenium.remote.SessionId;40import org.openqa.selenium.remote.http.HttpHandler;41import org.openqa.selenium.remote.http.HttpRequest;42import org.openqa.selenium.remote.http.HttpResponse;43import org.openqa.selenium.remote.tracing.DefaultTestTracer;44import org.openqa.selenium.remote.tracing.Tracer;45import java.net.URI;46import java.net.URISyntaxException;47import java.time.Instant;48import java.util.ArrayList;49import java.util.List;50import java.util.Optional;51import java.util.concurrent.Callable;52import java.util.concurrent.Executors;53import java.util.concurrent.Future;54import static java.util.concurrent.TimeUnit.SECONDS;55import static org.assertj.core.api.Assertions.assertThat;56import static org.assertj.core.api.Assertions.assertThatExceptionOfType;57import static org.openqa.selenium.remote.Dialect.W3C;58import static org.openqa.selenium.remote.http.HttpMethod.GET;59public class LocalNodeTest {60 private LocalNode node;61 private Session session;62 private Secret registrationSecret;63 private static <A, B> EitherAssert<A, B> assertThatEither(Either<A, B> either) {64 return new EitherAssert<>(either);65 }66 @Before67 public void setUp() throws URISyntaxException {68 Tracer tracer = DefaultTestTracer.createTracer();69 EventBus bus = new GuavaEventBus();70 URI uri = new URI("http://localhost:1234");71 Capabilities stereotype = new ImmutableCapabilities("cheese", "brie");72 registrationSecret = new Secret("red leicester");73 node = LocalNode.builder(tracer, bus, uri, uri, registrationSecret)74 .add(stereotype, new TestSessionFactory((id, caps) -> new Session(id, uri, stereotype, caps, Instant.now())))75 .build();76 Either<WebDriverException, CreateSessionResponse> response = node.newSession(77 new CreateSessionRequest(78 ImmutableSet.of(W3C),79 stereotype,80 ImmutableMap.of()));81 if (response.isRight()) {82 CreateSessionResponse sessionResponse = response.right();83 session = sessionResponse.getSession();84 } else {85 throw new AssertionError("Unable to create session" + response.left().getMessage());86 }87 }88 @Test89 public void shouldThrowIfSessionIsNotPresent() {90 assertThatExceptionOfType(NoSuchSessionException.class)91 .isThrownBy(() -> node.getSession(new SessionId("12345")));92 }93 @Test94 public void canRetrieveActiveSessionById() {95 assertThat(node.getSession(session.getId())).isEqualTo(session);96 }97 @Test98 public void isOwnerOfAnActiveSession() {99 assertThat(node.isSessionOwner(session.getId())).isTrue();100 }101 @Test102 public void canStopASession() {103 node.stop(session.getId());104 assertThatExceptionOfType(NoSuchSessionException.class)105 .isThrownBy(() -> node.getSession(session.getId()));106 }107 @Test108 public void isNotOwnerOfAStoppedSession() {109 node.stop(session.getId());110 assertThat(node.isSessionOwner(session.getId())).isFalse();111 }112 @Test113 public void cannotAcceptNewSessionsWhileDraining() {114 node.drain();115 assertThat(node.isDraining()).isTrue();116 node.stop(session.getId()); //stop the default session117 Capabilities stereotype = new ImmutableCapabilities("cheese", "brie");118 Either<WebDriverException, CreateSessionResponse> sessionResponse = node.newSession(119 new CreateSessionRequest(120 ImmutableSet.of(W3C),121 stereotype,122 ImmutableMap.of()));123 assertThatEither(sessionResponse).isLeft();124 assertThat(sessionResponse.left()).isInstanceOf(RetrySessionRequestException.class);125 }126 @Test127 public void cannotCreateNewSessionsOnMaxSessionCount() {128 Capabilities stereotype = new ImmutableCapabilities("cheese", "brie");129 Either<WebDriverException, CreateSessionResponse> sessionResponse = node.newSession(130 new CreateSessionRequest(131 ImmutableSet.of(W3C),132 stereotype,133 ImmutableMap.of()));134 assertThatEither(sessionResponse).isLeft();135 assertThat(sessionResponse.left()).isInstanceOf(RetrySessionRequestException.class);136 }137 @Test138 public void canReturnStatusInfo() {139 NodeStatus status = node.getStatus();140 assertThat(status.getSlots().stream()141 .filter(slot -> slot.getSession().isPresent())142 .map(slot -> slot.getSession().get())143 .filter(s -> s.getId().equals(session.getId()))).isNotEmpty();144 node.stop(session.getId());145 status = node.getStatus();146 assertThat(status.getSlots().stream()147 .filter(slot -> slot.getSession().isPresent())148 .map(slot -> slot.getSession().get())149 .filter(s -> s.getId().equals(session.getId()))).isEmpty();...
Source:SessionSlot.java
...17package org.openqa.selenium.grid.node.local;18import org.openqa.selenium.Capabilities;19import org.openqa.selenium.ImmutableCapabilities;20import org.openqa.selenium.NoSuchSessionException;21import org.openqa.selenium.RetrySessionRequestException;22import org.openqa.selenium.SessionNotCreatedException;23import org.openqa.selenium.WebDriverException;24import org.openqa.selenium.WebDriverInfo;25import org.openqa.selenium.events.EventBus;26import org.openqa.selenium.grid.data.CreateSessionRequest;27import org.openqa.selenium.grid.data.SessionClosedEvent;28import org.openqa.selenium.grid.node.ActiveSession;29import org.openqa.selenium.grid.node.SessionFactory;30import org.openqa.selenium.internal.Either;31import org.openqa.selenium.internal.Require;32import org.openqa.selenium.remote.SessionId;33import org.openqa.selenium.remote.http.HttpHandler;34import org.openqa.selenium.remote.http.HttpRequest;35import org.openqa.selenium.remote.http.HttpResponse;36import java.io.UncheckedIOException;37import java.util.ServiceLoader;38import java.util.UUID;39import java.util.concurrent.atomic.AtomicBoolean;40import java.util.function.Function;41import java.util.function.Predicate;42import java.util.logging.Level;43import java.util.logging.Logger;44import java.util.stream.StreamSupport;45public class SessionSlot implements46 HttpHandler,47 Function<CreateSessionRequest, Either<WebDriverException, ActiveSession>>,48 Predicate<Capabilities> {49 private static final Logger LOG = Logger.getLogger(SessionSlot.class.getName());50 private final EventBus bus;51 private final UUID id;52 private final Capabilities stereotype;53 private final SessionFactory factory;54 private final AtomicBoolean reserved = new AtomicBoolean(false);55 private final boolean supportingCdp;56 private ActiveSession currentSession;57 public SessionSlot(EventBus bus, Capabilities stereotype, SessionFactory factory) {58 this.bus = Require.nonNull("Event bus", bus);59 this.id = UUID.randomUUID();60 this.stereotype = ImmutableCapabilities.copyOf(Require.nonNull("Stereotype", stereotype));61 this.factory = Require.nonNull("Session factory", factory);62 this.supportingCdp = isSlotSupportingCdp(this.stereotype);63 }64 public UUID getId() {65 return id;66 }67 public Capabilities getStereotype() {68 return stereotype;69 }70 public void reserve() {71 if (reserved.getAndSet(true)) {72 throw new IllegalStateException("Attempt to reserve a slot that is already reserved");73 }74 }75 public void release() {76 reserved.set(false);77 }78 public boolean isAvailable() {79 return !reserved.get();80 }81 public ActiveSession getSession() {82 if (isAvailable()) {83 throw new NoSuchSessionException("Session is not running");84 }85 return currentSession;86 }87 public void stop() {88 if (isAvailable()) {89 return;90 }91 SessionId id = currentSession.getId();92 try {93 currentSession.stop();94 } catch (Exception e) {95 LOG.log(Level.WARNING, "Unable to cleanly close session", e);96 }97 currentSession = null;98 release();99 bus.fire(new SessionClosedEvent(id));100 }101 @Override102 public HttpResponse execute(HttpRequest req) throws UncheckedIOException {103 if (currentSession == null) {104 throw new NoSuchSessionException("No session currently running: " + req.getUri());105 }106 return currentSession.execute(req);107 }108 @Override109 public boolean test(Capabilities capabilities) {110 return factory.test(capabilities);111 }112 @Override113 public Either<WebDriverException, ActiveSession> apply(CreateSessionRequest sessionRequest) {114 if (currentSession != null) {115 return Either.left(new RetrySessionRequestException("Slot is busy. Try another slot."));116 }117 if (!test(sessionRequest.getDesiredCapabilities())) {118 return Either.left(new SessionNotCreatedException("New session request capabilities do not "119 + "match the stereotype."));120 }121 try {122 Either<WebDriverException, ActiveSession> possibleSession = factory.apply(sessionRequest);123 if (possibleSession.isRight()) {124 ActiveSession session = possibleSession.right();125 currentSession = session;126 return Either.right(session);127 } else {128 return Either.left(possibleSession.left());129 }...
Source:RetrySessionRequestException.java
...14// KIND, either express or implied. See the License for the15// specific language governing permissions and limitations16// under the License.17package org.openqa.selenium;18public class RetrySessionRequestException extends SessionNotCreatedException {19 public RetrySessionRequestException(String msg) {20 super(msg);21 }22 public RetrySessionRequestException(String msg, Throwable cause) {23 super(msg, cause);24 }25}...
RetrySessionRequestException
Using AI Code Generation
1import org.openqa.selenium.RetrySessionRequestException;2import org.openqa.selenium.WebDriver;3import org.openqa.selenium.chrome.ChromeDriver;4import org.openqa.selenium.chrome.ChromeOptions;5import org.openqa.selenium.remote.CapabilityType;6import org.openqa.selenium.remote.DesiredCapabilities;7import org.openqa.selenium.remote.RemoteWebDriver;8import org.openqa.selenium.remote.UnreachableBrowserException;9import org.openqa.selenium.remote.service.DriverService;10public class BaseClass {11 public static WebDriver driver;12 public static String driverPath = "D:\\chromedriver_win32\\chromedriver.exe";13 public static void main(String[] args) {14 System.setProperty("webdriver.chrome.driver", driverPath);15 ChromeOptions options = new ChromeOptions();16 options.addArguments("start-maximized");17 options.addArguments("disable-infobars");18 options.addArguments("--disable-extensions");19 options.addArguments("--disable-notifications");20 options.addArguments("--disable-gpu");21 options.addArguments("--disable-dev-shm-usage");22 options.addArguments("--no-sandbox");23 options.addArguments("--ignore-certificate-errors");24 options.addArguments("--allow-running-insecure-content");25 options.addArguments("--headless");26 options.addArguments("--disable-browser-side-navigation");27 options.addArguments("--disable-features=VizDisplayCompositor");28 options.addArguments("--disable-features=NetworkService");29 options.addArguments("--disable-features=VizDisplayCompositor");30 options.addArguments("--disable-features=NetworkService");31 options.addArguments("--disable-features=IsolateOrigins,site-per-process");32 options.addArguments("--disable-features=VizDisplayCompositor");33 options.addArguments("--disable-features=NetworkService");34 options.addArguments("--disable-features=IsolateOrigins,site-per-process");35 options.addArguments("--disable-features=VizDisplayCompositor");36 options.addArguments("--disable-features=NetworkService");37 options.addArguments("--disable-features=IsolateOrigins,site-per-process");38 options.addArguments("--disable-features=VizDisplayCompositor");39 options.addArguments("--disable-features=NetworkService");40 options.addArguments("--disable-features=IsolateOrigins,site-per-process");41 options.addArguments("--disable-features=VizDisplayCompositor");42 options.addArguments("--disable-features=NetworkService");43 options.addArguments("--disable-features
RetrySessionRequestException
Using AI Code Generation
1package com.selenium4beginners.java.webdriver;2import org.openqa.selenium.By;3import org.openqa.selenium.WebDriver;4import org.openqa.selenium.WebElement;5import org.openqa.selenium.chrome.ChromeDriver;6import org.openqa.selenium.support.ui.ExpectedConditions;7import org.openqa.selenium.support.ui.WebDriverWait;8public class RetrySessionRequestException {9 public static void main(String[] args) {10 System.setProperty("webdriver.chrome.driver", "C:\\Selenium\\chromedriver.exe");11 WebDriver driver = new ChromeDriver();12 WebDriverWait wait = new WebDriverWait(driver, 10);13 button.click();14 System.out.println(alert.getText());15 driver.close();16 }17}
RetrySessionRequestException
Using AI Code Generation
1package com.test;2import java.util.concurrent.TimeUnit;3import org.openqa.selenium.By;4import org.openqa.selenium.WebDriver;5import org.openqa.selenium.chrome.ChromeDriver;6import org.openqa.selenium.chrome.ChromeOptions;7import org.openqa.selenium.support.ui.ExpectedConditions;8import org.openqa.selenium.support.ui.WebDriverWait;9import org.testng.annotations.AfterTest;10import org.testng.annotations.BeforeTest;11import org.testng.annotations.Test;12public class TestClass {13 public static WebDriver driver;14 public void setup() {15 System.setProperty("webdriver.chrome.driver", "C:\\chromedriver.exe");16 ChromeOptions options = new ChromeOptions();17 options.addArguments("--disable-notifications");18 driver = new ChromeDriver(options);19 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);20 driver.manage().window().maximize();21 }22 public void test() throws InterruptedException {23 WebDriverWait wait = new WebDriverWait(driver, 10);24 wait.until(ExpectedConditions.elementToBeClickable(By.id("email"))).sendKeys("
RetrySessionRequestException
Using AI Code Generation
1import org.openqa.selenium.*;2import org.openqa.selenium.By;3import org.openqa.selenium.WebDriver;4import org.openqa.selenium.WebElement;5import org.openqa.selenium.chrome.ChromeDriver;6import org.openqa.selenium.chrome.ChromeOptions;7import org.openqa.selenium.support.ui.ExpectedConditions;8import org.openqa.selenium.support.ui.WebDriverWait;9import org.openqa.selenium.support.ui.ExpectedCondition;10import org.openqa.selenium.support.ui.Select;11import org.openqa.selenium.interactions.Actions;12import org.openqa.selenium.JavascriptExecutor;13import org.openqa.selenium.Keys;14import org.openqa.selenium.TimeoutException;15import org.openqa.selenium.NoSuchElementException;16import org.openqa.selenium.StaleElementReferenceException;17import org.openqa.selenium.WebDriverException;18import org.openqa.selenium.support.ui.FluentWait;19import org.openqa.selenium.support.ui.Wait;20import org.openqa.selenium.support.ui.Select;21import org.openqa.selenium.support.ui.ExpectedConditions;22import org.openqa.selenium.support.ui.FluentWait;23import org.openqa.selenium.support.ui.Wait;24import org.openqa.selenium.support.ui.Select;25import org.openqa.selenium.support.ui.ExpectedConditions;26import org.openqa.selenium.support.ui.FluentWait;27import org.openqa.selenium.support.ui.Wait;28import org.openqa.selenium.support.ui.Select;29import org.openqa.selenium.support.ui.ExpectedConditions;30import org.openqa.selenium.support.ui.FluentWait;31import org.openqa.selenium.support.ui.Wait;32import org.openqa.selenium.support.ui.Select;33import org.openqa.selenium.support.ui.ExpectedConditions;34import org.openqa.selenium.support.ui.FluentWait;35import org.openqa.selenium.support.ui.Wait;36import org.openqa.selenium.support.ui.Select;37import org.openqa.selenium.support.ui.ExpectedConditions;38import org.openqa.selenium.support.ui.FluentWait;39import org.openqa.selenium.support.ui.Wait;40import org.openqa.selenium.support.ui.Select;41import org.openqa.selenium.support.ui.ExpectedConditions;42import org.openqa.selenium.support.ui.FluentWait;43import org.openqa.selenium.support.ui.Wait;44import org.openqa.selenium.support.ui.Select;45import org.openqa.selenium.support.ui.ExpectedConditions;46import org.openqa.selenium.support.ui.FluentWait;47import org.openqa.selenium.support.ui.Wait;48import org.openqa.selenium.support.ui.Select;49import org.openqa.selenium.support.ui.ExpectedConditions;50import org.openqa.selenium.support.ui.FluentWait;51import org.openqa.selenium.support.ui.Wait;52import org.openqa.selenium.support.ui.Select;53import org.openqa.selenium.support.ui.ExpectedConditions;54import org.openqa.selenium.support.ui.FluentWait;55import org.openqa.selenium.support.ui.Wait;56import org.openqa.selenium.support.ui.Select;57import org.openqa.selenium.support.ui.Expected
RetrySessionRequestException
Using AI Code Generation
1import org.openqa.selenium.remote.SessionNotFoundException;2import org.openqa.selenium.remote.UnreachableBrowserException;3import org.openqa.selenium.remote.UnreachableBrowserException;4import org.openqa.selenium.remote.UnreachableBrowserException;5import org.openqa.selenium.remote.UnreachableBrowserException;6import org.openqa.selenium.remote.UnreachableBrowserException;7import org.openqa.selenium.remote.UnreachableBrowserException;8import org.openqa.selenium.remote.UnreachableBrowserException;9import org.openqa.selenium.remote.UnreachableBrowserException;10import org.openqa.selenium.remote.UnreachableBrowserException;11import org.openqa.selenium.remote.UnreachableBrowserException;12import org.openqa.selenium.remote.UnreachableBrowserException;13import org.openqa.selenium.remote.UnreachableBrowserException;14import org.openqa.selenium.remote.UnreachableBrowserException;15import org.openqa.selenium.remote.UnreachableBrowserException;16import org.openqa.selenium.remote.UnreachableBrowserException;17import org.openqa.selenium.remote.UnreachableBrowserException;18import org.openqa.selenium.remote.UnreachableBrowserException;19import org.openqa.selenium.remote.UnreachableBrowserException;20import org.openqa.selenium.remote.UnreachableBrowserException;21import org.openqa.selenium.remote.UnreachableBrowserException;22import org.openqa.selenium.remote.UnreachableBrowserException;23import org.openqa.selenium.remote.UnreachableBrowserException;24import org.openqa.selenium.remote.UnreachableBrowserException;25import org.openqa.selenium.remote.UnreachableBrowserException;26import org.openqa.selenium.remote.UnreachableBrowserException;27import org.openqa.selenium.remote.UnreachableBrowserException;28import org.openqa.selenium.remote.UnreachableBrowserException;29import org.openqa.selenium.remote.UnreachableBrowserException;30import org.openqa.selenium.remote.UnreachableBrowserException;31import org.openqa.selenium.remote.UnreachableBrowserException;32import org.openqa.selenium.remote.UnreachableBrowserException;33import org.openqa.selenium.remote.UnreachableBrowserException;34import org.openqa.selenium.remote.UnreachableBrowserException;35import org.openqa.selenium.remote.UnreachableBrowserException;36import org.openqa.selenium.remote.UnreachableBrowserException;37import org.openqa.selenium.remote.UnreachableBrowserException;38import org.openqa.selenium.remote.UnreachableBrowserException;39import org.openqa.selenium.remote.UnreachableBrowserException;40import org.openqa.selenium.remote.UnreachableBrowserException;41import org.openqa.selenium.remote.UnreachableBrowserException;42import org.openqa.selenium.remote.UnreachableBrowserException;43import org.openqa.selenium.remote.UnreachableBrowserException;44import org.openqa.selenium.remote.UnreachableBrowserException;45import org.openqa.selenium.remote.UnreachableBrowserException;46import org.openqa.selenium.remote.UnreachableBrowserException;47import org
RetrySessionRequestException
Using AI Code Generation
1import org.openqa.selenium.remote.RemoteWebDriver;2import org.openqa.selenium.remote.SessionNotFoundException;3import org.openqa.selenium.remote.http.HttpClient;4import org.openqa.selenium.remote.http.HttpRequest;5import org.openqa.selenium.remote.http.HttpResponse;6import org.openqa.selenium.remote.service.DriverService;7import java.io.IOException;8import java.net.URL;9import java.util.concurrent.TimeUnit;10public class RetrySessionRequestException {11 public static void main(String[] args) {12 RemoteWebDriver driver = new RemoteWebDriver(13 DesiredCapabilities.firefox()) {14 protected void startClient() {15 HttpClient.Factory factory = HttpClient.Factory.createDefault();16 HttpRequest request = new HttpRequest(HttpMethod.POST, "/session");17 request.setContent(ContentType.JSON, getCapabilities().asMap());18 DriverService service = getDriverService();19 int retries = 5;20 long interval = TimeUnit.SECONDS.toMillis(1);21 while (retries-- > 0) {22 HttpResponse response = null;23 try {24 response = factory.createClient(service.getUrl()).execute(request, true);25 if (response != null) {
LambdaTest’s Selenium 4 tutorial is covering every aspects of Selenium 4 testing with examples and best practices. Here you will learn basics, such as how to upgrade from Selenium 3 to Selenium 4, to some advanced concepts, such as Relative locators and Selenium Grid 4 for Distributed testing. Also will learn new features of Selenium 4, such as capturing screenshots of specific elements, opening a new tab or window on the browser, and new protocol adoptions.
Upgrading From Selenium 3 To Selenium 4?: In this chapter, learn in detail how to update Selenium 3 to Selenium 4 for Java binding. Also, learn how to upgrade while using different build tools such as Maven or Gradle and get comprehensive guidance for upgrading Selenium.
What’s New In Selenium 4 & What’s Being Deprecated? : Get all information about new implementations in Selenium 4, such as W3S protocol adaption, Optimized Selenium Grid, and Enhanced Selenium IDE. Also, learn what is deprecated for Selenium 4, such as DesiredCapabilites and FindsBy methods, etc.
Selenium 4 With Python: Selenium supports all major languages, such as Python, C#, Ruby, and JavaScript. In this chapter, learn how to install Selenium 4 for Python and the features of Python in Selenium 4, such as Relative locators, Browser manipulation, and Chrom DevTool protocol.
Selenium 4 Is Now W3C Compliant: JSON Wireframe protocol is retiring from Selenium 4, and they are adopting W3C protocol to learn in detail about the advantages and impact of these changes.
How To Use Selenium 4 Relative Locator? : Selenium 4 came with new features such as Relative Locators that allow constructing locators with reference and easily located constructors nearby. Get to know its different use cases with examples.
Selenium Grid 4 Tutorial For Distributed Testing: Selenium Grid 4 allows you to perform tests over different browsers, OS, and device combinations. It also enables parallel execution browser testing, reads up on various features of Selenium Grid 4 and how to download it, and runs a test on Selenium Grid 4 with best practices.
Selenium Video Tutorials: Binge on video tutorials on Selenium by industry experts to get step-by-step direction from automating basic to complex test scenarios with Selenium.
LambdaTest also provides certification for Selenium testing to accelerate your career in Selenium automation testing.
Get 100 minutes of automation test minutes FREE!!