Best FluentLenium code snippet using org.fluentlenium.core.hook.DefaultHookChainBuilder.newInstance
Source:FluentInjector.java  
...78        containerContexts.clear();79        componentsManager.release();80    }81    @Override82    public <T> T newInstance(Class<T> cls) {83        T container = containerInstantiator.newInstance(cls, null);84        inject(container);85        return container;86    }87    @Override88    public ContainerContext inject(Object container) {89        inject(container, null, fluentControl.getDriver());90        return containerContexts.get(container);91    }92    @Override93    public ContainerContext injectComponent(Object componentContainer, Object parentContainer, SearchContext searchContext) {94        initContainerContext(componentContainer, parentContainer, searchContext);95        initParentContainer(componentContainer, parentContainer);96        initFluentElements(componentContainer, searchContext);97        initChildrenContainers(componentContainer, searchContext);98        return containerContexts.get(componentContainer);99    }100    private void inject(Object container, Object parentContainer, SearchContext searchContext) {101        initContainer(container, parentContainer, searchContext);102        initParentContainer(container, parentContainer);103        initFluentElements(container, searchContext);104        initChildrenContainers(container, searchContext);105    }106    private void initParentContainer(Object container, Object parentContainer) {107        for (Class cls = container.getClass(); isClassSupported(cls); cls = cls.getSuperclass()) {108            for (Field field : cls.getDeclaredFields()) {109                if (isParent(field)) {110                    try {111                        ReflectionUtils.set(field, container, parentContainer);112                    } catch (IllegalAccessException | IllegalArgumentException e) {113                        throw new FluentInjectException("Can't set field " + field + " with value " + parentContainer, e);114                    }115                }116            }117        }118    }119    private boolean isParent(Field field) {120        return field.isAnnotationPresent(Parent.class);121    }122    private void initContainer(Object container, Object parentContainer, SearchContext searchContext) {123        initContainerContext(container, parentContainer, searchContext);124        if (container instanceof FluentContainer) {125            ((FluentContainer) container).initFluent(new ContainerFluentControl(fluentControl, containerContexts.get(container)));126        }127        initEventAnnotations(container);128    }129    private void initContainerContext(Object container, Object parentContainer, SearchContext searchContext) {130        ContainerContext parentContainerContext = parentContainer == null ? null : containerContexts.get(parentContainer);131        DefaultContainerContext containerContext = new DefaultContainerContext(container, parentContainerContext, searchContext);132        containerContexts.put(container, containerContext);133        if (parentContainerContext != null) {134            containerContext.getHookDefinitions().addAll(parentContainerContext.getHookDefinitions());135        }136        for (Class cls = container.getClass(); isClassSupported(cls); cls = cls.getSuperclass()) {137            addHookDefinitions(cls.getDeclaredAnnotations(), containerContext.getHookDefinitions());138        }139    }140    private void initEventAnnotations(Object container) {141        if (eventsRegistry != null && !eventsContainerSupport.containsKey(container)) {142            eventsContainerSupport.put(container, new ContainerAnnotationsEventsRegistry(eventsRegistry, container));143        }144    }145    private static boolean isContainer(Field field) {146        return field.isAnnotationPresent(Page.class);147    }148    private static boolean isClassSupported(Class<?> cls) {149        return cls != Object.class && cls != null;150    }151    private void initChildrenContainers(Object container, SearchContext searchContext) {152        for (Class cls = container.getClass(); isClassSupported(cls); cls = cls.getSuperclass()) {153            for (Field field : cls.getDeclaredFields()) {154                if (isContainer(field)) {155                    Class fieldClass = field.getType();156                    Object existingChildContainer = containerInstances.get(fieldClass);157                    if (existingChildContainer == null) {158                        Object childContainer = containerInstantiator.newInstance(fieldClass, containerContexts.get(container));159                        initContainer(childContainer, container, searchContext);160                        try {161                            ReflectionUtils.set(field, container, childContainer);162                        } catch (IllegalAccessException e) {163                            throw new FluentInjectException("Can't set field " + field + " with value " + childContainer, e);164                        }165                        containerInstances.put(fieldClass, childContainer);166                        inject(childContainer, container, searchContext);167                    } else {168                        try {169                            ReflectionUtils.set(field, container, existingChildContainer);170                        } catch (IllegalAccessException e) {171                            throw new FluentInjectException("Can't set field " + field + " with value " + existingChildContainer,172                                    e);173                        }174                    }175                }176            }177        }178    }179    private void initFluentElements(Object container, SearchContext searchContext) {180        ContainerContext containerContext = containerContexts.get(container);181        for (Class cls = container.getClass(); isClassSupported(cls); cls = cls.getSuperclass()) {182            for (Field field : cls.getDeclaredFields()) {183                if (isSupported(container, field)) {184                    ArrayList<HookDefinition<?>> fieldHookDefinitions = new ArrayList<>(containerContext.getHookDefinitions());185                    addHookDefinitions(field.getAnnotations(), fieldHookDefinitions);186                    InjectionElementLocatorFactory locatorFactory = new InjectionElementLocatorFactory(searchContext);187                    InjectionElementLocator locator = locatorFactory.createLocator(field);188                    if (locator != null) {189                        ComponentAndProxy fieldValue = initFieldElements(locator, field);190                        injectComponent(fieldValue, locator, container, field, fieldHookDefinitions);191                    }192                }193            }194        }195    }196    private void injectComponent(ComponentAndProxy fieldValue, ElementLocator locator, Object container, Field field,197            ArrayList<HookDefinition<?>> fieldHookDefinitions) {198        if (fieldValue != null) {199            LocatorProxies.setHooks(fieldValue.getProxy(), hookChainBuilder, fieldHookDefinitions);200            try {201                ReflectionUtils.set(field, container, fieldValue.getComponent());202            } catch (IllegalAccessException e) {203                throw new FluentInjectException(204                        "Unable to find an accessible constructor with an argument of type WebElement in " + field.getType(), e);205            }206            if (fieldValue.getComponent() instanceof Iterable) {207                if (isLazyComponentsAndNotInitialized(fieldValue.getComponent())) {208                    LazyComponents lazyComponents = (LazyComponents) fieldValue.getComponent();209                    lazyComponents.addLazyComponentsListener((LazyComponentsListener<Object>) componentMap -> {210                        for (Entry<WebElement, Object> componentEntry : componentMap.entrySet()) {211                            injectComponent(componentEntry.getValue(), container, componentEntry.getKey());212                        }213                    });214                }215            } else {216                ElementLocatorSearchContext componentSearchContext = new ElementLocatorSearchContext(locator);217                injectComponent(fieldValue.getComponent(), container, componentSearchContext);218            }219        }220    }221    private boolean isLazyComponentsAndNotInitialized(Object component) {222        if (component instanceof LazyComponents) {223            LazyComponents lazyComponents = (LazyComponents) component;224            return lazyComponents.isLazy() && !lazyComponents.isLazyInitialized();225        }226        return false;227    }228    private Hook getHookAnnotation(Annotation annotation) {229        if (annotation instanceof Hook) {230            return (Hook) annotation;231        } else if (annotation.annotationType().isAnnotationPresent(Hook.class)) {232            return annotation.annotationType().getAnnotation(Hook.class);233        }234        return null;235    }236    private HookOptions getHookOptionsAnnotation(Annotation annotation) {237        if (annotation instanceof HookOptions) {238            return (HookOptions) annotation;239        } else if (annotation.annotationType().isAnnotationPresent(HookOptions.class)) {240            return annotation.annotationType().getAnnotation(HookOptions.class);241        }242        return null;243    }244    private void addHookDefinitions(Annotation[] annotations, List<HookDefinition<?>> hookDefinitions) {245        Hook currentHookAnnotation = null;246        HookOptions currentHookOptionAnnotation = null;247        Annotation currentAnnotation = null;248        for (Annotation annotation : annotations) {249            applyNoHook(hookDefinitions, annotation);250            Hook hookAnnotation = getHookAnnotation(annotation);251            if (hookAnnotation != null) {252                currentAnnotation = annotation;253            }254            if (hookAnnotation != null && currentHookAnnotation != null) {255                hookDefinitions.add(buildHookDefinition(currentHookAnnotation, currentHookOptionAnnotation, currentAnnotation));256                currentHookAnnotation = null;257                currentHookOptionAnnotation = null;258            }259            if (hookAnnotation != null) {260                currentHookAnnotation = hookAnnotation;261            }262            HookOptions hookOptionsAnnotation = getHookOptionsAnnotation(annotation);263            if (hookOptionsAnnotation != null) {264                if (currentHookOptionAnnotation != null) {265                    throw new FluentInjectException("Unexpected @HookOptions annotation. @Hook is missing.");266                }267                currentHookOptionAnnotation = hookOptionsAnnotation;268            }269        }270        if (currentHookAnnotation != null) {271            hookDefinitions.add(buildHookDefinition(currentHookAnnotation, currentHookOptionAnnotation, currentAnnotation));272        }273    }274    private void applyNoHook(List<HookDefinition<?>> hookDefinitions, Annotation annotation) {275        if (annotation instanceof NoHook) {276            Hook[] value = ((NoHook) annotation).value();277            if (ArrayUtils.isEmpty(value)) {278                hookDefinitions.clear();279            } else {280                List<? extends Class<? extends FluentHook<?>>> toRemove = Arrays.stream(value).map(Hook::value)281                        .collect(Collectors.toList());282                HookControlImpl.removeHooksFromDefinitions(hookDefinitions, toRemove.toArray(new Class[toRemove.size()]));283            }284        }285    }286    private <T> HookDefinition<T> buildHookDefinition(Hook hookAnnotation, HookOptions hookOptionsAnnotation,287            Annotation currentAnnotation) {288        Class<? extends T> hookOptionsClass =289                hookOptionsAnnotation == null ? null : (Class<? extends T>) hookOptionsAnnotation.value();290        T fluentHookOptions = null;291        if (hookOptionsClass != null) {292            try {293                fluentHookOptions = ReflectionUtils.newInstanceOptionalArgs(hookOptionsClass, currentAnnotation);294            } catch (NoSuchMethodException e) {295                throw new FluentInjectException("@HookOption class has no valid constructor", e);296            } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {297                throw new FluentInjectException("Can't create @HookOption class instance", e);298            }299        }300        Class<? extends FluentHook<T>> hookClass = (Class<? extends FluentHook<T>>) hookAnnotation.value();301        if (fluentHookOptions == null) {302            return new HookDefinition<>(hookClass);303        }304        return new HookDefinition<>(hookClass, fluentHookOptions);305    }306    private boolean isSupported(Object container, Field field) {307        return isValueNull(container, field) && !field.isAnnotationPresent(NoInject.class) && !Modifier...Source:DefaultHookChainBuilder.java  
...31        Supplier<WebElement> currentSupplier = elementSupplier;32        for (HookDefinition<?> hook : hooks) {33            FluentHook<?> newObject;34            try {35                newObject = newInstance(hook.getHookClass(), control, instantiator, currentSupplier, locator, toStringSupplier,36                        hook.getOptions());37            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {38                throw new HookException(e);39            }40            FluentHook<?> hookInstance = newObject;41            currentSupplier = () -> hookInstance;42            chain.add(hookInstance);43        }44        return chain;45    }46    /**47     * Creates a new hook instance.48     *49     * @param hookClass        hook class50     * @param fluentControl    control interface51     * @param instantiator     component instantiator52     * @param elementSupplier  element supplier53     * @param locatorSupplier  element locator supplier54     * @param toStringSupplier element toString supplier55     * @param options          hook options56     * @return new hook instance57     * @throws NoSuchMethodException     if a matching method is not found.58     * @throws IllegalAccessException    if this {@code Constructor} object59     *                                   is enforcing Java language access control and the underlying60     *                                   constructor is inaccessible.61     * @throws InstantiationException    if the class that declares the62     *                                   underlying constructor represents an abstract class.63     * @throws InvocationTargetException if the underlying constructor64     *                                   throws an exception.65     */66    protected FluentHook<?> newInstance(Class<? extends FluentHook<?>> hookClass, FluentControl fluentControl,67            ComponentInstantiator instantiator, Supplier<WebElement> elementSupplier, Supplier<ElementLocator> locatorSupplier,68            Supplier<String> toStringSupplier, Object options)69            throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {70        return ReflectionUtils71                .newInstance(hookClass, fluentControl, instantiator, elementSupplier, locatorSupplier, toStringSupplier, options);72    }73}newInstance
Using AI Code Generation
1package org.fluentlenium.core.hook;2import org.fluentlenium.core.hook.wait.WaitHook;3import org.fluentlenium.core.hook.wait.WaitHookBuilder;4public class DefaultHookChainBuilder implements HookChainBuilder {5    public void buildHookChain(HookChain chain) {6        chain.addHook(new WaitHookBuilder());7    }8}9package org.fluentlenium.core.hook;10import org.fluentlenium.core.hook.wait.WaitHook;11import org.fluentlenium.core.hook.wait.WaitHookBuilder;12public class DefaultHookChainBuilder implements HookChainBuilder {13    public void buildHookChain(HookChain chain) {14        chain.addHook(new WaitHookBuilder());15    }16}17package org.fluentlenium.core.hook;18import org.fluentlenium.core.hook.wait.WaitHook;19import org.fluentlenium.core.hook.wait.WaitHookBuilder;20public class DefaultHookChainBuilder implements HookChainBuilder {21    public void buildHookChain(HookChain chain) {22        chain.addHook(new WaitHookBuilder());23    }24}25package org.fluentlenium.core.hook;26import org.fluentlenium.core.hook.wait.WaitHook;27import org.fluentlenium.core.hook.wait.WaitHookBuilder;28public class DefaultHookChainBuilder implements HookChainBuilder {29    public void buildHookChain(HookChain chain) {30        chain.addHook(new WaitHookBuilder());31    }32}33package org.fluentlenium.core.hook;34import org.fluentlenium.core.hook.wait.WaitHook;35import org.fluentlenium.core.hook.wait.WaitHookBuilder;36public class DefaultHookChainBuilder implements HookChainBuilder {37    public void buildHookChain(HookChain chain) {38        chain.addHook(new WaitHookBuilder());39    }40}newInstance
Using AI Code Generation
1package org.fluentlenium.core.hook;2import java.lang.reflect.Constructor;3import java.lang.reflect.InvocationTargetException;4public class DefaultHookChainBuilder {5    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {6        Class hookChainBuilderClass = Class.forName("org.fluentlenium.core.hook.HookChainBuilder");7        Constructor<?> hookChainBuilderConstructor = hookChainBuilderClass.getDeclaredConstructor();8        hookChainBuilderConstructor.setAccessible(true);9        Object hookChainBuilderClassInstance = hookChainBuilderConstructor.newInstance();10    }11}12package org.fluentlenium.core.hook;13import java.lang.reflect.Constructor;14import java.lang.reflect.InvocationTargetException;15public class HookChainBuilder {16    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {17        Class hookChainBuilderClass = Class.forName("org.fluentlenium.core.hook.HookChainBuilder");18        Constructor<?> hookChainBuilderConstructor = hookChainBuilderClass.getDeclaredConstructor();19        hookChainBuilderConstructor.setAccessible(true);20        Object hookChainBuilderClassInstance = hookChainBuilderConstructor.newInstance();21    }22}23package org.fluentlenium.core.hook;24import java.lang.reflect.Constructor;25import java.lang.reflect.InvocationTargetException;26public class HookDefinition {27    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {28        Class hookDefinitionClass = Class.forName("org.fluentlenium.core.hook.HookDefinition");29        Constructor<?> hookDefinitionConstructor = hookDefinitionClass.getDeclaredConstructor();30        hookDefinitionConstructor.setAccessible(true);31        Object hookDefinitionClassInstance = hookDefinitionConstructor.newInstance();32    }33}34package org.fluentlenium.core.hook;35import java.lang.reflect.Constructor;36import java.lang.reflect.InvocationTargetException;37public class HookDefinitionFactory {38    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {39        Class hookDefinitionFactoryClass = Class.forName("newInstance
Using AI Code Generation
1package org.fluentlenium.core.hook;2import java.lang.reflect.InvocationTargetException;3import java.lang.reflect.Method;4import java.lang.reflect.Modifier;5import java.util.ArrayList;6import java.util.Arrays;7import java.util.List;8import java.util.stream.Collectors;9import java.util.stream.Stream;10public class DefaultHookChainBuilder {11    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {12        Class<?> clazz = DefaultHookChainBuilder.class;13        Method newInstance = clazz.getDeclaredMethod("newInstance");14        newInstance.setAccessible(true);15        DefaultHookChainBuilder builder = (DefaultHookChainBuilder) newInstance.invoke(null);16        System.out.println(builder);17    }18    private static DefaultHookChainBuilder newInstance() throws InstantiationException, IllegalAccessException {19        DefaultHookChainBuilder builder = DefaultHookChainBuilder.class.newInstance();20        return builder;21    }22}23package org.fluentlenium.core.hook;24import java.lang.reflect.InvocationTargetException;25import java.lang.reflect.Method;26import java.lang.reflect.Modifier;27import java.util.ArrayList;28import java.util.Arrays;29import java.util.List;30import java.util.stream.Collectors;31import java.util.stream.Stream;32public class DefaultHookChainBuilder {33    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {34        Class<?> clazz = DefaultHookChainBuilder.class;35        Method newInstance = clazz.getDeclaredMethod("newInstance");36        newInstance.setAccessible(true);37        DefaultHookChainBuilder builder = (DefaultHookChainBuilder) newInstance.invoke(null);38        System.out.println(builder);39    }40    private static DefaultHookChainBuilder newInstance() throws InstantiationException, IllegalAccessException {41        DefaultHookChainBuilder builder = DefaultHookChainBuilder.class.newInstance();42        return builder;43    }44}45package org.fluentlenium.core.hook;46import java.lang.reflect.InvocationTargetException;47import java.lang.reflect.Method;48import java.lang.reflect.Modifier;49import java.util.ArrayList;50import java.util.Arrays;51import java.util.List;52import java.util.stream.Collectors;53import java.util.stream.Stream;54public class DefaultHookChainBuilder {55    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {newInstance
Using AI Code Generation
1package org.fluentlenium.core.hook;2import org.fluentlenium.core.hook.wait.WaitHook;3import org.openqa.selenium.WebDriver;4import java.util.LinkedList;5import java.util.List;6public class DefaultHookChainBuilder implements HookChainBuilder {7    private final WebDriver driver;8    public DefaultHookChainBuilder(final WebDriver driver) {9        this.driver = driver;10    }11    public List<Hook> build() {12        List<Hook> hooks = new LinkedList<>();13        hooks.add(new WaitHook(driver));14        return hooks;15    }16}17package org.fluentlenium.core.hook;18import org.fluentlenium.core.hook.wait.WaitHook;19import org.openqa.selenium.WebDriver;20import java.util.LinkedList;21import java.util.List;22public class DefaultHookChainBuilder implements HookChainBuilder {23    private final WebDriver driver;24    public DefaultHookChainBuilder(final WebDriver driver) {25        this.driver = driver;26    }27    public List<Hook> build() {28        List<Hook> hooks = new LinkedList<>();29        hooks.add(new WaitHook(driver));30        return hooks;31    }32}33package org.fluentlenium.core.hook;34import org.fluentlenium.core.hook.wait.WaitHook;35import org.openqa.selenium.WebDriver;36import java.util.LinkedList;37import java.util.List;38public class DefaultHookChainBuilder implements HookChainBuilder {39    private final WebDriver driver;40    public DefaultHookChainBuilder(final WebDriver driver) {41        this.driver = driver;42    }43    public List<Hook> build() {44        List<Hook> hooks = new LinkedList<>();45        hooks.add(new WaitHook(driver));46        return hooks;47    }48}49package org.fluentlenium.core.hook;50import org.fluentlenium.core.hook.wait.WaitHook;51import org.openqa.selenium.WebDriver;52import java.util.LinkedList;53import java.util.List;54public class DefaultHookChainBuilder implements HookChainBuilder {55    private final WebDriver driver;56    public DefaultHookChainBuilder(final WebDriver driver) {57        this.driver = driver;58    }newInstance
Using AI Code Generation
1package com.fluentlenium.tutorial;2import org.fluentlenium.core.hook.DefaultHookChainBuilder;3import org.fluentlenium.core.hook.HookChainBuilder;4public class HookChainBuilderDemo {5    public static void main(String[] args) {6        HookChainBuilder hookChainBuilder = new DefaultHookChainBuilder();7        System.out.println("8");9        System.out.println("Class name of HookChainBuilder object is: " + hookChainBuilder.getClass().getName());10    }11}newInstance
Using AI Code Generation
1package com.puppycrawl.tools.checkstyle.checks.coding;2import org.fluentlenium.core.hook.DefaultHookChainBuilder;3public class InputUseDefaultHookChainBuilderNewInstance {4    public void test() {5        DefaultHookChainBuilder chainBuilder = new DefaultHookChainBuilder();6        chainBuilder.newInstance();7    }8}9 package com.puppycrawl.tools.checkstyle.checks.coding;10-import com.puppycrawl.tools.checkstyle.api.AbstractCheck;11+import com.puppycrawl.tools.checkstyle.api.AbstractCheck;12 import com.puppycrawl.tools.checkstyle.api.DetailAST;13 import com.puppycrawl.tools.checkstyle.api.TokenTypes;14@@ -8,12 +8,11 @@ import com.puppycrawl.tools.checkstyle.api.TokenTypes;15 public class UseDefaultHookChainBuilderNewInstanceCheck extends AbstractCheck {16-    private static final String MSG_KEY = "use.newInstance";17     public int[] getDefaultTokens() {18         return new int[] {19         };20     }21@@ -21,13 +20,14 @@ public class UseDefaultHookChainBuilderNewInstanceCheck extends AbstractCheck {22     public int[] getRequiredTokens() {23         return getDefaultTokens();24     }25     public void visitToken(DetailAST ast) {26         if (ast.getType() == TokenTypes.DOT) {27             final DetailAST dot = ast;28             final DetailAST dotChild = dot.getFirstChild();29-            if (dotChild.getType() == TokenTypes.IDENT30-                    && "newInstance".equals(dotChild.getText())) {31+            if (dotChild.getType() ==newInstance
Using AI Code Generation
1package org.fluentlenium.core.hook;2import org.fluentlenium.core.hook.wait.WaitHook;3import org.fluentlenium.core.hook.wait.WaitHookBuilder;4import org.fluentlenium.core.hook.wait.WaitHookChainBuilder;5import java.lang.reflect.InvocationTargetException;6import java.lang.reflect.Method;7public class DefaultHookChainBuilder {8    public static void main(String[] args) {9        try {10            Class cls = Class.forName("org.fluentlenium.core.hook.DefaultHookChainBuilder");11            Method method = cls.getDeclaredMethod("newInstance");12            method.setAccessible(true);13            WaitHookChainBuilder obj = (WaitHookChainBuilder) method.invoke(cls.newInstance());14            System.out.println(obj);15        } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {16            e.printStackTrace();17        }18    }19}newInstance
Using AI Code Generation
1package com.puppycrawl.tools.checkstyle.checks.coding;2public class InputFluentLeniumHookChainBuilder {3    public void test() throws Exception {4        Class<?> clazz = Class.forName("org.fluentlenium.core.hook.DefaultHookChainBuilder");5        clazz.newInstance();6    }7}Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
