Best Selenium code snippet using org.openqa.selenium.grid.data.SessionRequest.toString
Source:LocalDistributor.java  
...315    Map<String, EventAttributeValue> attributeMap = new HashMap<>();316    try {317      attributeMap.put(AttributeKey.LOGGER_CLASS.getKey(),318        EventAttribute.setValue(getClass().getName()));319      attributeMap.put("request.payload", EventAttribute.setValue(request.getDesiredCapabilities().toString()));320      String sessionReceivedMessage = "Session request received by the distributor";321      span.addEvent(sessionReceivedMessage, attributeMap);322      LOG.info(String.format("%s: \n %s", sessionReceivedMessage, request.getDesiredCapabilities()));323      // If there are no capabilities at all, something is horribly wrong324      if (request.getDesiredCapabilities().isEmpty()) {325        SessionNotCreatedException exception =326          new SessionNotCreatedException("No capabilities found in session request payload");327        EXCEPTION.accept(attributeMap, exception);328        attributeMap.put(AttributeKey.EXCEPTION_MESSAGE.getKey(),329          EventAttribute.setValue("Unable to create session. No capabilities found: " +330            exception.getMessage()));331        span.addEvent(AttributeKey.EXCEPTION_EVENT.getKey(), attributeMap);332        return Either.left(exception);333      }334      boolean retry = false;335      SessionNotCreatedException lastFailure = new SessionNotCreatedException("Unable to create new session");336      for (Capabilities caps : request.getDesiredCapabilities()) {337        if (!isSupported(caps)) {338          continue;339        }340        // Try and find a slot that we can use for this session. While we341        // are finding the slot, no other session can possibly be started.342        // Therefore, spend as little time as possible holding the write343        // lock, and release it as quickly as possible. Under no344        // circumstances should we try to actually start the session itself345        // in this next block of code.346        SlotId selectedSlot = reserveSlot(request.getRequestId(), caps);347        if (selectedSlot == null) {348          LOG.info(String.format("Unable to find slot for request %s. May retry: %s ", request.getRequestId(), caps));349          retry = true;350          continue;351        }352        CreateSessionRequest singleRequest = new CreateSessionRequest(353          request.getDownstreamDialects(),354          caps,355          request.getMetadata());356        try {357          CreateSessionResponse response = startSession(selectedSlot, singleRequest);358          sessions.add(response.getSession());359          model.setSession(selectedSlot, response.getSession());360          SessionId sessionId = response.getSession().getId();361          Capabilities sessionCaps = response.getSession().getCapabilities();362          String sessionUri = response.getSession().getUri().toString();363          SESSION_ID.accept(span, sessionId);364          CAPABILITIES.accept(span, sessionCaps);365          SESSION_ID_EVENT.accept(attributeMap, sessionId);366          CAPABILITIES_EVENT.accept(attributeMap, sessionCaps);367          span.setAttribute(SESSION_URI.getKey(), sessionUri);368          attributeMap.put(SESSION_URI.getKey(), EventAttribute.setValue(sessionUri));369          String sessionCreatedMessage = "Session created by the distributor";370          span.addEvent(sessionCreatedMessage, attributeMap);371          LOG.info(String.format("%s. Id: %s, Caps: %s", sessionCreatedMessage, sessionId, sessionCaps));372          return Either.right(response);373        } catch (SessionNotCreatedException e) {374          model.setSession(selectedSlot, null);375          lastFailure = e;376        }377      }378      // If we've made it this far, we've not been able to start a session379      if (retry) {380        lastFailure = new RetrySessionRequestException(381          "Will re-attempt to find a node which can run this session",382          lastFailure);383        attributeMap.put(384          AttributeKey.EXCEPTION_MESSAGE.getKey(),385          EventAttribute.setValue("Will retry session " + request.getRequestId()));386      } else {387        EXCEPTION.accept(attributeMap, lastFailure);388        attributeMap.put(AttributeKey.EXCEPTION_MESSAGE.getKey(),389          EventAttribute.setValue("Unable to create session: " + lastFailure.getMessage()));390        span.addEvent(AttributeKey.EXCEPTION_EVENT.getKey(), attributeMap);391      }392      return Either.left(lastFailure);393    } catch (SessionNotCreatedException e) {394      span.setAttribute(AttributeKey.ERROR.getKey(), true);395      span.setStatus(Status.ABORTED);396      EXCEPTION.accept(attributeMap, e);397      attributeMap.put(AttributeKey.EXCEPTION_MESSAGE.getKey(),398        EventAttribute.setValue("Unable to create session: " + e.getMessage()));399      span.addEvent(AttributeKey.EXCEPTION_EVENT.getKey(), attributeMap);400      return Either.left(e);401    } catch (UncheckedIOException e) {402      span.setAttribute(AttributeKey.ERROR.getKey(), true);403      span.setStatus(Status.UNKNOWN);404      EXCEPTION.accept(attributeMap, e);405      attributeMap.put(AttributeKey.EXCEPTION_MESSAGE.getKey(),406        EventAttribute.setValue("Unknown error in LocalDistributor while creating session: " + e.getMessage()));407      span.addEvent(AttributeKey.EXCEPTION_EVENT.getKey(), attributeMap);408      return Either.left(new SessionNotCreatedException(e.getMessage(), e));409    } finally {410      span.close();411    }412  }413  private CreateSessionResponse startSession(SlotId selectedSlot, CreateSessionRequest singleRequest) {414    Node node = nodes.get(selectedSlot.getOwningNodeId());415    if (node == null) {416      throw new SessionNotCreatedException("Unable to find owning node for slot");417    }418    Either<WebDriverException, CreateSessionResponse> result;419    try {420      result = node.newSession(singleRequest);421    } catch (SessionNotCreatedException e) {422      result = Either.left(e);423    } catch (RuntimeException e) {424      result = Either.left(new SessionNotCreatedException(e.getMessage(), e));425    }426    if (result.isLeft()) {427      WebDriverException exception = result.left();428      if (exception instanceof SessionNotCreatedException) {429        throw exception;430      }431      throw new SessionNotCreatedException(exception.getMessage(), exception);432    }433    return result.right();434  }435  private SlotId reserveSlot(RequestId requestId, Capabilities caps) {436    Lock writeLock = lock.writeLock();437    writeLock.lock();438    try {439      Set<SlotId> slotIds = slotSelector.selectSlot(caps, getAvailableNodes());440      if (slotIds.isEmpty()) {441        LOG.log(442          getDebugLogLevel(),443          String.format("No slots found for request %s and capabilities %s", requestId, caps));444        return null;445      }446      for (SlotId slotId : slotIds) {447        if (reserve(slotId)) {448          return slotId;449        }450      }451      return null;452    } finally {453      writeLock.unlock();454    }455  }456  private boolean isSupported(Capabilities caps) {457    return getAvailableNodes().stream().anyMatch(node -> node.hasCapability(caps));458  }459  private boolean reserve(SlotId id) {460    Require.nonNull("Slot ID", id);461    Lock writeLock = this.lock.writeLock();462    writeLock.lock();463    try {464      Node node = nodes.get(id.getOwningNodeId());465      if (node == null) {466        LOG.log(getDebugLogLevel(), String.format("Unable to find node with id %s", id));467        return false;468      }469      return model.reserve(id);470    } finally {471      writeLock.unlock();472    }473  }474  public void callExecutorShutdown() {475    LOG.info("Shutting down Distributor executor service");476    regularly.shutdown();477  }478  public class NewSessionRunnable implements Runnable {479    @Override480    public void run() {481      List<SessionRequestCapability> queueContents = sessionQueue.getQueueContents();482      if (rejectUnsupportedCaps) {483        checkMatchingSlot(queueContents);484      }485      int initialSize = queueContents.size();486      boolean retry = initialSize != 0;487      while (retry) {488        // We deliberately run this outside of a lock: if we're unsuccessful489        // starting the session, we just put the request back on the queue.490        // This does mean, however, that under high contention, we might end491        // up starving a session request.492        Set<Capabilities> stereotypes =493            getAvailableNodes().stream()494                .filter(NodeStatus::hasCapacity)495                .map(496                    node ->497                        node.getSlots().stream()498                            .map(Slot::getStereotype)499                            .collect(Collectors.toSet()))500                .flatMap(Collection::stream)501                .collect(Collectors.toSet());502        Optional<SessionRequest> maybeRequest = sessionQueue.getNextAvailable(stereotypes);503        maybeRequest.ifPresent(this::handleNewSessionRequest);504        int currentSize = sessionQueue.getQueueContents().size();505        retry = currentSize != 0 && currentSize != initialSize;506        initialSize = currentSize;507      }508    }509    private void checkMatchingSlot(List<SessionRequestCapability> sessionRequests) {510      for(SessionRequestCapability request : sessionRequests) {511        long unmatchableCount = request.getDesiredCapabilities().stream()512          .filter(caps -> !isSupported(caps))513          .count();514        if (unmatchableCount == request.getDesiredCapabilities().size()) {515          SessionNotCreatedException exception = new SessionNotCreatedException(516            "No nodes support the capabilities in the request");517          sessionQueue.complete(request.getRequestId(), Either.left(exception));518        }519      }520    }521    private void handleNewSessionRequest(SessionRequest sessionRequest) {522      RequestId reqId = sessionRequest.getRequestId();523      try (Span span = TraceSessionRequest.extract(tracer, sessionRequest).createSpan("distributor.poll_queue")) {524        Map<String, EventAttributeValue> attributeMap = new HashMap<>();525        attributeMap.put(526          AttributeKey.LOGGER_CLASS.getKey(),527          EventAttribute.setValue(getClass().getName()));528        span.setAttribute(AttributeKey.REQUEST_ID.getKey(), reqId.toString());529        attributeMap.put(530          AttributeKey.REQUEST_ID.getKey(),531          EventAttribute.setValue(reqId.toString()));532        attributeMap.put("request", EventAttribute.setValue(sessionRequest.toString()));533        Either<SessionNotCreatedException, CreateSessionResponse> response = newSession(sessionRequest);534        if (response.isLeft() && response.left() instanceof RetrySessionRequestException) {535          try(Span childSpan = span.createSpan("distributor.retry")) {536            LOG.info("Retrying");537            boolean retried = sessionQueue.retryAddToQueue(sessionRequest);538            attributeMap.put("request.retry_add", EventAttribute.setValue(retried));539            childSpan.addEvent("Retry adding to front of queue. No slot available.", attributeMap);540            if (retried) {541              return;542            }543            childSpan.addEvent("retrying_request", attributeMap);544          }545        }546        sessionQueue.complete(reqId, response);...Source:LocalNode.java  
...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);300        span.setAttribute(AttributeKey.SESSION_URI.getKey(), sessionUri);301        // The session we return has to look like it came from the node, since we might be dealing302        // with a webdriver implementation that only accepts connections from localhost303        Session externalSession = createExternalSession(304          session,305          externalUri,306          slotToUse.isSupportingCdp() || caps.getCapability("se:cdp") != null);307        return Either.right(new CreateSessionResponse(308          externalSession,309          getEncoder(session.getDownstreamDialect()).apply(externalSession)));310      } else {311        slotToUse.release();312        span.setAttribute("error", true);313        span.addEvent("Unable to create session with the driver", attributeMap);314        return Either.left(possibleSession.left());315      }316    }317  }318  @Override319  public boolean isSessionOwner(SessionId id) {320    Require.nonNull("Session ID", id);321    return currentSessions.getIfPresent(id) != null;322  }323  @Override324  public Session getSession(SessionId id) throws NoSuchSessionException {325    Require.nonNull("Session ID", id);326    SessionSlot slot = currentSessions.getIfPresent(id);327    if (slot == null) {328      throw new NoSuchSessionException("Cannot find session with id: " + id);329    }330    return createExternalSession(slot.getSession(), externalUri, slot.isSupportingCdp());331  }332  @Override333  public TemporaryFilesystem getTemporaryFilesystem(SessionId id) throws IOException {334    try {335      return tempFileSystems.get(id, () -> TemporaryFilesystem.getTmpFsBasedOn(336          TemporaryFilesystem.getDefaultTmpFS().createTempDir("session", id.toString())));337    } catch (ExecutionException e) {338      throw new IOException(e);339    }340  }341  @Override342  public HttpResponse executeWebDriverCommand(HttpRequest req) {343    // True enough to be good enough344    SessionId id = getSessionId(req.getUri()).map(SessionId::new)345      .orElseThrow(() -> new NoSuchSessionException("Cannot find session: " + req));346    SessionSlot slot = currentSessions.getIfPresent(id);347    if (slot == null) {348      throw new NoSuchSessionException("Cannot find session with id: " + id);349    }350    HttpResponse toReturn = slot.execute(req);...Source:GraphqlHandlerTest.java  
...132    assertThat(topLevel).isEqualTo(133      singletonMap(134        "data", singletonMap(135          "grid", singletonMap(136            "uri", publicUri.toString()))));137  }138  @Test139  public void shouldBeAbleToGetGridVersion() {140    GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);141    Map<String, Object> topLevel = executeQuery(handler, "{ grid { version } }");142    assertThat(topLevel).isEqualTo(143      singletonMap(144        "data", singletonMap(145          "grid", singletonMap(146            "version", version))));147  }148  private void continueOnceAddedToQueue(SessionRequest request) {149    // Add to the queue in the background150    CountDownLatch latch = new CountDownLatch(1);151    events.addListener(NewSessionRequestEvent.listener(id -> latch.countDown()));152    new Thread(() -> {153      queue.addToQueue(request);154    }).start();155    try {156      assertThat(latch.await(5, SECONDS)).isTrue();157    } catch (InterruptedException e) {158      Thread.currentThread().interrupt();159      throw new RuntimeException(e);160    }161  }162  @Test163  public void shouldBeAbleToGetSessionQueueSize() throws URISyntaxException {164    SessionRequest request = new SessionRequest(165      new RequestId(UUID.randomUUID()),166      Instant.now(),167      Set.of(W3C),168      Set.of(caps),169      Map.of(),170      Map.of());171    continueOnceAddedToQueue(request);172    GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);173    Map<String, Object> topLevel = executeQuery(handler, "{ grid { sessionQueueSize } }");174    assertThat(topLevel).isEqualTo(175      singletonMap(176        "data", singletonMap(177          "grid", singletonMap(178            "sessionQueueSize", 1L))));179  }180  @Test181  public void shouldBeAbleToGetSessionQueueRequests() throws URISyntaxException {182    SessionRequest request = new SessionRequest(183      new RequestId(UUID.randomUUID()),184      Instant.now(),185      Set.of(W3C),186      Set.of(caps),187      Map.of(),188      Map.of());189    continueOnceAddedToQueue(request);190    GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);191    Map<String, Object> topLevel = executeQuery(handler,192      "{ sessionsInfo { sessionQueueRequests } }");193    assertThat(topLevel).isEqualTo(194      singletonMap(195        "data", singletonMap(196          "sessionsInfo", singletonMap(197            "sessionQueueRequests", singletonList(JSON.toJson(caps))))));198  }199  @Test200  public void shouldBeReturnAnEmptyListIfQueueIsEmpty() {201    GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);202    Map<String, Object> topLevel = executeQuery(handler,203      "{ sessionsInfo { sessionQueueRequests } }");204    assertThat(topLevel).isEqualTo(205      singletonMap(206        "data", singletonMap(207          "sessionsInfo", singletonMap(208            "sessionQueueRequests", Collections.emptyList()))));209  }210  @Test211  public void shouldReturnAnEmptyListForNodesIfNoneAreRegistered() {212    GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);213    Map<String, Object> topLevel = executeQuery(handler, "{ nodesInfo { nodes { uri } } }");214    assertThat(topLevel).describedAs(topLevel.toString()).isEqualTo(215      singletonMap(216        "data", singletonMap(217          "nodesInfo", singletonMap(218            "nodes", Collections.emptyList()))));219  }220  @Test221  public void shouldBeAbleToGetUrlsOfAllNodes() throws URISyntaxException {222    Capabilities stereotype = new ImmutableCapabilities("cheese", "stilton");223    String nodeUri = "http://localhost:5556";224    Node node = LocalNode.builder(tracer, events, new URI(nodeUri), publicUri, registrationSecret)225      .add(stereotype, new SessionFactory() {226        @Override227        public Either<WebDriverException, ActiveSession> apply(228          CreateSessionRequest createSessionRequest) {229          return Either.left(new SessionNotCreatedException("Factory for testing"));230        }231        @Override232        public boolean test(Capabilities capabilities) {233          return false;234        }235      })236      .build();237    distributor.add(node);238    wait.until(obj -> distributor.getStatus().hasCapacity());239    GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);240    Map<String, Object> topLevel = executeQuery(handler, "{ nodesInfo { nodes { uri } } }");241    assertThat(topLevel).describedAs(topLevel.toString()).isEqualTo(242      singletonMap(243        "data", singletonMap(244          "nodesInfo", singletonMap(245            "nodes", singletonList(singletonMap("uri", nodeUri))))));246  }247  @Test248  public void shouldBeAbleToGetSessionCount() throws URISyntaxException {249    String nodeUrl = "http://localhost:5556";250    URI nodeUri = new URI(nodeUrl);251    Node node = LocalNode.builder(tracer, events, nodeUri, publicUri, registrationSecret)252      .add(caps, new TestSessionFactory((id, caps) -> new org.openqa.selenium.grid.data.Session(253        id,254        nodeUri,255        stereotype,256        caps,257        Instant.now()))).build();258    distributor.add(node);259    wait.until(obj -> distributor.getStatus().hasCapacity());260    Either<SessionNotCreatedException, CreateSessionResponse> response = distributor.newSession(sessionRequest);261    if (response.isRight()) {262      Session session = response.right().getSession();263      assertThat(session).isNotNull();264      GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);265      Map<String, Object> topLevel = executeQuery(handler,266        "{ grid { sessionCount } }");267      assertThat(topLevel).isEqualTo(268        singletonMap(269          "data", singletonMap(270            "grid", singletonMap(271              "sessionCount", 1L ))));272    } else {273      fail("Session creation failed", response.left());274    }275  }276  @Test277  public void shouldBeAbleToGetSessionInfo() throws URISyntaxException {278    String nodeUrl = "http://localhost:5556";279    URI nodeUri = new URI(nodeUrl);280    Node node = LocalNode.builder(tracer, events, nodeUri, publicUri, registrationSecret)281      .add(caps, new TestSessionFactory((id, caps) -> new org.openqa.selenium.grid.data.Session(282        id,283        nodeUri,284        stereotype,285        caps,286        Instant.now()))).build();287    distributor.add(node);288    wait.until(obj -> distributor.getStatus().hasCapacity());289    Either<SessionNotCreatedException, CreateSessionResponse> response = distributor.newSession(sessionRequest);290    if (response.isRight()) {291      Session session = response.right().getSession();292      assertThat(session).isNotNull();293      String sessionId = session.getId().toString();294      Set<Slot> slots = distributor.getStatus().getNodes().stream().findFirst().get().getSlots();295      Slot slot = slots.stream().findFirst().get();296      org.openqa.selenium.grid.graphql.Session graphqlSession =297        new org.openqa.selenium.grid.graphql.Session(298          sessionId,299          session.getCapabilities(),300          session.getStartTime(),301          session.getUri(),302          node.getId().toString(),303          node.getUri(),304          slot);305      String query = String.format(306        "{ session (id: \"%s\") { id, capabilities, startTime, uri } }", sessionId);307      GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);308      Map<String, Object> result = executeQuery(handler, query);309      assertThat(result).describedAs(result.toString()).isEqualTo(310        singletonMap(311          "data", singletonMap(312            "session", ImmutableMap.of(313              "id", sessionId,314              "capabilities", graphqlSession.getCapabilities(),315              "startTime", graphqlSession.getStartTime(),316              "uri", graphqlSession.getUri().toString()))));317    } else {318      fail("Session creation failed", response.left());319    }320  }321  @Test322  public void shouldBeAbleToGetNodeInfoForSession() throws URISyntaxException {323    String nodeUrl = "http://localhost:5556";324    URI nodeUri = new URI(nodeUrl);325    Node node = LocalNode.builder(tracer, events, nodeUri, publicUri, registrationSecret)326      .add(caps, new TestSessionFactory((id, caps) -> new org.openqa.selenium.grid.data.Session(327        id,328        nodeUri,329        stereotype,330        caps,331        Instant.now()))).build();332    distributor.add(node);333    wait.until(obj -> distributor.getStatus().hasCapacity());334    Either<SessionNotCreatedException, CreateSessionResponse> response = distributor.newSession(sessionRequest);335    if (response.isRight()) {336      Session session = response.right().getSession();337      assertThat(session).isNotNull();338      String sessionId = session.getId().toString();339      Set<Slot> slots = distributor.getStatus().getNodes().stream().findFirst().get().getSlots();340      Slot slot = slots.stream().findFirst().get();341      org.openqa.selenium.grid.graphql.Session graphqlSession =342        new org.openqa.selenium.grid.graphql.Session(343          sessionId,344          session.getCapabilities(),345          session.getStartTime(),346          session.getUri(),347          node.getId().toString(),348          node.getUri(),349          slot);350      String query = String.format("{ session (id: \"%s\") { nodeId, nodeUri } }", sessionId);351      GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);352      Map<String, Object> result = executeQuery(handler, query);353      assertThat(result).describedAs(result.toString()).isEqualTo(354        singletonMap(355          "data", singletonMap(356            "session", ImmutableMap.of(357              "nodeId", graphqlSession.getNodeId(),358              "nodeUri", graphqlSession.getNodeUri().toString()))));359    } else {360      fail("Session creation failed", response.left());361    }362  }363  @Test364  public void shouldBeAbleToGetSlotInfoForSession() throws URISyntaxException {365    String nodeUrl = "http://localhost:5556";366    URI nodeUri = new URI(nodeUrl);367    Node node = LocalNode.builder(tracer, events, nodeUri, publicUri, registrationSecret)368      .add(caps, new TestSessionFactory((id, caps) -> new org.openqa.selenium.grid.data.Session(369        id,370        nodeUri,371        stereotype,372        caps,373        Instant.now()))).build();374    distributor.add(node);375    wait.until(obj -> distributor.getStatus().hasCapacity());376    Either<SessionNotCreatedException, CreateSessionResponse> response = distributor.newSession(sessionRequest);377    if (response.isRight()) {378      Session session = response.right().getSession();379      assertThat(session).isNotNull();380      String sessionId = session.getId().toString();381      Set<Slot> slots = distributor.getStatus().getNodes().stream().findFirst().get().getSlots();382      Slot slot = slots.stream().findFirst().get();383      org.openqa.selenium.grid.graphql.Session graphqlSession =384        new org.openqa.selenium.grid.graphql.Session(385          sessionId,386          session.getCapabilities(),387          session.getStartTime(),388          session.getUri(),389          node.getId().toString(),390          node.getUri(),391          slot);392      org.openqa.selenium.grid.graphql.Slot graphqlSlot = graphqlSession.getSlot();393      String query = String.format(394        "{ session (id: \"%s\") { slot { id, stereotype, lastStarted } } }", sessionId);395      GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);396      Map<String, Object> result = executeQuery(handler, query);397      assertThat(result).describedAs(result.toString()).isEqualTo(398        singletonMap(399          "data", singletonMap(400            "session", singletonMap(401              "slot", ImmutableMap.of(402                "id", graphqlSlot.getId(),403                "stereotype", graphqlSlot.getStereotype(),404                "lastStarted", graphqlSlot.getLastStarted())))));405    } else {406      fail("Session creation failed", response.left());407    }408  }409  @Test410  public void shouldBeAbleToGetSessionDuration() throws URISyntaxException {411    String nodeUrl = "http://localhost:5556";412    URI nodeUri = new URI(nodeUrl);413    Node node = LocalNode.builder(tracer, events, nodeUri, publicUri, registrationSecret)414      .add(caps, new TestSessionFactory((id, caps) -> new org.openqa.selenium.grid.data.Session(415        id,416        nodeUri,417        stereotype,418        caps,419        Instant.now()))).build();420    distributor.add(node);421    wait.until(obj -> distributor.getStatus().hasCapacity());422    Either<SessionNotCreatedException, CreateSessionResponse> response = distributor.newSession(sessionRequest);423    if (response.isRight()) {424      Session session = response.right().getSession();425      assertThat(session).isNotNull();426      String sessionId = session.getId().toString();427      String query = String.format("{ session (id: \"%s\") { sessionDurationMillis } }", sessionId);428      GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);429      Map<String, Object> result = executeQuery(handler, query);430      assertThat(result)431        .containsOnlyKeys("data")432        .extracting("data").asInstanceOf(MAP).containsOnlyKeys("session")433        .extracting("session").asInstanceOf(MAP).containsOnlyKeys("sessionDurationMillis");434    } else {435      fail("Session creation failed", response.left());436    }437  }438  @Test439  public void shouldThrowExceptionWhenSessionNotFound() throws URISyntaxException {440    String nodeUrl = "http://localhost:5556";441    URI nodeUri = new URI(nodeUrl);442    Node node = LocalNode.builder(tracer, events, nodeUri, publicUri, registrationSecret)443      .add(caps, new TestSessionFactory((id, caps) -> new org.openqa.selenium.grid.data.Session(444        id,445        nodeUri,446        stereotype,447        caps,448        Instant.now()))).build();449    distributor.add(node);450    wait.until(obj -> distributor.getStatus().hasCapacity());451    String randomSessionId = UUID.randomUUID().toString();452    String query = "{ session (id: \"" + randomSessionId + "\") { sessionDurationMillis } }";453    GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);454    Map<String, Object> result = executeQuery(handler, query);455    assertThat(result)456      .containsEntry("data", null)457      .containsKey("errors")458      .extracting("errors").asInstanceOf(LIST).isNotEmpty()459      .element(0).asInstanceOf(MAP).containsKey("extensions")460      .extracting("extensions").asInstanceOf(MAP).containsKey("sessionId")461      .extracting("sessionId").isEqualTo(randomSessionId);462  }463  @Test464  public void shouldThrowExceptionWhenSessionIsEmpty() throws URISyntaxException {465    String nodeUrl = "http://localhost:5556";...Source:NewSessionQueuerTest.java  
...324    HttpClient client = new PassthroughHttpClient(local);325    remote = new RemoteNewSessionQueuer(tracer, client);326    HttpRequest request = createRequest(payload, POST, "/session");327    request.addHeader(SESSIONREQUEST_TIMESTAMP_HEADER,328                      Long.toString(1539091064));329    AtomicInteger count = new AtomicInteger();330    bus.addListener(NewSessionRequestEvent.listener(reqId -> {331      // Add to front of queue, when retry is triggered it will check if request timed out332      count.incrementAndGet();333      remote.retryAddToQueue(request, reqId);334    }));335    HttpResponse httpResponse = remote.addToQueue(request);336    assertEquals(count.get(),1);337    assertEquals(httpResponse.getStatus(), HTTP_INTERNAL_ERROR);338  }339  @Test340  public void shouldBeAbleToTimeoutARequestOnPoll() {341    Tracer tracer = DefaultTestTracer.createTracer();342    LocalNewSessionQueue sessionQueue = new LocalNewSessionQueue(343        tracer,344        bus,345        Duration.ofSeconds(4),346        Duration.ofSeconds(0));347    local = new LocalNewSessionQueuer(tracer, bus, sessionQueue);348    HttpClient client = new PassthroughHttpClient(local);349    remote = new RemoteNewSessionQueuer(tracer, client);350    AtomicBoolean isPresent = new AtomicBoolean();351    bus.addListener(NewSessionRequestEvent.listener(reqId -> {352      Optional<HttpRequest> request = remote.remove();353      isPresent.set(request.isPresent());354      bus.fire(355          new NewSessionRejectedEvent(356              new NewSessionErrorResponse(reqId, "Error")));357    }));358    HttpResponse httpResponse = remote.addToQueue(request);359    assertEquals(httpResponse.getStatus(), HTTP_INTERNAL_ERROR);360    assertThat(isPresent.get()).isFalse();361  }362  @Test363  public void shouldBeAbleToClearQueueAndRejectMultipleRequests() {364    ExecutorService executor = Executors.newFixedThreadPool(2);365    Callable<HttpResponse> callable = () -> remote.addToQueue(request);366    Future<HttpResponse> firstRequest = executor.submit(callable);367    Future<HttpResponse> secondRequest = executor.submit(callable);368    int count = 0;369    while (count < 2) {370      count += remote.clearQueue();371    }372    try {373      HttpResponse firstResponse = firstRequest.get(30, TimeUnit.SECONDS);374      HttpResponse secondResponse = secondRequest.get(30, TimeUnit.SECONDS);375      assertEquals(firstResponse.getStatus(), HTTP_INTERNAL_ERROR);376      assertEquals(secondResponse.getStatus(), HTTP_INTERNAL_ERROR);377    } catch (InterruptedException | ExecutionException | TimeoutException e) {378      fail("Could not create session");379    }380    executor.shutdown();381  }382  private HttpRequest createRequest(NewSessionPayload payload, HttpMethod httpMethod, String uri) {383    StringBuilder builder = new StringBuilder();384    try {385      payload.writeTo(builder);386    } catch (IOException e) {387      throw new UncheckedIOException(e);388    }389    HttpRequest request = new HttpRequest(httpMethod, uri);390    request.setContent(utf8String(builder.toString()));391    return request;392  }393}...Source:LocalNewSessionQueueTest.java  
...99    long timestamp = Instant.now().getEpochSecond();100    ImmutableCapabilities chromeCaps = new ImmutableCapabilities("browserName", "chrome");101    NewSessionPayload chromePayload = NewSessionPayload.create(chromeCaps);102    HttpRequest chromeRequest = createRequest(chromePayload, POST, "/session");103    chromeRequest.addHeader(SESSIONREQUEST_TIMESTAMP_HEADER, Long.toString(timestamp));104    RequestId chromeRequestId = new RequestId(UUID.randomUUID());105    ImmutableCapabilities firefoxCaps = new ImmutableCapabilities("browserName", "firefox");106    NewSessionPayload firefoxpayload = NewSessionPayload.create(firefoxCaps);107    HttpRequest firefoxRequest = createRequest(firefoxpayload, POST, "/session");108    firefoxRequest.addHeader(SESSIONREQUEST_TIMESTAMP_HEADER, Long.toString(timestamp));109    RequestId firefoxRequestId = new RequestId(UUID.randomUUID());110    boolean addedChromeRequest = sessionQueue.offerFirst(chromeRequest, chromeRequestId);111    assertTrue(addedChromeRequest);112    boolean addFirefoxRequest = sessionQueue.offerFirst(firefoxRequest, firefoxRequestId);113    assertTrue(addFirefoxRequest);114    Optional<HttpRequest> polledChromeRequest = sessionQueue.remove(chromeRequestId);115    assertTrue(polledChromeRequest.isPresent());116    assertEquals(chromeRequest, polledChromeRequest.get());117    Optional<HttpRequest> polledFirefoxRequest = sessionQueue.remove(firefoxRequestId);118    assertTrue(polledFirefoxRequest.isPresent());119    assertEquals(firefoxRequest, polledFirefoxRequest.get());120  }121  @Test122  public void shouldAddTimestampHeader() {123    boolean added = sessionQueue.offerLast(expectedSessionRequest, requestId);124    assertTrue(added);125    Optional<HttpRequest> receivedRequest = sessionQueue.remove(requestId);126    assertTrue(receivedRequest.isPresent());127    HttpRequest request = receivedRequest.get();128    assertEquals(expectedSessionRequest, request);129    assertTrue(request.getHeader(NewSessionQueue.SESSIONREQUEST_TIMESTAMP_HEADER) != null);130  }131  @Test132  public void shouldAddRequestIdHeader() {133    boolean added = sessionQueue.offerLast(expectedSessionRequest, requestId);134    assertTrue(added);135    Optional<HttpRequest> receivedRequest = sessionQueue.remove(requestId);136    assertTrue(receivedRequest.isPresent());137    HttpRequest request = receivedRequest.get();138    assertEquals(expectedSessionRequest, request);139    String polledRequestId = request.getHeader(NewSessionQueue.SESSIONREQUEST_ID_HEADER);140    assertTrue(polledRequestId != null);141    assertEquals(requestId, new RequestId(UUID.fromString(polledRequestId)));142  }143  @Test144  public void shouldBeAbleToAddToFrontOfQueue() {145    long timestamp = Instant.now().getEpochSecond();146    ImmutableCapabilities chromeCaps = new ImmutableCapabilities("browserName", "chrome");147    NewSessionPayload chromePayload = NewSessionPayload.create(chromeCaps);148    HttpRequest chromeRequest = createRequest(chromePayload, POST, "/session");149    chromeRequest.addHeader(SESSIONREQUEST_TIMESTAMP_HEADER, Long.toString(timestamp));150    RequestId chromeRequestId = new RequestId(UUID.randomUUID());151    ImmutableCapabilities firefoxCaps = new ImmutableCapabilities("browserName", "firefox");152    NewSessionPayload firefoxpayload = NewSessionPayload.create(firefoxCaps);153    HttpRequest firefoxRequest = createRequest(firefoxpayload, POST, "/session");154    firefoxRequest.addHeader(SESSIONREQUEST_TIMESTAMP_HEADER, Long.toString(timestamp));155    RequestId firefoxRequestId = new RequestId(UUID.randomUUID());156    boolean addedChromeRequest = sessionQueue.offerFirst(chromeRequest, chromeRequestId);157    assertTrue(addedChromeRequest);158    boolean addFirefoxRequest = sessionQueue.offerFirst(firefoxRequest, firefoxRequestId);159    assertTrue(addFirefoxRequest);160    Optional<HttpRequest> polledFirefoxRequest = sessionQueue.remove(firefoxRequestId);161    assertTrue(polledFirefoxRequest.isPresent());162    assertEquals(firefoxRequest, polledFirefoxRequest.get());163    Optional<HttpRequest> polledChromeRequest = sessionQueue.remove(chromeRequestId);164    assertTrue(polledChromeRequest.isPresent());165    assertEquals(chromeRequest, polledChromeRequest.get());166  }167  @Test168  public void shouldBeClearAPopulatedQueue() {169    sessionQueue.offerLast(expectedSessionRequest, new RequestId(UUID.randomUUID()));170    sessionQueue.offerLast(expectedSessionRequest, new RequestId(UUID.randomUUID()));171    int count = sessionQueue.clear();172    assertEquals(count, 2);173  }174  @Test175  public void shouldBeClearAEmptyQueue() {176    int count = sessionQueue.clear();177    assertEquals(count, 0);178  }179  @Test180  public void shouldBeAbleToGetQueueSize() {181    boolean added = sessionQueue.offerLast(expectedSessionRequest, requestId);182    assertTrue(added);183    int size = sessionQueue.getQueueSize();184    assertEquals(1, size);185  }186  @Test187  public void shouldBeAbleToGetQueueContents() {188    long timestamp = Instant.now().getEpochSecond();189    ImmutableCapabilities chromeCaps = new ImmutableCapabilities(190      "browserName", "chrome",191      "platform", "mac",192      "version", "87");193    NewSessionPayload chromePayload = NewSessionPayload.create(chromeCaps);194    HttpRequest chromeRequest = createRequest(chromePayload, POST, "/session");195    chromeRequest.addHeader(SESSIONREQUEST_TIMESTAMP_HEADER, Long.toString(timestamp));196    RequestId chromeRequestId = new RequestId(UUID.randomUUID());197    boolean addedChromeRequest = sessionQueue.offerLast(chromeRequest, chromeRequestId);198    assertTrue(addedChromeRequest);199    ImmutableCapabilities firefoxCaps = new ImmutableCapabilities(200      "browserName", "firefox",201      "platform", "windows",202      "version", "84");203    NewSessionPayload firefoxPayload = NewSessionPayload.create(firefoxCaps);204    HttpRequest firefoxRequest = createRequest(firefoxPayload, POST, "/session");205    firefoxRequest.addHeader(SESSIONREQUEST_TIMESTAMP_HEADER, Long.toString(timestamp));206    RequestId firefoxRequestId = new RequestId(UUID.randomUUID());207    boolean addFirefoxRequest = sessionQueue.offerLast(firefoxRequest, firefoxRequestId);208    assertTrue(addFirefoxRequest);209    List<Object> response = sessionQueue.getQueuedRequests();210    assertThat(response).isNotNull();211    assertEquals(2, response.size());212    assertEquals(chromeCaps, response.get(0));213    assertEquals(firefoxCaps, response.get(1));214  }215  @Test216  public void shouldBeAbleToRemoveRequestsOnTimeout() throws InterruptedException {217    NewSessionQueue localSessionQueue = new LocalNewSessionQueue(218      DefaultTestTracer.createTracer(),219      bus,220      Duration.ofSeconds(30),221      Duration.ofSeconds(1));222    CountDownLatch latch = new CountDownLatch(1);223    bus.addListener(NewSessionRejectedEvent.listener(reqId -> latch.countDown()));224    boolean added = localSessionQueue.offerLast(expectedSessionRequest, requestId);225    assertTrue(added);226    boolean requestExpired = latch.await(2, TimeUnit.MINUTES);227    assertThat(requestExpired).isTrue();228    assertThat(localSessionQueue.getQueueSize()).isZero();229  }230  private HttpRequest createRequest(NewSessionPayload payload, HttpMethod httpMethod, String uri) {231    StringBuilder builder = new StringBuilder();232    try {233      payload.writeTo(builder);234    } catch (IOException e) {235      throw new UncheckedIOException(e);236    }237    HttpRequest request = new HttpRequest(httpMethod, uri);238    request.setContent(utf8String(builder.toString()));239    return request;240  }241}...Source:LocalNewSessionQueue.java  
...141      SessionRequest sessionRequest = new SessionRequest(requestId, request);142      addRequestHeaders(request, requestId);143      boolean added = sessionRequests.offerLast(sessionRequest);144      attributeMap.put(145        AttributeKey.REQUEST_ID.getKey(), EventAttribute.setValue(requestId.toString()));146      attributeMap.put("request.added", EventAttribute.setValue(added));147      span.addEvent("Add new session request to the queue", attributeMap);148      if (added) {149        bus.fire(new NewSessionRequestEvent(requestId));150      }151      return added;152    } finally {153      writeLock.unlock();154      span.close();155    }156  }157  @Override158  public boolean offerFirst(HttpRequest request, RequestId requestId) {159    Require.nonNull("New Session request", request);...Source:AddBackToSessionQueue.java  
...42  @Override43  public HttpResponse execute(HttpRequest req) {44    try (Span span = newSpanAsChildOf(tracer, req, "sessionqueue.retry")) {45      HTTP_REQUEST.accept(span, req);46      span.setAttribute(AttributeKey.REQUEST_ID.getKey(), id.toString());47      SessionRequest sessionRequest = Contents.fromJson(req, SessionRequest.class);48      boolean value = newSessionQueue.retryAddToQueue(sessionRequest);49      span.setAttribute("request.retry", value);50      HttpResponse response = new HttpResponse()51        .setContent(asJson(singletonMap("value", value)));52      HTTP_RESPONSE.accept(span, response);53      return response;54    }55  }56}...toString
Using AI Code Generation
1import org.openqa.selenium.grid.data.SessionRequest;2import org.openqa.selenium.remote.http.HttpRequest;3import org.openqa.selenium.remote.http.HttpResponse;4public class SessionRequestToString {5  public static void main(String[] args) {6    HttpRequest request = new HttpRequest("POST", "/session");7    request.setContent("{\"capabilities\": {\"alwaysMatch\": {\"browserName\": \"firefox\"}}}".getBytes());8    SessionRequest sessionRequest = new SessionRequest(request);9    System.out.println(sessionRequest.toString());10  }11}12SessionRequest{capabilities=Capabilities{alwaysMatch={browserName=firefox}}}13import org.openqa.selenium.grid.data.Session;14import org.openqa.selenium.remote.http.HttpRequest;15import org.openqa.selenium.remote.http.HttpResponse;16public class SessionToString {17  public static void main(String[] args) {18    HttpRequest request = new HttpRequest("POST", "/session");19    request.setContent("{\"capabilities\": {\"alwaysMatch\": {\"browserName\": \"firefox\"}}}".getBytes());20    SessionRequest sessionRequest = new SessionRequest(request);21    Session session = new Session(22      new HttpResponse().setContent("{\"capabilities\": {\"alwaysMatch\": {\"browserName\": \"firefox\"}}}".getBytes()),23    );24    System.out.println(session.toString());25  }26}27import org.openqa.selenium.grid.data.Session;28import org.openqa.selenium.grid.data.Slot;29import org.openqa.selenium.grid.data.SlotId;30import org.openqa.selenium.grid.data.StandaloneSession;31import org.openqa.selenium.remote.http.HttpRequest;32import org.openqa.selenium.remote.http.HttpResponse;33import java.net.URI;34import java.net.URISyntaxException;35import java.time.Instant;36public class SlotToString {37  public static void main(String[] args) throws URISyntaxException {toString
Using AI Code Generation
1log.info("SessionRequest object to string: {}", sessionRequest.toString());2log.info("SessionId object to string: {}", sessionId.toString());3log.info("Session object to string: {}", session.toString());4log.info("NodeId object to string: {}", nodeId.toString());5log.info("NodeStatus object to string: {}", nodeStatus.toString());6log.info("Node object to string: {}", node.toString());7log.info("Slot object to string: {}", slot.toString());8log.info("SlotId object to string: {}", slotId.toString());9log.info("SlotSession object to string: {}", slotSession.toString());10log.info("SlotStatus object to string: {}", slotStatus.toString());11log.info("Availability object to string: {}", availability.toString());12log.info("AvailabilityEvent object to string: {}", availabilityEvent.toString());13log.info("AvailabilityListener object to string: {}", availabilityListener.toString());toString
Using AI Code Generation
1System.out.println(sessionRequest.toString());2System.out.println(sessionRequest);3System.out.println(sessionRequest.toString());4System.out.println(sessionRequest.toString());5System.out.println(sessionRequest);6System.out.println(sessionRequest.toString());7System.out.println(sessionRequest.toString());8System.out.println(sessionRequest);9System.out.println(sessionRequest.toString());10System.out.println(sessionRequest.toString());11System.out.println(sessionRequest);12System.out.println(sessionRequest.toString());13System.out.println(sessionRequest.toStringtoString
Using AI Code Generation
1System.out.println(new SessionRequest(2  new ImmutableCapabilities("browserName", "chrome"),3  ImmutableSet.of( new ImmutableCapabilities("browserName", "chrome"), new ImmutableCapabilities("browserName", "firefox")),4  ImmutableSet.of("chrome", "firefox")5).toString());6{"capabilities":{"browserName":"chrome"},"alwaysMatch":[{"browserName":"chrome"},{"browserName":"firefox"}],"firstMatch":["chrome","firefox"]}7System.out.println(new SessionRequest(8  new ImmutableCapabilities("browserName", "chrome"),9  ImmutableSet.of( new ImmutableCapabilities("browserName", "chrome"), new ImmutableCapabilities("browserName", "firefox")),10  ImmutableSet.of("chrome", "firefox")11).toString());12{"capabilities":{"browserName":"chrome"},"alwaysMatch":[{"browserName":"chrome"},{"browserName":"firefox"}],"firstMatch":["chrome","firefox"]}13System.out.println(new SessionRequest(14  new ImmutableCapabilities("browserName", "chrome"),15  ImmutableSet.of( new ImmutableCapabilities("browserName", "chrome"), new ImmutableCapabilities("browserName", "firefox")),16  ImmutableSet.of("chrome", "firefox")17).toString());18{"capabilities":{"browserName":"chrome"},"alwaysMatch":[{"browserName":"chrome"},{"browserName":"firefox"}],"firstMatch":["chrome","firefox"]}19System.out.println(new SessionRequest(20  new ImmutableCapabilities("browserName", "chrome"),21  ImmutableSet.of( new ImmutableCapabilities("browserName", "chrome"), new ImmutableCapabilities("browserName", "firefox")),22  ImmutableSet.of("chrome", "firefox")23).toString());24{"capabilities":{"browserName":"chrome"},"alwaysMatch":[{"browserName":"chrome"},{"browserName":"firefox"}],"firstMatch":["chrome","firefox"]}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!!
