Best JavaScript code snippet using wpt
PLENControlServerService.ts
Source:PLENControlServerService.ts
1enum SERVER_STATE2{3 DISCONNECTED,4 CONNECTED,5 WAITING6};7class PLENControlServerService8{9 private _state: SERVER_STATE = SERVER_STATE.DISCONNECTED;10 private _ip_addr: string;11 private _socket: WebSocket = null;12 static $inject = [13 '$q',14 '$http',15 '$modal',16 '$rootScope',17 'SharedThreeService'18 ];19 constructor(20 private _$q: ng.IQService,21 private _$http: ng.IHttpService,22 private _$modal: angular.ui.bootstrap.IModalService,23 private _$rootScope: ng.IRootScopeService,24 private _three: ThreeModel25 )26 {27 this._$rootScope.$on("SyncBegin", () => { this.onSyncBegin(); });28 this._$rootScope.$on("SyncEnd", () => { this.onSyncEnd(); });29 this._$rootScope.$on("3DModelReset", () =>30 {31 if (!_.isNull(this._socket))32 {33 _.each(this._three.rotation_axes, (axis: THREE.Object3D, index: number) =>34 {35 this._socket.send('applyDiff/' + axis.name + '/0');36 });37 }38 });39 this._$rootScope.$on("FrameLoadFinished", () =>40 {41 if (!_.isNull(this._socket))42 {43 _.each(this._three.rotation_axes, (axis: THREE.Object3D, index: number) =>44 {45 this._socket.send('applyDiff/' + axis.name + '/' + this._three.getDiffAngle(axis, index).toString());46 });47 }48 });49 }50 checkServerVersion(): void51 {52 this._$http.get("//" + this._ip_addr + "/connect")53 .success(() =>54 {55 alert("Your control-server's version is old. Please use latest version.");56 })57 .error(() =>58 {59 alert("The control-server hasn't run.");60 });61 }62 connect(success_callback = null): void63 {64 if (this._state === SERVER_STATE.DISCONNECTED)65 {66 var modal = this._$modal.open({67 controller: PLENControlServerModalController,68 controllerAs: "$ctrl",69 templateUrl: "./angularjs/components/PLENControlServerModal/view.html"70 });71 modal.result.then((ip_addr: string) =>72 {73 this._state = SERVER_STATE.WAITING;74 this._ip_addr = ip_addr;75 this._$http.get("//" + this._ip_addr + "/v2/connect")76 .success((response: any) =>77 {78 if (response.data.result === true)79 {80 this._state = SERVER_STATE.CONNECTED;81 if (!_.isNull(success_callback))82 {83 success_callback();84 }85 }86 else87 {88 this._state = SERVER_STATE.DISCONNECTED;89 alert("USB connection was disconnected!");90 this._$rootScope.$broadcast("SyncEnd");91 }92 })93 .error(() =>94 {95 this._state = SERVER_STATE.DISCONNECTED;96 this.checkServerVersion();97 });98 });99 }100 }101 disconnect(success_callback = null): void102 {103 if (this._state === SERVER_STATE.CONNECTED)104 {105 this._state = SERVER_STATE.WAITING;106 this._$http.get("//" + this._ip_addr + "/v2/disconnect")107 .success((response: any) =>108 {109 if (response.data.result === true)110 {111 if (!_.isNull(success_callback))112 {113 success_callback();114 }115 }116 this._state = SERVER_STATE.DISCONNECTED;117 this._$rootScope.$broadcast("SyncEnd");118 })119 .error(() =>120 {121 this._state = SERVER_STATE.CONNECTED;122 });123 }124 }125 install(json, success_callback = null): void126 {127 if (this._state === SERVER_STATE.CONNECTED)128 {129 this._state = SERVER_STATE.WAITING;130 this._$http.put("//" + this._ip_addr + "/v2/motions/" + json.slot.toString(), json)131 .success((response: any) =>132 {133 this._state = SERVER_STATE.CONNECTED;134 if (response.data.result === true)135 {136 if (!_.isNull(success_callback))137 {138 success_callback();139 }140 }141 else142 {143 this._state = SERVER_STATE.DISCONNECTED;144 alert("USB connection was disconnected!");145 this._$rootScope.$broadcast("SyncEnd");146 }147 })148 .error(() =>149 {150 this._state = SERVER_STATE.DISCONNECTED;151 })152 .finally(() =>153 {154 this._$rootScope.$broadcast("InstallFinished");155 });156 }157 }158 play(slot: number, success_callback = null): void159 {160 if (this._state === SERVER_STATE.CONNECTED)161 {162 this._state = SERVER_STATE.WAITING;163 this._$http.get("//" + this._ip_addr + "/v2/motions/" + slot.toString() + "/play")164 .success((response: any) =>165 {166 this._state = SERVER_STATE.CONNECTED;167 if (response.data.result === true)168 {169 if (!_.isNull(success_callback))170 {171 success_callback();172 }173 }174 else175 {176 this._state = SERVER_STATE.DISCONNECTED;177 alert("USB connection was disconnected!");178 this._$rootScope.$broadcast("SyncEnd");179 }180 })181 .error(() =>182 {183 this._state = SERVER_STATE.DISCONNECTED;184 });185 }186 }187 stop(success_callback = null): void188 {189 if (this._state === SERVER_STATE.CONNECTED)190 {191 this._state = SERVER_STATE.WAITING;192 this._$http.get("//" + this._ip_addr + "/v2/motions/stop")193 .success((response: any) =>194 {195 this._state = SERVER_STATE.CONNECTED;196 if (response.data.result === true)197 {198 if (!_.isNull(success_callback))199 {200 success_callback();201 }202 }203 else204 {205 this._state = SERVER_STATE.DISCONNECTED;206 alert("USB connection was disconnected!");207 this._$rootScope.$broadcast("SyncEnd");208 }209 })210 .error(() =>211 {212 this._state = SERVER_STATE.DISCONNECTED;213 });214 }215 }216 getStatus(): SERVER_STATE217 {218 return this._state;219 }220 asyncCheckVersionOfPLEN(): ng.IPromise<any>221 {222 var url_promises: Array<ng.IPromise<any>> = _.map(223 [224 '//' + this._ip_addr + '/v2/version',225 '//' + this._ip_addr + '/v2/metadata'226 ],227 (url) =>228 {229 return this._$http.get(url).then((r) => { return r.data; });230 });231 return this._$q.all(url_promises)232 .then((responses) =>233 {234 try {235 var firmware_version: number = parseInt(responses[0].data['version'].replace(/\./g, ''));236 var required_verison: number = parseInt(responses[1].data['required-firmware'].replace(/[\.\~]/g, ''));237 if (firmware_version < required_verison) throw ('Firmware version of your PLEN is old. Please update version ' + responses[1].data['required-firmware'] + '.');238 if (required_verison < 141) throw ('Application version of "Control Server" is old. Please update version 2.3.1 or above.');239 }240 catch (error)241 {242 return this._$q.reject(error);243 }244 })245 .catch((error: any) =>246 {247 this.disconnect();248 alert(_.isString(error)? error : 'Application version of "Control Server" is old. Please update version 2.3.1 or above.');249 });250 }251 onSyncBegin(): void252 {253 if (!_.isNull(this._socket))254 {255 this._socket.close();256 this._socket = null;257 }258 this._socket = new WebSocket('ws://' + this._ip_addr + '/v2/cmdstream');259 this._socket.onopen = () =>260 {261 if (this._socket.readyState === WebSocket.OPEN)262 {263 this._state = SERVER_STATE.CONNECTED;264 $("html").on("angleChange.toPLENControlServerService", () =>265 {266 if (this._state === SERVER_STATE.CONNECTED)267 {268 var device: string = this._three.transform_controls.object.name;269 var value: number = this._three.getDiffAngle(this._three.transform_controls.object);270 this._socket.send('applyDiff/' + device + '/' + value.toString());271 this._state = SERVER_STATE.WAITING;272 }273 });274 }275 };276 this._socket.onmessage = (e: MessageEvent) =>277 {278 if (e.data == 'False')279 {280 if (this._state === SERVER_STATE.WAITING)281 {282 this._state = SERVER_STATE.DISCONNECTED;283 alert("USB connection was disconnected!");284 this._$rootScope.$broadcast("SyncEnd");285 }286 }287 else288 {289 this._state = SERVER_STATE.CONNECTED;290 }291 };292 this._socket.onerror = () =>293 {294 this._state = SERVER_STATE.DISCONNECTED;295 alert("USB connection was disconnected!");296 this._$rootScope.$broadcast("SyncEnd");297 };298 }299 onSyncEnd(): void300 {301 this._socket.close();302 this._socket = null;303 $("html").off("angleChange.toPLENControlServerService");304 }305}...
PLENControlServer.Service.ts
Source:PLENControlServer.Service.ts
1/// <reference path='../index.ts' />2enum SERVER_STATE3{4 DISCONNECTED,5 CONNECTED,6 WAITING7};8class PLENControlServerService9{10 private _state: SERVER_STATE = SERVER_STATE.DISCONNECTED;11 private _socket: WebSocket = null;12 private _ip_addr: string = 'localhost:17264';13 static $inject = [14 '$q',15 '$http',16 '$rootScope'17 ];18 constructor(19 private _$q: ng.IQService,20 private _$http: ng.IHttpService,21 private _$rootScope: ng.IRootScopeService22 )23 {24 this.connect(() => { this.checkVersionOfPLEN(); });25 }26 connect(success_callback = null): void27 {28 if (this._state === SERVER_STATE.DISCONNECTED)29 {30 this._state = SERVER_STATE.WAITING;31 this._$http.get('//' + this._ip_addr + '/v2/connect')32 .success((response: any) =>33 {34 if (response.data.result === true)35 {36 this._state = SERVER_STATE.CONNECTED;37 this._createWebSocket();38 if (!_.isNull(success_callback))39 {40 success_callback();41 }42 }43 else44 {45 this._state = SERVER_STATE.DISCONNECTED;46 alert('USB connection has been disconnected!');47 }48 })49 .error(() =>50 {51 this._state = SERVER_STATE.DISCONNECTED;52 alert("The control-server hasn't run.");53 });54 }55 }56 install(json, success_callback = null): void57 {58 if (this._state === SERVER_STATE.CONNECTED)59 {60 this._state = SERVER_STATE.WAITING;61 this._$http.put('//' + this._ip_addr + '/v2/motions/' + json.slot.toString(), json)62 .success((response: any) =>63 {64 this._state = SERVER_STATE.CONNECTED;65 if (response.data.result === true)66 {67 if (!_.isNull(success_callback))68 {69 success_callback();70 }71 }72 })73 .error(() =>74 {75 this._state = SERVER_STATE.DISCONNECTED;76 })77 .finally(() =>78 {79 this._$rootScope.$broadcast('InstallFinished');80 });81 }82 }83 applyNative(device: string, value: number): void84 {85 if (this._state === SERVER_STATE.CONNECTED)86 {87 this._socket.send('apply/' + device + '/' + value.toString());88 this._state = SERVER_STATE.WAITING;89 }90 }91 setMin(device: string, value: number): void92 {93 if (this._state === SERVER_STATE.CONNECTED)94 {95 this._socket.send('setMin/' + device + '/' + value.toString());96 this._state = SERVER_STATE.WAITING;97 }98 }99 setMax(device: string, value: number): void100 {101 if (this._state === SERVER_STATE.CONNECTED)102 {103 this._socket.send('setMax/' + device + '/' + value.toString());104 this._state = SERVER_STATE.WAITING;105 }106 }107 setHome(device: string, value: number): void108 {109 if (this._state === SERVER_STATE.CONNECTED)110 {111 this._socket.send('setHome/' + device + '/' + value.toString());112 this._state = SERVER_STATE.WAITING;113 }114 }115 resetJointSettings(): void116 {117 if (this._state === SERVER_STATE.CONNECTED)118 {119 this._socket.send('resetJointSettings');120 this._state = SERVER_STATE.WAITING;121 }122 }123 getStatus(): SERVER_STATE124 {125 return this._state;126 }127 checkVersionOfPLEN(): void128 {129 if (this._state === SERVER_STATE.CONNECTED)130 {131 var deferred: ng.IDeferred<any> = this._$q.defer();132 var promise: ng.IPromise<any> = deferred.promise;133 var urls: Array<string> = [134 '//' + this._ip_addr + '/v2/version',135 '//' + this._ip_addr + '/v2/metadata'136 ];137 var responses: Array<any> = [];138 _.each(urls, (url: string) =>139 {140 promise = promise.finally(() =>141 {142 return this._$http.get(url)143 .success((response: any) =>144 {145 responses.push(response);146 });147 });148 });149 promise = promise150 .then(() =>151 {152 try {153 var firmware_version: number = parseInt(responses[0].data['version'].replace(/\./g, ''));154 var required_verison: number = parseInt(responses[1].data['required-firmware'].replace(/[\.\~]/g, ''));155 if (firmware_version < required_verison) throw 'version error';156 }157 catch (e)158 {159 this._state = SERVER_STATE.DISCONNECTED;160 alert('Firmware version of your PLEN is old. Please update version ' + responses[1].data['required-firmware'] + '.');161 }162 })163 .catch(() =>164 {165 this._state = SERVER_STATE.DISCONNECTED;166 });167 deferred.resolve();168 }169 }170 private _createWebSocket(): void171 {172 if (!_.isNull(this._socket))173 {174 this._socket.close();175 this._socket = null;176 }177 this._socket = new WebSocket('ws://' + this._ip_addr + '/v2/cmdstream');178 this._socket.onopen = () =>179 {180 if (this._socket.readyState === WebSocket.OPEN)181 {182 this._state = SERVER_STATE.CONNECTED;183 this._$rootScope.$apply();184 }185 };186 this._socket.onmessage = (event: any) =>187 {188 if (event.data == 'False')189 {190 if (this._state === SERVER_STATE.WAITING)191 {192 this._state = SERVER_STATE.DISCONNECTED;193 this._$rootScope.$apply();194 alert('USB connection has been disconnected!');195 }196 }197 else198 {199 this._state = SERVER_STATE.CONNECTED;200 }201 };202 this._socket.onerror = () =>203 {204 this._state = SERVER_STATE.DISCONNECTED;205 this._$rootScope.$apply();206 alert("The control-server hasn't run.");207 };208 }209}...
serverState.js
Source:serverState.js
1var SERVER_STATE = require("../models/server-state-model");2const nftData = require("../models/nft-model");3module.exports = (app, io) => {4 // initialAreana = {5 // nftTokenIdOne: 0,6 // nftTokenIdTwo: 07 // }8 // SERVER_STATE.areanas.push(initialAreana)9 initialAreana = {10 areanaId: 1,11 nftTokenIdOne: 0,12 nftTokenIdTwo: 0,13 nftTokenOneOwner: "",14 };15 SERVER_STATE.areanas.push(initialAreana);16 function startTimer() {17 var serverTick = setInterval(() => {18 if (SERVER_STATE.appSettings.timerVal === 0) {19 //call the no more bets for each socket20 //get a player from queue and emit it to all clients21 var random = Math.floor(Math.random() * SERVER_STATE.queue.length);22 console.log(random);23 // SERVER_STATE24 io.emit("addPlayerToFight");25 clearInterval(serverTick);26 SERVER_STATE.appSettings.timerVal = 30;27 startTimer();28 } else {29 io.emit("timerTick", SERVER_STATE.appSettings.timerVal--);30 var random = Math.floor(Math.random() * (10 + 1));31 // console.log(random)32 // console.log(SERVER_STATE.appSettings.timerVal)33 }34 }, 1000);35 }36 startTimer();37 io.on("connection", (socket) => {38 console.log(socket.id);39 sendBack = { areanas: SERVER_STATE.areanas };40 socket.emit("areanas", sendBack);41 // socket.on('sendNftId', async function(tokenId, func) {42 // // console.log(tokenId)43 // // data = await nftData.findOne({nftId: tokenId}).then((res) => {44 // // console.log(res)45 // // })46 // // console.log(tokenId);47 // socket.emit('getNftData', data)48 // })49 // io.to(socket).emit('init', SERVER_STATE.areanas)50 socket.emit("init", SERVER_STATE.areanas);51 socket.on("fight", async function (data, func) {52 if (53 SERVER_STATE.areanas[data - 1] &&54 (SERVER_STATE.areanas[data - 1].nftTokenIdOne === 0 ||55 SERVER_STATE.areanas[data - 1].nftTokenIdTwo === 0)56 ) {57 return;58 }59 const tokenOne = await nftData.findOne({60 nftId: SERVER_STATE.areanas[data - 1].nftTokenIdOne,61 });62 const tokenTwo = await nftData.findOne({63 nftId: SERVER_STATE.areanas[data - 1].nftTokenIdTwo,64 });65 const typeValueOne = tokenOne.type;66 const typeValueTwo = tokenTwo.type;67 var totalValueOne = 0;68 var totalValueTwo = 0;69 SERVER_STATE.types.map((type) => {70 if (type.type === typeValueOne) {71 totalValueOne = type.strength;72 }73 if (type.type === typeValueTwo) {74 totalValueTwo = type.strength;75 }76 });77 totalValueOne += tokenOne.level * 2;78 totalValueTwo += tokenTwo.level * 2;79 if (tokenOne.rank < tokenTwo.rank) {80 totalValueOne += 10;81 } else {82 totalValueTwo += 10;83 }84 let percentOneWillWin =85 (totalValueOne * 100) / (totalValueOne + totalValueTwo);86 let randomOne = Math.floor(Math.random() * totalValueOne);87 let randomTwo = Math.floor(Math.random() * totalValueTwo);88 //transfer nfts n stuff89 if (randomOne > randomTwo) {90 console.log("NFT ONE WON: ", randomOne);91 } else {92 console.log("NFT TWO WON: ", randomTwo);93 }94 //reset the areana95 SERVER_STATE.areanas[data - 1].nftTokenIdOne = 0;96 SERVER_STATE.areanas[data - 1].nftTokenIdTwo = 0;97 sendBack = { areanas: SERVER_STATE.areanas };98 // socket.emit('areanas',sendBack)99 io.emit("areanas", sendBack);100 console.log(percentOneWillWin);101 console.log(totalValueOne);102 });103 //add queing104 socket.on("sendNftToAreana", async function (data, func) {105 console.log(data);106 if (!data.tokenId) {107 //emit an error108 return;109 }110 if (SERVER_STATE.areanas[data.areanaId - 1].nftTokenIdOne === 0) {111 SERVER_STATE.areanas[data.areanaId - 1].nftTokenIdOne = data.tokenId;112 SERVER_STATE.areanas[data.areanaId - 1].nftTokenOneOwner = data.owner;113 } else if (114 SERVER_STATE.areanas[data.areanaId - 1].nftTokenIdTwo === 0 &&115 SERVER_STATE.areanas[data.areanaId - 1].nftTokenIdOne !== data.tokenId116 ) {117 SERVER_STATE.areanas[data.areanaId - 1].nftTokenIdTwo = data.tokenId;118 } else {119 //theres something in both they want to join the queue120 if (!data.owner) {121 //emit an error122 return;123 }124 var canAdd = true;125 //loop through queue126 for (var i = 0; i < SERVER_STATE.queue.length; i++) {127 if (SERVER_STATE.queue[i].owner == data.owner) {128 //cant have the same owner in the queue twice129 canAdd = false;130 }131 }132 if (canAdd) {133 player = {134 owner: data.owner,135 nftId: data.tokenId,136 };137 SERVER_STATE.queue.push(player);138 }139 }140 sendBack = { areanas: SERVER_STATE.areanas };141 io.emit("areanas", sendBack);142 });143 });...
Using AI Code Generation
1var wpt = require('webpagetest');2var wpt = new WebPageTest('www.webpagetest.org');3wpt.serverState(function(err, data) {4 if (err) {5 console.log('Error: ' + err);6 } else {7 console.log(data);8 }9});10var wpt = require('webpagetest');11var wpt = new WebPageTest('www.webpagetest.org');12 if (err) {13 console.log('Error: ' + err);14 } else {15 console.log(data);16 }17});18var wpt = require('webpagetest');19var wpt = new WebPageTest('www.webpagetest.org');
Using AI Code Generation
1var wpt = require('webpagetest');2var wpt = new WebPageTest('www.webpagetest.org');3wpt.server_state(function(err, data) {4 console.log(data);5});6var wpt = require('webpagetest');7var wpt = new WebPageTest('www.webpagetest.org');8wpt.server_state(function(err, data) {9 console.log(data);10});11var wpt = require('webpagetest');12var wpt = new WebPageTest('www.webpagetest.org');13wpt.server_state(function(err, data) {14 console.log(data);15});16var wpt = require('webpagetest');17var wpt = new WebPageTest('www.webpagetest.org');18wpt.server_state(function(err, data) {19 console.log(data);20});21var wpt = require('webpagetest');22var wpt = new WebPageTest('www.webpagetest.org');23wpt.server_state(function(err, data) {24 console.log(data);25});26var wpt = require('webpagetest');27var wpt = new WebPageTest('www.webpagetest.org');28wpt.server_state(function(err, data) {29 console.log(data);30});31var wpt = require('webpagetest');32var wpt = new WebPageTest('www.webpagetest.org');33wpt.server_state(function(err, data) {34 console.log(data);35});36var wpt = require('webpagetest');37var wpt = new WebPageTest('www.webpagetest.org');38wpt.server_state(function(err, data) {39 console.log(data);40});
Using AI Code Generation
1var wpt = require('wptdriver');2wpt.server_state(url, function(error, result){3 if(error){4 console.log(error);5 }else{6 console.log(result);7 }8});9 $(document).ready(function(){10 $.ajax({11 success: function(data){12 console.log(data);13 }14 });15 });16 $ch = curl_init();17 curl_setopt($ch, CURLOPT_POST, 1);18 curl_setopt($ch, CURLOPT_POSTFIELDS, "url=".$url);19 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);20 $server_output = curl_exec($ch);21 curl_close($ch);22 echo $server_output;23 $ch = curl_init();24 curl_setopt($ch, CURLOPT_POST, 1);25 curl_setopt($ch, CURLOPT_POSTFIELDS, "url=".$url);26 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);27 $server_output = curl_exec($ch);28 curl_close($ch);29 echo $server_output;30### <a name="server_state"></a>server_state (url, callback)
Using AI Code Generation
1var wpt = require('webpagetest');2var api = new wpt('A.1f1a3b3c3d3e3f3g3h3i3j3k3l3m3n3o3p3q3r3s3t3u3v3w3x3y3z3');3var options = {4};5api.runTest(url, options, function(err, data) {6 if (err) return console.log(err);7 var testId = data.data.testId;8 api.getTestResults(testId, function(err, data) {9 if (err) return console.log(err);10 console.log(data);11 });12});13var wpt = require('webpagetest');14var api = new wpt('A.1f1a3b3c3d3e3f3g3h3i3j3k3l3m3n3o3p3q3r3s3t3u3v3w3x3y3z3');15var options = {16};17api.runTest(url, options, function(err, data) {18 if (err) return console.log(err);19 var testId = data.data.testId;20 api.getTestResults(testId, function(err, data) {21 if (err) return console.log(err);22 console.log(data);23 });24});25var wpt = require('webpagetest');26var api = new wpt('A.1f1a3b3c3d3e3f3g3h3i3j3k3l3m3n3o3p3q3r3s3t3u3v3w3x3y3z3');27var options = {
Using AI Code Generation
1var wpt = require('webpagetest');2var webPageTest = new wpt('A.6b1e9f4c3d4b4b4e0f4d0b4f8b8c4f2');3 lighthouseConfig: {4 settings: {5 }6 }7}, function (err, data) {8 if (err) {9 console.log(err);10 } else {11 console.log(data);12 var testId = data.data.testId;13 webPageTest.waitForTestToComplete(testId, function (err, data) {14 if (err) {15 console.log(err);16 } else {17 console.log(data);18 var server_state = data.data.median.firstView.server_state;19 console.log(server_state);20 }21 });22 }23});24### wpt.getTestResults(testId, callback)25var wpt = require('webpagetest');26var webPageTest = new wpt('A.6b1e9f4c3d4b4b4e0f4d0b4f8b8c4f2');27webPageTest.getTestResults('210712_AiDc8c_5a5f5e7f1d2e2a7a1a5c2f7d9f5c5d5', function (err, data) {28 if (err) {29 console.log(err);30 } else {31 console.log(data);32 }33});34### wpt.getTestStatus(testId
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!!