How to use expectedBasePath method in stryker-parent

Best JavaScript code snippet using stryker-parent

named-parameter-substitution.spec.ts

Source:named-parameter-substitution.spec.ts Github

copy

Full Screen

1/*2 * Copyright (c) 2018-2020 Swiss Federal Railways3 *4 * This program and the accompanying materials are made5 * available under the terms of the Eclipse Public License 2.06 * which is available at https://www.eclipse.org/legal/epl-2.0/7 *8 * SPDX-License-Identifier: EPL-2.09 */10import {MicrofrontendPlatform} from '../../microfrontend-platform';11import {RouterOutlets} from './router-outlet.element';12import {OutletRouter} from './outlet-router';13import {NavigationOptions} from './metadata';14import {expectPromise} from '../../testing/spec.util.spec';15import {UUID} from '@scion/toolkit/uuid';16import {mapToBody} from '../../messaging.model';17import {Beans} from '@scion/toolkit/bean-manager';18import {MessageClient} from '../messaging/message-client';19import {firstValueFrom} from 'rxjs';20describe('OutletRouter', () => {21 describe('Named parameter substitution', () => {22 beforeAll(async () => await MicrofrontendPlatform.startHost({applications: []}));23 afterAll(async () => await MicrofrontendPlatform.destroy());24 describe('absolute URL (hash-based routing)', () => testSubstitution('http://localhost:4200/#/', {expectedBasePath: 'http://localhost:4200/#/'}));25 describe('absolute URL (push-state routing)', () => testSubstitution('http://localhost:4200/', {expectedBasePath: 'http://localhost:4200/'}));26 describe('relative URL (hash-based routing)', () => testSubstitution('/', {expectedBasePath: 'http://localhost:4200/#/', relativeTo: 'http://localhost:4200/#/a/b/c'}));27 describe('relative URL (push-based routing)', () => testSubstitution('/', {expectedBasePath: 'http://localhost:4200/', relativeTo: 'http://localhost:4200/a/b/c'}));28 function testSubstitution(basePath: string, options: {relativeTo?: string; expectedBasePath: string}): void {29 it('should substitute a named path param', async () => {30 const url = navigate(`${basePath}order/:id`, {31 params: new Map().set('id', 123),32 relativeTo: options.relativeTo,33 });34 await expectPromise(url).toResolve(`${options.expectedBasePath}order/123`);35 });36 it('should substitute multiple named path params (1)', async () => {37 const url = navigate(`${basePath}order/:orderId/product/:productId`, {38 params: new Map().set('orderId', 123).set('productId', 456),39 relativeTo: options.relativeTo,40 });41 await expectPromise(url).toResolve(`${options.expectedBasePath}order/123/product/456`);42 });43 it('should substitute multiple named path params (2)', async () => {44 const url = navigate(`${basePath}order/:orderId/product/:productId/vendor`, {45 params: new Map().set('orderId', 123).set('productId', 456),46 relativeTo: options.relativeTo,47 });48 await expectPromise(url).toResolve(`${options.expectedBasePath}order/123/product/456/vendor`);49 });50 it('should substitute a named query param', async () => {51 const url = navigate(`${basePath}order/:orderId?product=:productId`, {52 params: new Map().set('orderId', 123).set('productId', 456),53 relativeTo: options.relativeTo,54 });55 await expectPromise(url).toResolve(`${options.expectedBasePath}order/123?product=456`);56 });57 it('should substitute multiple named query params', async () => {58 const url = navigate(`${basePath}order/:orderId?product=:productId&stock=:stock`, {59 params: new Map().set('orderId', 123).set('productId', 456).set('stock', 5),60 relativeTo: options.relativeTo,61 });62 await expectPromise(url).toResolve(`${options.expectedBasePath}order/123?product=456&stock=5`);63 });64 it('should substitute multiple named query params (2)', async () => {65 const url = navigate(`${basePath}order/:orderId?product=:productId&stock=:stock&vendor=true`, {66 params: new Map().set('orderId', 123).set('productId', 456).set('stock', 5),67 relativeTo: options.relativeTo,68 });69 await expectPromise(url).toResolve(`${options.expectedBasePath}order/123?product=456&stock=5&vendor=true`);70 });71 it('should substitute a named matrix param', async () => {72 const url = navigate(`${basePath}order/:orderId;product=:productId`, {73 params: new Map().set('orderId', 123).set('productId', 456),74 relativeTo: options.relativeTo,75 });76 await expectPromise(url).toResolve(`${options.expectedBasePath}order/123;product=456`);77 });78 it('should substitute multiple named matrix params', async () => {79 const url = navigate(`${basePath}order/:orderId;product=:productId;stock=:stock`, {80 params: new Map().set('orderId', 123).set('productId', 456).set('stock', 5),81 relativeTo: options.relativeTo,82 });83 await expectPromise(url).toResolve(`${options.expectedBasePath}order/123;product=456;stock=5`);84 });85 it('should substitute multiple named matrix params (2)', async () => {86 const url = navigate(`${basePath}order/:orderId;product=:productId;stock=:stock;vendor=true`, {87 params: new Map().set('orderId', 123).set('productId', 456).set('stock', 5),88 relativeTo: options.relativeTo,89 });90 await expectPromise(url).toResolve(`${options.expectedBasePath}order/123;product=456;stock=5;vendor=true`);91 });92 it('should substitute a named fragment param (1)', async () => {93 const url = navigate(`${basePath}order/:orderId#:fragment`, {94 params: new Map().set('orderId', 123).set('productId', 456).set('fragment', 'abc'),95 relativeTo: options.relativeTo,96 });97 await expectPromise(url).toResolve(`${options.expectedBasePath}order/123#abc`);98 });99 it('should substitute a named fragment param (2)', async () => {100 const url = navigate(`${basePath}order/:orderId#fragment:fragment`, {101 params: new Map().set('orderId', 123).set('productId', 456).set('fragment', 'abc'),102 relativeTo: options.relativeTo,103 });104 await expectPromise(url).toResolve(`${options.expectedBasePath}order/123#fragmentabc`);105 });106 it('should substitute named path params, named query params, named matrix params and named fragment params', async () => {107 const url = navigate(`${basePath}a/:param1/b/:param2;mp1=:param3;mp2=:param4;mp3=:param1;m4=static?qp1=:param5&qp2=:param6&qp3=static#frag_:param7`, {108 params: new Map()109 .set('param1', 'PARAM1')110 .set('param2', 'PARAM2')111 .set('param3', 'PARAM3')112 .set('param4', 'PARAM4')113 .set('param5', 'PARAM5')114 .set('param6', 'PARAM6')115 .set('param7', 'PARAM7'),116 relativeTo: options.relativeTo,117 });118 await expectPromise(url).toResolve(`${options.expectedBasePath}a/PARAM1/b/PARAM2;mp1=PARAM3;mp2=PARAM4;mp3=PARAM1;m4=static?qp1=PARAM5&qp2=PARAM6&qp3=static#frag_PARAM7`);119 });120 it('should substitute falsy params', async () => {121 const url = navigate(`${basePath}a?0=:0&false=:false&null=:null&undefined=:undefined`, {122 params: new Map()123 .set('0', 0)124 .set('false', false)125 .set('null', null)126 .set('undefined', undefined),127 relativeTo: options.relativeTo,128 });129 await expectPromise(url).toResolve(`${options.expectedBasePath}a?0=0&false=false&null=null`);130 });131 it('should format array values as comma-separated list (query param) (1)', async () => {132 const url = navigate(`${basePath}order?array=:array`, {133 params: new Map().set('array', ['a', 'b', 'c']),134 relativeTo: options.relativeTo,135 });136 await expectPromise(url).toResolve(`${options.expectedBasePath}order?array=a,b,c`);137 });138 it('should format array values as comma-separated list (query param) (2)', async () => {139 const url = navigate(`${basePath}order?array=:array&a=b`, {140 params: new Map().set('array', ['a', 'b', 'c']),141 relativeTo: options.relativeTo,142 });143 await expectPromise(url).toResolve(`${options.expectedBasePath}order?array=a,b,c&a=b`);144 });145 it('should format array values as comma-separated list (matrix param) (1)', async () => {146 const url = navigate(`${basePath}order;array=:array`, {147 params: new Map().set('array', ['a', 'b', 'c']),148 relativeTo: options.relativeTo,149 });150 await expectPromise(url).toResolve(`${options.expectedBasePath}order;array=a,b,c`);151 });152 it('should format array values as comma-separated list (matrix param) (2)', async () => {153 const url = navigate(`${basePath}order;array=:array;a=b`, {154 params: new Map().set('array', ['a', 'b', 'c']),155 relativeTo: options.relativeTo,156 });157 await expectPromise(url).toResolve(`${options.expectedBasePath}order;array=a,b,c;a=b`);158 });159 it('should not remove missing path params (1)', async () => {160 const url = navigate(`${basePath}:a/b/c`, {161 relativeTo: options.relativeTo,162 });163 await expectPromise(url).toResolve(`${options.expectedBasePath}:a/b/c`);164 });165 it('should not remove missing path params (2)', async () => {166 const url = navigate(`${basePath}a/:b/c`, {167 relativeTo: options.relativeTo,168 });169 await expectPromise(url).toResolve(`${options.expectedBasePath}a/:b/c`);170 });171 it('should not remove missing path params (3)', async () => {172 const url = navigate(`${basePath}a/b/:c`, {173 relativeTo: options.relativeTo,174 });175 await expectPromise(url).toResolve(`${options.expectedBasePath}a/b/:c`);176 });177 it('should not remove missing path params (4)', async () => {178 const url = navigate(`${basePath}a/b/:c?a=b`, {179 relativeTo: options.relativeTo,180 });181 await expectPromise(url).toResolve(`${options.expectedBasePath}a/b/:c?a=b`);182 });183 it('should not remove missing path params (5)', async () => {184 const url = navigate(`${basePath}a/b/:c;a=b`, {185 relativeTo: options.relativeTo,186 });187 await expectPromise(url).toResolve(`${options.expectedBasePath}a/b/:c;a=b`);188 });189 it('should remove missing query params (1)', async () => {190 const url = navigate(`${basePath}order?qp1=:qp1&qp2=qp2`, {191 params: new Map().set('qp1', 'QP1'),192 relativeTo: options.relativeTo,193 });194 await expectPromise(url).toResolve(`${options.expectedBasePath}order?qp1=QP1&qp2=qp2`);195 });196 it('should remove missing query params (2a)', async () => {197 const url = navigate(`${basePath}order?qp1=:qp1&qp2=qp2`, {198 params: new Map(),199 relativeTo: options.relativeTo,200 });201 await expectPromise(url).toResolve(`${options.expectedBasePath}order?qp2=qp2`);202 });203 it('should remove missing query params (2b)', async () => {204 const url = navigate(`${basePath}order?qp1=:qp1&qp2=qp2`, {205 params: new Map().set('qp1', undefined),206 relativeTo: options.relativeTo,207 });208 await expectPromise(url).toResolve(`${options.expectedBasePath}order?qp2=qp2`);209 });210 it('should remove missing query params (3)', async () => {211 const url = navigate(`${basePath}order?qp1=qp1&qp2=:qp2`, {212 params: new Map(),213 relativeTo: options.relativeTo,214 });215 await expectPromise(url).toResolve(`${options.expectedBasePath}order?qp1=qp1`);216 });217 it('should remove missing query params (4)', async () => {218 const url = navigate(`${basePath}order?qp1=qp1&qp2=:qp2&qp3=qp3`, {219 params: new Map(),220 relativeTo: options.relativeTo,221 });222 await expectPromise(url).toResolve(`${options.expectedBasePath}order?qp1=qp1&qp3=qp3`);223 });224 it('should remove missing query params (5)', async () => {225 const url = navigate(`${basePath}order?qp1=:qp1&qp2=:qp2&qp3=:qp3`, {226 params: new Map(),227 relativeTo: options.relativeTo,228 });229 await expectPromise(url).toResolve(`${options.expectedBasePath}order`);230 });231 it('should remove missing query params (6)', async () => {232 const url = navigate(`${basePath}order?qp1=:qp1&qp2=:qp2&qp3=:qp3`, {233 params: new Map().set('qp1', 'QP1').set('qp2', 'QP2'),234 relativeTo: options.relativeTo,235 });236 await expectPromise(url).toResolve(`${options.expectedBasePath}order?qp1=QP1&qp2=QP2`);237 });238 it('should remove missing query params (7)', async () => {239 const url = navigate(`${basePath}order?qp1=:qp1&qp2=:qp2#fragment`, {240 params: new Map().set('qp1', 'QP1'),241 relativeTo: options.relativeTo,242 });243 await expectPromise(url).toResolve(`${options.expectedBasePath}order?qp1=QP1#fragment`);244 });245 it('should remove missing query params (8)', async () => {246 const url = navigate(`${basePath}order?qp1=:qp1&qp2=:qp2#fragment`, {247 params: new Map().set('qp2', 'QP2'),248 relativeTo: options.relativeTo,249 });250 await expectPromise(url).toResolve(`${options.expectedBasePath}order?qp2=QP2#fragment`);251 });252 it('should remove missing query params (9)', async () => {253 const url = navigate(`${basePath}order?qp1=:qp1&qp2=:qp2#fragment`, {254 params: new Map(),255 relativeTo: options.relativeTo,256 });257 await expectPromise(url).toResolve(`${options.expectedBasePath}order#fragment`);258 });259 it('should remove missing matrix params (1)', async () => {260 const url = navigate(`${basePath}order;mp1=:mp1;mp2=mp2`, {261 params: new Map().set('mp1', 'MP1'),262 relativeTo: options.relativeTo,263 });264 await expectPromise(url).toResolve(`${options.expectedBasePath}order;mp1=MP1;mp2=mp2`);265 });266 it('should remove missing matrix params (2a)', async () => {267 const url = navigate(`${basePath}order;mp1=:mp1;mp2=mp2`, {268 params: new Map(),269 relativeTo: options.relativeTo,270 });271 await expectPromise(url).toResolve(`${options.expectedBasePath}order;mp2=mp2`);272 });273 it('should remove missing matrix params (2b)', async () => {274 const url = navigate(`${basePath}order;mp1=:mp1;mp2=mp2`, {275 params: new Map().set('mp1', undefined),276 relativeTo: options.relativeTo,277 });278 await expectPromise(url).toResolve(`${options.expectedBasePath}order;mp2=mp2`);279 });280 it('should remove missing matrix params (3)', async () => {281 const url = navigate(`${basePath}order;mp1=mp1;mp2=:mp2`, {282 params: new Map(),283 relativeTo: options.relativeTo,284 });285 await expectPromise(url).toResolve(`${options.expectedBasePath}order;mp1=mp1`);286 });287 it('should remove missing matrix params (4)', async () => {288 const url = navigate(`${basePath}order;mp1=mp1;mp2=:mp2;mp3=mp3`, {289 params: new Map(),290 relativeTo: options.relativeTo,291 });292 await expectPromise(url).toResolve(`${options.expectedBasePath}order;mp1=mp1;mp3=mp3`);293 });294 it('should remove missing matrix params (5)', async () => {295 const url = navigate(`${basePath}order;mp1=:mp1;mp2=:mp2;mp3=:mp3`, {296 params: new Map(),297 relativeTo: options.relativeTo,298 });299 await expectPromise(url).toResolve(`${options.expectedBasePath}order`);300 });301 it('should remove missing matrix params (6)', async () => {302 const url = navigate(`${basePath}order;mp1=:mp1;mp2=:mp2;mp3=:mp3`, {303 params: new Map().set('mp1', 'MP1').set('mp2', 'MP2'),304 relativeTo: options.relativeTo,305 });306 await expectPromise(url).toResolve(`${options.expectedBasePath}order;mp1=MP1;mp2=MP2`);307 });308 it('should remove missing matrix params (7)', async () => {309 const url = navigate(`${basePath}order;mp1=:mp1;mp2=:mp2#fragment`, {310 params: new Map().set('mp1', 'MP1'),311 relativeTo: options.relativeTo,312 });313 await expectPromise(url).toResolve(`${options.expectedBasePath}order;mp1=MP1#fragment`);314 });315 it('should remove missing matrix params (8)', async () => {316 const url = navigate(`${basePath}order;mp1=:mp1;mp2=:mp2#fragment`, {317 params: new Map().set('mp2', 'MP2'),318 relativeTo: options.relativeTo,319 });320 await expectPromise(url).toResolve(`${options.expectedBasePath}order;mp2=MP2#fragment`);321 });322 it('should remove missing matrix params (9)', async () => {323 const url = navigate(`${basePath}order;mp1=:mp1;mp2=:mp2#fragment`, {324 params: new Map(),325 relativeTo: options.relativeTo,326 });327 await expectPromise(url).toResolve(`${options.expectedBasePath}order#fragment`);328 });329 it('should remove missing matrix params (10)', async () => {330 const url = navigate(`${basePath}order;mp1=:mp1;mp2=:mp2?a=b`, {331 params: new Map(),332 relativeTo: options.relativeTo,333 });334 await expectPromise(url).toResolve(`${options.expectedBasePath}order?a=b`);335 });336 it('should remove missing matrix params (11)', async () => {337 const url = navigate(`${basePath}order;mp1=:mp1;mp2=:mp2#fragment`, {338 params: new Map(),339 relativeTo: options.relativeTo,340 });341 await expectPromise(url).toResolve(`${options.expectedBasePath}order#fragment`);342 });343 it('should remove missing matrix params (12)', async () => {344 const url = navigate(`${basePath}order;mp1=:mp1;mp2=:mp2?qp1=:qp1&qp2=:qp2#fragment`, {345 params: new Map(),346 relativeTo: options.relativeTo,347 });348 await expectPromise(url).toResolve(`${options.expectedBasePath}order#fragment`);349 });350 it('should remove missing matrix params (13)', async () => {351 const url = navigate(`${basePath}order;mp1=:mp1;mp2=:mp2?qp1=:qp1&qp2=:qp2#fragment`, {352 params: new Map().set('qp2', 'QP2'),353 relativeTo: options.relativeTo,354 });355 await expectPromise(url).toResolve(`${options.expectedBasePath}order?qp2=QP2#fragment`);356 });357 it('should remove missing matrix params (14)', async () => {358 const url = navigate(`${basePath}a/:b;mp1=:mp1;mp2=mp2/c`, {359 params: new Map(),360 relativeTo: options.relativeTo,361 });362 await expectPromise(url).toResolve(`${options.expectedBasePath}a/:b;mp2=mp2/c`);363 });364 it('should remove missing matrix params (15)', async () => {365 const url = navigate(`${basePath}a/:b;mp1=:mp1;mp2=mp2/c`, {366 params: new Map().set('b', 'b'),367 relativeTo: options.relativeTo,368 });369 await expectPromise(url).toResolve(`${options.expectedBasePath}a/b;mp2=mp2/c`);370 });371 it('should remove missing matrix params (16)', async () => {372 const url = navigate(`${basePath}a/:b;mp1=:mp1;mp2=:mp2/c`, {373 params: new Map(),374 relativeTo: options.relativeTo,375 });376 await expectPromise(url).toResolve(`${options.expectedBasePath}a/:b/c`);377 });378 it('should remove missing matrix params (17)', async () => {379 const url = navigate(`${basePath}a/:b;mp1=:mp1/c`, {380 params: new Map(),381 relativeTo: options.relativeTo,382 });383 await expectPromise(url).toResolve(`${options.expectedBasePath}a/:b/c`);384 });385 it('should remove missing matrix params (18)', async () => {386 const url = navigate(`${basePath}a/:b;mp1=:mp1`, {387 params: new Map(),388 relativeTo: options.relativeTo,389 });390 await expectPromise(url).toResolve(`${options.expectedBasePath}a/:b`);391 });392 it('should remove missing matrix params (19)', async () => {393 const url = navigate(`${basePath}a/:b;mp1=:mp1`, {394 params: new Map().set('mp1', 'MP1'),395 relativeTo: options.relativeTo,396 });397 await expectPromise(url).toResolve(`${options.expectedBasePath}a/:b;mp1=MP1`);398 });399 }400 async function navigate(url: string, navigationOptions: NavigationOptions): Promise<string> {401 const outlet = UUID.randomUUID();402 // Navigate to the given URL403 await Beans.get(OutletRouter).navigate(url, {...navigationOptions, outlet});404 // Lookup the navigated URL405 return firstValueFrom(Beans.get(MessageClient).observe$<string>(RouterOutlets.urlTopic(outlet)).pipe(mapToBody<string>()));406 }407 });...

Full Screen

Full Screen

index.test.ts

Source:index.test.ts Github

copy

Full Screen

1import { createMajorVersionNumber, createHandlerBasePath } from '../../../src/utils';2describe("'Utils' file", () => {3 let SEMVER_VERSION_NUMBER;4 let expectedVersionNumber;5 let expectedBasePath;6 beforeEach(() => {7 SEMVER_VERSION_NUMBER = '1.0.0';8 expectedVersionNumber = createMajorVersionNumber(SEMVER_VERSION_NUMBER);9 expectedBasePath = createHandlerBasePath(expectedVersionNumber);10 });11 describe("'createMajorVersionNumber' function", () => {12 it('should return the major version when a version number following semver is passed', () => {13 expect(SEMVER_VERSION_NUMBER).toMatch(/^(\d+\.)?(\d+\.)?(\*|\d+)$/);14 expect(expectedVersionNumber).toBe('1');15 expect(expectedVersionNumber).not.toBe('1.0.0');16 });17 });18 describe("'createHandlerBasePath' function", () => {19 it("should return the basePath as '/v<x>' where 'x' is a major version number when a number is given", () => {20 expect(expectedBasePath).toBe('v1');21 expect(expectedVersionNumber).not.toBe('v1.0.0');22 });23 });...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const expectedBasePath = require('stryker-parent').expectedBasePath;2const expectedBasePath = require('stryker-parent').expectedBasePath;3const expectedBasePath = require('stryker-parent').expectedBasePath;4const expectedBasePath = require('stryker-parent').expectedBasePath;5const expectedBasePath = require('stryker-parent').expectedBasePath;6const expectedBasePath = require('stryker-parent').expectedBasePath;7const expectedBasePath = require('stryker-parent').expectedBasePath;8const expectedBasePath = require('stryker-parent').expectedBasePath;9const expectedBasePath = require('stryker-parent').expectedBasePath;10const expectedBasePath = require('stryker-parent').expectedBasePath;11const expectedBasePath = require('stryker-parent').expectedBasePath;12const expectedBasePath = require('stryker-parent').expectedBasePath;13const expectedBasePath = require('stryker-parent').expectedBasePath;14const expectedBasePath = require('stryker-parent').expectedBasePath;15const expectedBasePath = require('stryker-parent').expectedBasePath;

Full Screen

Using AI Code Generation

copy

Full Screen

1var strykerParent = require('stryker-parent');2var expectedBasePath = strykerParent.expectedBasePath;3var path = require('path');4var expectedPath = expectedBasePath('test.js');5console.log(expectedPath);6var strykerParent = require('stryker-parent');7var expectedBasePath = strykerParent.expectedBasePath;8var path = require('path');9var expectedPath = expectedBasePath('test.js');10console.log(expectedPath);11var strykerParent = require('stryker-parent');12var expectedBasePath = strykerParent.expectedBasePath;13var path = require('path');14var expectedPath = expectedBasePath('test.js');15console.log(expectedPath);16var strykerParent = require('stryker-parent');17var expectedBasePath = strykerParent.expectedBasePath;18var path = require('path');19var expectedPath = expectedBasePath('test.js');20console.log(expectedPath);21var strykerParent = require('stryker-parent');22var expectedBasePath = strykerParent.expectedBasePath;23var path = require('path');24var expectedPath = expectedBasePath('test.js');25console.log(expectedPath);

Full Screen

Using AI Code Generation

copy

Full Screen

1var expectedBasePath = require('stryker-parent').expectedBasePath;2var expectedPath = expectedBasePath('src');3console.log(expectedPath);4module.exports = function(config) {5 config.set({6 karma: {7 config: {8 { pattern: 'test.js', mutated: false, included: true }9 }10 }11 });12};13module.exports = function(config) {14 config.set({15 preprocessors: {},16 });17};

Full Screen

Automation Testing Tutorials

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.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run stryker-parent 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