How to use fromJson method of org.openqa.selenium.remote.http.Contents class

Best Selenium code snippet using org.openqa.selenium.remote.http.Contents.fromJson

Source:StatusServletTests.java Github

copy

Full Screen

1// Licensed to the Software Freedom Conservancy (SFC) under one2// or more contributor license agreements. See the NOTICE file3// distributed with this work for additional information4// regarding copyright ownership. The SFC licenses this file5// to you under the Apache License, Version 2.0 (the6// "License"); you may not use this file except in compliance7// with the License. You may obtain a copy of the License at8//9// http://www.apache.org/licenses/LICENSE-2.010//11// Unless required by applicable law or agreed to in writing,12// software distributed under the License is distributed on an13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY14// KIND, either express or implied. See the License for the15// specific language governing permissions and limitations16// under the License.17package org.openqa.grid.internal;18import static org.junit.Assert.assertEquals;19import static org.junit.Assert.assertFalse;20import static org.junit.Assert.assertNotNull;21import static org.junit.Assert.assertNull;22import static org.junit.Assert.assertTrue;23import static org.openqa.selenium.json.Json.MAP_TYPE;24import static org.openqa.selenium.remote.http.Contents.string;25import static org.openqa.selenium.remote.http.Contents.utf8String;26import static org.openqa.selenium.remote.http.HttpMethod.GET;27import static org.openqa.selenium.remote.http.HttpMethod.POST;28import com.google.common.collect.ImmutableList;29import com.google.common.collect.ImmutableMap;30import org.junit.After;31import org.junit.Before;32import org.junit.Test;33import org.openqa.grid.common.RegistrationRequest;34import org.openqa.grid.internal.mock.GridHelper;35import org.openqa.grid.internal.utils.configuration.GridHubConfiguration;36import org.openqa.grid.web.Hub;37import org.openqa.grid.web.servlet.handler.RequestHandler;38import org.openqa.selenium.json.Json;39import org.openqa.selenium.net.PortProber;40import org.openqa.selenium.remote.CapabilityType;41import org.openqa.selenium.remote.DesiredCapabilities;42import org.openqa.selenium.remote.http.HttpClient;43import org.openqa.selenium.remote.http.HttpRequest;44import org.openqa.selenium.remote.http.HttpResponse;45import java.io.IOException;46import java.net.URL;47import java.net.URLEncoder;48import java.util.ArrayList;49import java.util.Collection;50import java.util.HashMap;51import java.util.List;52import java.util.Map;53public class StatusServletTests {54 private Hub hub;55 private RemoteProxy p1;56 private URL proxyApi;57 private URL hubApi;58 private URL testSessionApi;59 private TestSession session;60 private HttpClient client;61 @Before62 public void setup() throws Exception {63 GridHubConfiguration c = new GridHubConfiguration();64 c.timeout = 12345;65 c.port = PortProber.findFreePort();66 c.host = "localhost";67 hub = new Hub(c);68 GridRegistry registry = hub.getRegistry();69 client = HttpClient.Factory.createDefault().createClient(hub.getUrl());70 hubApi = hub.getUrl("/grid/api/hub");71 proxyApi = hub.getUrl("/grid/api/proxy");72 testSessionApi = hub.getUrl("/grid/api/testsession");73 hub.start();74 p1 = RemoteProxyFactory.getNewBasicRemoteProxy("app1", "http://machine1:4444", registry);75 RemoteProxy p2 =76 RemoteProxyFactory.getNewBasicRemoteProxy("app1", "http://machine2:4444", registry);77 RemoteProxy p3 =78 RemoteProxyFactory.getNewBasicRemoteProxy("app1", "http://machine3:4444", registry);79 RemoteProxy p4 =80 RemoteProxyFactory.getNewBasicRemoteProxy("app1", "http://machine4:4444", registry);81 RegistrationRequest req = new RegistrationRequest();82 req.getConfiguration().capabilities.clear();83 Map<String, Object> capability = new HashMap<>();84 capability.put(CapabilityType.BROWSER_NAME, "custom app");85 req.getConfiguration().capabilities.add(new DesiredCapabilities(capability));86 req.getConfiguration().host = "machine5";87 req.getConfiguration().port = 4444;88 RemoteProxy customProxy = new MyCustomProxy(req, registry);89 registry.add(p1);90 registry.add(p2);91 registry.add(p3);92 registry.add(p4);93 registry.add(customProxy);94 Map<String, Object> cap = new HashMap<>();95 cap.put(CapabilityType.BROWSER_NAME, "app1");96 RequestHandler newSessionRequest = GridHelper.createNewSessionHandler(registry, cap);97 newSessionRequest.process();98 session = newSessionRequest.getSession();99 session.setExternalKey(ExternalSessionKey.fromString("ext. key"));100 }101 @Test102 public void testGet() throws IOException {103 String id = "http://machine1:4444";104 HttpRequest request = new HttpRequest(GET, proxyApi.toExternalForm() + "?id=" + id);105 HttpResponse response = client.execute(request);106 assertEquals(200, response.getStatus());107 Map<String, Object> o = extractObject(response);108 assertEquals(id, o.get("id"));109 }110 @Test111 public void testGetNegative() throws IOException {112 String id = "http://wrongOne:4444";113 HttpRequest r = new HttpRequest(GET, proxyApi.toExternalForm() + "?id=" + id);114 HttpResponse response = client.execute(r);115 assertEquals(200, response.getStatus());116 Map<String, Object> o = extractObject(response);117 assertEquals(false, o.get("success"));118 }119 @Test120 public void testPost() throws IOException {121 String id = "http://machine1:4444";122 Map<String, Object> o = ImmutableMap.of("id", id);123 HttpRequest r = new HttpRequest(POST, proxyApi.toExternalForm());124 r.setContent(utf8String(new Json().toJson(o)));125 HttpResponse response = client.execute(r);126 assertEquals(200, response.getStatus());127 Map<String, Object> res = extractObject(response);128 assertEquals(id, res.get("id"));129 }130 @Test131 public void testPostReflection() throws IOException {132 String id = "http://machine5:4444";133 Map<String, Object> o = ImmutableMap.of(134 "id", id,135 "getURL", "",136 "getBoolean", "",137 "getString", "");138 HttpRequest r = new HttpRequest(POST, proxyApi.toExternalForm());139 r.setContent(utf8String(new Json().toJson(o)));140 HttpResponse response = client.execute(r);141 assertEquals(200, response.getStatus());142 Map<String, Object> res = extractObject(response);143 assertEquals(MyCustomProxy.MY_BOOLEAN, res.get("getBoolean"));144 assertEquals(MyCustomProxy.MY_STRING, res.get("getString"));145 // url converted to string146 assertEquals(MyCustomProxy.MY_URL.toString(), res.get("getURL"));147 }148 @Test149 public void testSessionApi() throws IOException {150 ExternalSessionKey s = session.getExternalKey();151 Map<String, Object> o = ImmutableMap.of("session", s.toString());152 HttpRequest r = new HttpRequest(POST, testSessionApi.toExternalForm());153 r.setContent(utf8String(new Json().toJson(o)));154 HttpResponse response = client.execute(r);155 assertEquals(200, response.getStatus());156 Map<String, Object> res = extractObject(response);157 assertTrue((boolean) res.get("success"));158 assertNotNull(res.get("internalKey"));159 assertEquals(s, ExternalSessionKey.fromJSON((String) res.get("session")));160 assertNotNull(res.get("inactivityTime"));161 assertEquals(p1.getId(), res.get("proxyId"));162 }163 @Test164 public void testSessionGet() throws IOException {165 ExternalSessionKey s = session.getExternalKey();166 String url =167 testSessionApi.toExternalForm() + "?session=" + URLEncoder.encode(s.getKey(), "UTF-8");168 HttpRequest r = new HttpRequest(GET, url);169 HttpResponse response = client.execute(r);170 assertEquals(200, response.getStatus());171 Map<String, Object> o = extractObject(response);172 assertTrue((boolean) o.get("success"));173 assertNotNull(o.get("internalKey"));174 assertEquals(s, ExternalSessionKey.fromJSON((String) o.get("session")));175 assertNotNull(o.get("inactivityTime"));176 assertEquals(p1.getId(), o.get("proxyId"));177 }178 /**179 * if a certain set of parameters are requested to the hub, only those params are returned.180 */181 @Test182 public void testHubGetSpecifiedConfig() throws IOException {183 String url = hubApi.toExternalForm();184 HttpRequest r = new HttpRequest(POST, url);185 Map<String, Object> j = ImmutableMap.of(186 "configuration", ImmutableList.of(187 "timeout",188 "I'm not a valid key",189 "servlets"));190 r.setContent(utf8String(new Json().toJson(j)));191 HttpResponse response = client.execute(r);192 assertEquals(200, response.getStatus());193 Map<String, Object> o = extractObject(response);194 assertTrue((Boolean) o.get("success"));195 assertEquals(12345L, o.get("timeout"));196 assertNull(o.get("I'm not a valid key"));197 assertEquals(0, ((Collection) o.get("servlets")).size());198 assertNull(o.get("capabilityMatcher"));199 }200 /**201 * if a certain set of parameters are requested to the hub, only those params are returned.202 */203 @Test204 public void testHubGetSpecifiedConfigWithQueryString() throws IOException {205 List<String> keys = new ArrayList<>();206 keys.add(URLEncoder.encode("timeout", "UTF-8"));207 keys.add(URLEncoder.encode("I'm not a valid key", "UTF-8"));208 keys.add(URLEncoder.encode("servlets", "UTF-8"));209 String query = "?configuration=" + String.join(",",keys);210 String url = hubApi.toExternalForm() + query ;211 HttpRequest r = new HttpRequest(GET, url);212 HttpResponse response = client.execute(r);213 assertEquals(200, response.getStatus());214 Map<String, Object> o = extractObject(response);215 assertTrue((Boolean) o.get("success"));216 assertEquals(12345L, o.get("timeout"));217 assertNull(o.get("I'm not a valid key"));218 assertEquals(0, ((Collection<?>) o.get("servlets")).size());219 assertFalse(o.containsKey("capabilityMatcher"));220 }221 /**222 * when no param is specified, a call to the hub API returns all the config params the hub223 * currently uses.224 */225 @Test226 public void testHubGetAllConfig() throws IOException {227 String url = hubApi.toExternalForm();228 HttpRequest r = new HttpRequest(GET, url);229 Map<String, Object> j = ImmutableMap.of("configuration", ImmutableList.of());230 r.setContent(utf8String(new Json().toJson(j)));231 HttpResponse response = client.execute(r);232 assertEquals(200, response.getStatus());233 Map<String, Object> o = extractObject(response);234 assertTrue((boolean) o.get("success"));235 assertEquals("org.openqa.grid.internal.utils.DefaultCapabilityMatcher",236 o.get("capabilityMatcher"));237 assertNull(o.get("prioritizer"));238 }239 @Test240 public void testHubGetAllConfigNoParamsWhenNoPostBody() throws IOException {241 String url = hubApi.toExternalForm();242 HttpRequest r = new HttpRequest(GET, url);243 HttpResponse response = client.execute(r);244 assertEquals(200, response.getStatus());245 Map<String, Object> o = extractObject(response);246 assertTrue((Boolean) o.get("success"));247 assertEquals("org.openqa.grid.internal.utils.DefaultCapabilityMatcher",248 o.get("capabilityMatcher"));249 assertNull(o.get("prioritizer"));250 }251 @Test252 public void testHubGetNewSessionRequestCount() throws IOException {253 String url = hubApi.toExternalForm();254 HttpRequest r = new HttpRequest(GET, url);255 Map<String, Object> j = ImmutableMap.of(256 "configuration", ImmutableList.of("newSessionRequestCount"));257 r.setContent(utf8String(new Json().toJson(j)));258 HttpResponse response = client.execute(r);259 assertEquals(200, response.getStatus());260 Map<String, Object> o = extractObject(response);261 assertTrue((Boolean) o.get("success"));262 assertEquals(0L, o.get("newSessionRequestCount"));263 }264 @Test265 public void testHubGetSlotCounts() throws IOException {266 String url = hubApi.toExternalForm();267 HttpRequest r = new HttpRequest(POST, url);268 Map<String, Object> j = ImmutableMap.of("configuration", ImmutableList.of("slotCounts"));269 r.setContent(utf8String(new Json().toJson(j)));270 HttpResponse response = client.execute(r);271 assertEquals(200, response.getStatus());272 Map<String, Object> o = extractObject(response);273 assertTrue((Boolean) o.get("success"));274 assertNotNull(o.get("slotCounts"));275 Map<?, ?> slotCounts = (Map<?, ?>) o.get("slotCounts");276 assertEquals(4L, slotCounts.get("free"));277 assertEquals(5L, slotCounts.get("total"));278 }279 @Test280 public void testSessionApiNeg() throws IOException {281 String s = "non-existing session";282 Map<String, Object> o = ImmutableMap.of("session", s);283 HttpRequest r = new HttpRequest(POST, testSessionApi.toExternalForm());284 r.setContent(utf8String(new Json().toJson(o)));285 HttpResponse response = client.execute(r);286 assertEquals(200, response.getStatus());287 Map<String, Object> res = extractObject(response);288 assertFalse((boolean) res.get("success"));289 }290 @After291 public void teardown() {292 hub.stop();293 }294 private Map<String, Object> extractObject(HttpResponse resp) {295 return new Json().toType(string(resp), MAP_TYPE);296 }297}...

Full Screen

Full Screen

Source:SessionRequest.java Github

copy

Full Screen

...136 toReturn.put("metadata", metadata);137 toReturn.put("traceHeaders", traceHeaders);138 return unmodifiableMap(toReturn);139 }140 private static SessionRequest fromJson(JsonInput input) {141 RequestId id = null;142 Instant enqueued = null;143 Set<Capabilities> capabilities = null;144 Set<Dialect> dialects = null;145 Map<String, Object> metadata = emptyMap();146 Map<String, String> tracerHeaders = emptyMap();147 input.beginObject();148 while (input.hasNext()) {149 switch (input.nextName()) {150 case "capabilities":151 capabilities = input.read(SET_OF_CAPABILITIES);152 break;153 case "dialects":154 dialects = input.read(SET_OF_DIALECTS);...

Full Screen

Full Screen

Source:AddBackToSessionQueue.java Github

copy

Full Screen

...43 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}...

Full Screen

Full Screen

Source:GetNextMatchingRequest.java Github

copy

Full Screen

...44 @Override45 public HttpResponse execute(HttpRequest req) throws UncheckedIOException {46 try (Span span = newSpanAsChildOf(tracer, req, "sessionqueue.getrequest")) {47 HTTP_REQUEST.accept(span, req);48 Set<Capabilities> stereotypes = Contents.fromJson(req, SET_OF_CAPABILITIES);49 Optional<SessionRequest> maybeRequest = queue.getNextAvailable(stereotypes);50 HttpResponse response = new HttpResponse().setContent(Contents.asJson(singletonMap("value", maybeRequest.orElse(null))));51 HTTP_RESPONSE.accept(span, response);52 return response;53 }54 }55}...

Full Screen

Full Screen

Source:SessionNotCreated.java Github

copy

Full Screen

...41 @Override42 public HttpResponse execute(HttpRequest req) throws UncheckedIOException {43 try (Span span = newSpanAsChildOf(tracer, req, "sessionqueue.created_bad")) {44 HTTP_REQUEST.accept(span, req);45 String message = Contents.fromJson(req, String.class);46 SessionNotCreatedException exception = new SessionNotCreatedException(message);47 queue.complete(requestId, Either.left(exception));48 HttpResponse res = new HttpResponse();49 HTTP_RESPONSE.accept(span, res);50 return res;51 }52 }53}...

Full Screen

Full Screen

Source:SessionCreated.java Github

copy

Full Screen

...41 @Override42 public HttpResponse execute(HttpRequest req) throws UncheckedIOException {43 try (Span span = newSpanAsChildOf(tracer, req, "sessionqueue.created_ok")) {44 HTTP_REQUEST.accept(span, req);45 CreateSessionResponse response = Contents.fromJson(req, CreateSessionResponse.class);46 queue.complete(requestId, Either.right(response));47 HttpResponse res = new HttpResponse();48 HTTP_RESPONSE.accept(span, res);49 return res;50 }51 }52}...

Full Screen

Full Screen

Source:CreateSession.java Github

copy

Full Screen

...34 this.distributor = Require.nonNull("Distributor", distributor);35 }36 @Override37 public HttpResponse execute(HttpRequest req) throws UncheckedIOException {38 SessionRequest request = Contents.fromJson(req, SessionRequest.class);39 Either<SessionNotCreatedException, CreateSessionResponse> result = distributor.newSession(request);40 HttpResponse res = new HttpResponse();41 Map<String, Object> value;42 if (result.isLeft()) {43 res.setStatus(HTTP_INTERNAL_ERROR);44 value = singletonMap("value", result.left());45 } else {46 value = singletonMap("value", result.right());47 }48 res.setContent(Contents.asJson(value));49 return res;50 }51}...

Full Screen

Full Screen

Source:AddToSessionQueue.java Github

copy

Full Screen

...36 @Override37 public HttpResponse execute(HttpRequest req) {38 try (Span span = newSpanAsChildOf(tracer, req, "sessionqueue.add")) {39 HTTP_REQUEST.accept(span, req);40 HttpResponse response = newSessionQueue.addToQueue(Contents.fromJson(req, SessionRequest.class));41 HTTP_RESPONSE.accept(span, response);42 return response;43 }44 }45}...

Full Screen

Full Screen

fromJson

Using AI Code Generation

copy

Full Screen

1import org.openqa.selenium.remote.http.Contents2import groovy.json.JsonSlurper3def jsonSlurper = new JsonSlurper()4def json = jsonSlurper.parseText(Contents.fromJson(response.body).asReader())5import org.openqa.selenium.remote.http.Contents6import groovy.json.JsonSlurper7def jsonSlurper = new JsonSlurper()8def json = jsonSlurper.parseText(Contents.fromJson(response.body).asReader())9import org.openqa.selenium.remote.http.Contents10import groovy.json.JsonSlurper11def jsonSlurper = new JsonSlurper()12def json = jsonSlurper.parseText(Contents.fromJson(response.body).asReader())13import org.openqa.selenium.remote.http.Contents14import groovy.json.JsonSlurper15def jsonSlurper = new JsonSlurper()16def json = jsonSlurper.parseText(Contents.fromJson(response.body).asReader())17import org.openqa.selenium.remote.http.Contents18import groovy.json.JsonSlurper19def jsonSlurper = new JsonSlurper()20def json = jsonSlurper.parseText(Contents.fromJson(response.body).asReader())

Full Screen

Full Screen

fromJson

Using AI Code Generation

copy

Full Screen

1import org.openqa.selenium.remote.http.Contents;2import java.io.IOException;3public class JsonToJava {4 public static void main(String[] args) throws IOException {5 String json = "{\"name\":\"John\",\"age\":30,\"car\":null}";6 Contents contents = Contents.fromJson(json);7 System.out.println(contents);8 }9}10{name=John, age=30, car=null}

Full Screen

Full Screen

fromJson

Using AI Code Generation

copy

Full Screen

1package org.openqa.selenium.remote.http;2import java.util.Map;3public class Contents {4 public static Map<String, Object> fromJson(String json) {5 return new JsonToBeanConverter().convert(Map.class, json);6 }7}8package org.openqa.selenium.remote.http;9import java.util.Map;10public class Contents {11 public static String toJson(Map<String, Object> map) {12 return new BeanToJsonConverter().convert(map);13 }14}15package org.openqa.selenium.remote.http;16import java.util.List;17public class Contents {18 public static String toJson(List<Object> list) {19 return new BeanToJsonConverter().convert(list);20 }21}22package org.openqa.selenium.remote.http;23import java.util.Set;24public class Contents {25 public static String toJson(Set<Object> set) {26 return new BeanToJsonConverter().convert(set);27 }28}29package org.openqa.selenium.remote.http;30public class Contents {31 public static String toJson(String string) {32 return new BeanToJsonConverter().convert(string);33 }34}35package org.openqa.selenium.remote.http;36public class Contents {37 public static String toJson(Number number) {38 return new BeanToJsonConverter().convert(number);39 }40}41package org.openqa.selenium.remote.http;42public class Contents {43 public static String toJson(Boolean bool) {44 return new BeanToJsonConverter().convert(bool);45 }46}47package org.openqa.selenium.remote.http;48public class Contents {49 public static String toJson() {50 return new BeanToJsonConverter().convert(null);51 }52}

Full Screen

Full Screen

fromJson

Using AI Code Generation

copy

Full Screen

1import org.openqa.selenium.remote.http.Contents;2String content = Contents.string(response.getContent());3import org.openqa.selenium.remote.http.Contents;4byte[] content = Contents.bytes(response.getContent());5import org.openqa.selenium.remote.http.Contents;6JsonObject content = Contents.json(response.getContent());7import org.openqa.selenium.remote.http.Contents;8JsonArray content = Contents.jsonArray(response.getContent());9import org.openqa.selenium.remote.http.Contents;10InputStream content = Contents.asInputStream(response.getContent());11import org.openqa.selenium.remote.http.Contents;12Reader content = Contents.asReader(response.getContent());13import org.openqa.selenium.remote.http.Contents;14BufferedReader content = Contents.asBufferedReader(response.getContent());15import org.openqa.selenium.remote.http.Contents;16BufferedInputStream content = Contents.asBufferedInputStream(response.getContent());17import org.openqa.selenium.remote.http.Contents;18File content = Contents.asFile(response.getContent());19import org.openqa.selenium.remote.http.Contents;20Path content = Contents.asPath(response.getContent());21import org.openqa.selenium.remote.http.Contents;22Image content = Contents.asImage(response.getContent());

Full Screen

Full Screen

Selenium 4 Tutorial:

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.

Chapters:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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.

Selenium 101 certifications:

LambdaTest also provides certification for Selenium testing to accelerate your career in Selenium automation testing.

Run Selenium automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful