How to use InjectedFunc method in chromy

Best JavaScript code snippet using chromy

RTYCommon.js

Source:RTYCommon.js Github

copy

Full Screen

1/**2 * 参照Python模块的实现3 * Created by Ian on 2016/12/25.4 */5// / 来源于NodejS系统内置的6const sysUtil = require('util')7const sysURL = require('url')8const sysFS = require('fs')9const sysOS = require('os')10const sysCluster = require('cluster')11const sysChildProcess = require('child_process')12const sysNet = require('net')13const sysHTTP = require('http')14const sysHTTPS = require('https')15const sysEvents = require('events')16const sysDNS = require('dns')17const sysPunyCode = require('punycode')18const sysReadline = require('readline')19const sysStream = require('stream')20const sysStringDecoder = require('string_decoder')21const sysTLS = require('tls')22const sysDatagram = require('dgram')23const sysVM = require('vm')24const sysZlib = require('zlib')25const sysBuffer = require('buffer')26const sysCrypto = require('crypto')27const sysPath = require('path')28const Q = require('q')29// 服务器传回到客户端的消息类型30const ServerTaskMsgTypes = {31 Running: 's_task_exec_running',32 RealTimeFeedback: 's_task_exec_feedback',33 Err: 's_err_progress',34 Complete: 's_task_exec_result'35}36function obj2str (obj) {37 if (sysUtil.isObject(obj) || sysUtil.isArray(obj)) {38 return sysUtil.inspect(obj, {39 showHidden: true,40 depth: null41 })42 }43 return obj44}45function Singleton () {46 const that = this47 // 服务器传回到客户端的消息类型48 that.ServerTaskMsgTypes = ServerTaskMsgTypes49 that.obj2str = obj2str50 // 方便调式的处理方式51 that.debugHandler = {}52 /**53 * app 在ready状态下,必须更新54 * @returns {{}|*}55 */56 that.updateDebugHandler = function () {57 const that = this58 that.debugHandler = {59 sysOS,60 sysPath,61 sysFS,62 sysBuffer,63 sysUtil,64 sysCrypto,65 sysCluster,66 sysChildProcess,67 sysNet,68 sysHTTP,69 sysHTTPS,70 sysEvents,71 sysDNS,72 sysPunyCode,73 sysReadline,74 sysStream,75 sysStringDecoder,76 sysTLS,77 sysDatagram,78 sysVM,79 sysZlib,80 //81 $END: {}82 }83 return that.debugHandler84 }85 // 对象Clone86 that.clone = function (obj) {87 //88 // We only need to clone reference types (Object)89 //90 let copy = {}91 if (obj instanceof Error) {92 // With potential custom Error objects, this might not be exactly correct,93 // but probably close-enough for purposes of this lib.94 copy = new Error(obj.message)95 Object.getOwnPropertyNames(obj).forEach(key => {96 copy[key] = obj[key]97 })98 return copy99 } else if (!(obj instanceof Object)) {100 return obj101 } else if (obj instanceof Date) {102 return new Date(obj.getTime())103 }104 for (const i in obj) {105 if (Array.isArray(obj[i])) {106 copy[i] = obj[i].slice(0)107 } else if (obj[i] instanceof Buffer) {108 copy[i] = obj[i].slice(0)109 } else if (typeof obj[i] !== 'function') {110 copy[i] = obj[i] instanceof Object ? exports.clone(obj[i]) : obj[i]111 } else if (typeof obj[i] === 'function') {112 copy[i] = obj[i]113 }114 }115 return copy116 }117 // ////////////////////////////////////////////////////////////118 // 已经加载Module字典119 that.globalLoadedModulesMap = {}120 // 查找已经加载的Module是否存在121 that.findLoadedModuleByPath = function (modulePath) {122 const that = this123 // console.log("globalLoadedModulesMap = %s", that.obj2str(that.globalLoadedModulesMap));124 return that.globalLoadedModulesMap.hasOwnProperty(modulePath)125 }126 // 添加新的Module到字典中127 that.registerLoadedModule = function (modulePath, moduleObj) {128 const that = this129 that.globalLoadedModulesMap[modulePath] = moduleObj130 console.log('register new module, ', modulePath)131 }132 // 获取指定的Module133 that.getLoadedModule = function (modulePath, reload) {134 const that = this135 if (that.findLoadedModuleByPath(modulePath)) {136 if (reload === true) {137 // 删除缓存,然后重新加载138 const CachesForModulePath = require.resolve(modulePath)139 console.log('CachesForModulePath = %s', CachesForModulePath)140 console.log('require.cache = %s', require.cache)141 try {142 delete require.cache[CachesForModulePath]143 delete that.globalLoadedModulesMap[modulePath]144 } catch (err) {145 console.trace(err)146 }147 } else {148 return that.globalLoadedModulesMap[modulePath]149 }150 }151 return null152 }153 // 获取JSON字符串154 that.getJSONMessage = function (info) {155 try {156 return JSON.stringify(info)157 } catch (err) {158 console.error(err)159 console.trace(err)160 }161 return ''162 }163 // 获取Func164 that.getFunc = function (moduleName, funcName, reload) {165 const that = this166 let funcObj = null167 // Check Path is Exist?168 const modulePath = './' + moduleName169 let specModule = that.getLoadedModule(modulePath, reload)170 if (!specModule) {171 try {172 specModule = require(modulePath)173 if (specModule) {174 that.registerLoadedModule(modulePath, specModule)175 }176 } catch (err) {177 console.error(err)178 console.trace(err)179 }180 }181 if (specModule) {182 if (specModule.hasOwnProperty(funcName)) {183 const _func = specModule[funcName]184 if (sysUtil.isFunction(_func)) {185 funcObj = _func186 }187 }188 }189 if (!funcObj) {190 console.log('the Module:', moduleName, ' call ' + funcName + ' function faild....')191 }192 return funcObj193 }194 /**195 * CLI调用Agent196 */197 const CLICallAgent = (function () {198 function CLICallAgent (taskInfo, user_id, cb, event, service) {199 this.taskInfo = taskInfo200 this.user_id = user_id201 this.cb = cb202 this.event = event203 this.service = service204 this.baseInfo = {205 task_id: taskInfo.task_id,206 task_cli: taskInfo.cli,207 cb: taskInfo.callback,208 event: event209 }210 this.result = null211 }212 CLICallAgent.prototype.start = function () {213 const self = this214 self.run()215 }216 CLICallAgent.prototype.run = function () {217 const self = this218 // /////////////////////////////////////////////219 const fnSendMessageToClient = self.cb220 let result_data = null,221 cli = null,222 command = null,223 reload = false224 try {225 console.log('taskInfo = %s', obj2str(self.taskInfo))226 cli = self.taskInfo.cli227 reload = self.taskInfo.reload228 command = self.taskInfo.command229 console.log('CLICallAgent cli=%s, command=%s, reload=%d', obj2str(cli), obj2str(command), reload)230 // / 开始运行部分231 var info = self.service.clone(self.baseInfo)232 info.msg_type = ServerTaskMsgTypes.Running233 // / 配置基础信息234 var jsonStr = self.service.getJSONMessage(info)235 // / 返回调用的信息236 fnSendMessageToClient(self.user_id, self.event, jsonStr)237 // / 定义反馈函数238 function sendFeedback (user_id, baseInfo, content, msg_type, injectedFunc) {239 const info = self.service.clone(baseInfo)240 info.msg_type = msg_type || ServerTaskMsgTypes.RealTimeFeedback241 info.content = content242 injectedFunc && injectedFunc(info) // 注入其他信息243 const jsonStr = self.service.getJSONMessage(info)244 fnSendMessageToClient(self.user_id, self.event, jsonStr) // 返回调用的信息245 }246 function fncSendFeedbackMessage (content, injectedFunc) {247 sendFeedback(self.user_id, self.baseInfo, content, ServerTaskMsgTypes.RealTimeFeedback, injectedFunc)248 }249 function fncSendResultMessage (content, injectedFunc) {250 sendFeedback(self.user_id, self.baseInfo, content, ServerTaskMsgTypes.Complete, injectedFunc)251 }252 function fncSendErrorMessage (content, injectedFunc) {253 sendFeedback(self.user_id, self.baseInfo, content, ServerTaskMsgTypes.Err, injectedFunc)254 }255 /**256 # CLI 执行257 # 默认修改或者建立模块的化使用MainRTYCLI函数258 # 1.监测是否存在259 # 2.MainRTYCLI,加入参数:fncSendFeedbackMessage 反馈信息到客户端的函数句柄260 #261 * */262 console.log('To find %s.MainRTYCLI', cli)263 const cliMain = self.service.getFunc(cli, 'MainRTYCLI', reload)264 if (cliMain) {265 result_data = cliMain(fncSendFeedbackMessage, command, self.baseInfo)266 } else {267 console.log('no found cliMain.......')268 }269 // 判断result_data的对象类型270 if (result_data && typeof result_data.then === 'function') {271 const promise = result_data272 // promise273 promise.then(function (deferredListOrDeferred) {274 var tmpList = []275 if (Array.isArray(deferredListOrDeferred)) {276 tmpList = deferredListOrDeferred277 } else {278 tmpList.push(deferredListOrDeferred)279 }280 tmpList.forEach((oneDeferred) => {281 oneDeferred.promise.then(function (dataInfo) {282 fncSendResultMessage(dataInfo, function (info) {283 })284 })285 })286 }, function (err) {287 fncSendErrorMessage(err.message, function (info) {288 info.traceback = err.stack || ''289 info.tracebackMsg = err.stack || ''290 })291 })292 // promise end293 } else if (result_data) {294 const info = self.baseInfo295 info.msg_type = ServerTaskMsgTypes.Complete296 info.result = result_data || {}297 const jsonStr = self.service.getJSONMessage(info)298 fnSendMessageToClient(self.user_id, jsonStr)299 }300 } catch (err) {301 console.error('Exception = %s', err)302 console.trace(err)303 const info = self.service.clone(self.baseInfo)304 info.msg_type = ServerTaskMsgTypes.Err305 info.content = err.message || ''306 info.traceback = err.stack || ''307 info.tracebackMsg = err.stack || ''308 const jsonStr = self.service.getJSONMessage(info)309 fnSendMessageToClient(self.user_id, jsonStr)310 }311 }312 return CLICallAgent313 })()314 // ////////////// 通用Call方式315 /**316 * 通过分发方式,调用其他的模块的python,并且可以将信息返回到调用者317 * @param taskInfo 对象,{task_id, cli, callback}. 传进来的任务对象318 * @param user_id 标识与谁的连接319 * @param cb 调用方传过来的回调函数320 */321 that.callCommonCLI = function (taskInfo, user_id, cb, event) {322 const that = this323 console.log('callCommonCLI: %s', obj2str(taskInfo))324 const agent = new CLICallAgent(taskInfo, user_id, cb, event, that)325 agent.start()326 }327}328/* ************************************************************************329 Singleton CLASS DEFINITION330 ************************************************************************ */331Singleton.instance = null332/**333 * Singleton getInstance definition334 * @return Singleton class335 */336Singleton.getInstance = function () {337 const that = this338 if (that.instance === null) {339 that.instance = new Singleton()340 that.instance.updateDebugHandler()341 console.log('### <Singleton.getInstance>')342 }343 return this.instance344}...

Full Screen

Full Screen

defer.js

Source:defer.js Github

copy

Full Screen

1import { expect } from 'chai';2import when from 'when';3import { msleep } from './utils/sleep';4import createContext from '../../src/lib/createContext';5import args from '../../src/decorators/args';6import defer from '../../src/decorators/defer';7const Promise = when.promise;8const firstSpec = {9 @args()10 first: () => Promise(resolve => {11 msleep(10);12 resolve(`first`);13 })14}15const secondSpec = {16 @args({$ref: 'environment'})17 second: (environment) => Promise(resolve => {18 msleep(10);19 resolve(`second_` + environment.importantEnvVar);20 })21}22const zeroSpec = {23 @args({$ref: 'environment'})24 zero: (environment) => 'zero_' + environment.importantEnvVar25}26const spec = {27 @args()28 environment: () => ({29 importantEnvVar: 'importantEnvVar'30 }),31 @args()32 environmentAnother: () => ({33 type: 'crud'34 }),35 @defer(zeroSpec)36 zeroDeferredComponent: {},37 @defer(38 [firstSpec, secondSpec],39 {$ref: 'environment'},40 {$ref: 'environmentAnother'}41 )42 deferredComponent: {},43 @args({$ref: 'deferredComponent'})44 A: (injectedFunc) => injectedFunc()45}46describe('Create context with deferred component', async () => {47 let context;48 before(async function() {49 try {50 context = await createContext(spec);51 } catch (error) {52 console.log('ERROR:' , error);53 }54 });55 it('context A component should be an object', () => {56 expect(context.A).to.be.an('object');57 });58 it('context zeroDeferredComponent component should be a function', () => {59 expect(context.zeroDeferredComponent).to.be.a('function');60 });61 it('context deferredComponent component should be a function', () => {62 expect(context.deferredComponent).to.be.a('function');63 });64 it('context A component should have field first', () => {65 expect(context.A.first).to.equal('first');66 });67 it('context A component should have field second', () => {68 expect(context.A.second).to.equal('second_importantEnvVar');69 });70 it('context A component should have destroy method', () => {71 expect(context.A.destroy).to.be.a('function');72 });73 after(async function() {74 try {75 context.destroy();76 } catch (error) {77 console.log('ERROR on destroy:' , error);78 }79 });80});81const specOne = {82 @args()83 env: () => ({84 importantEnvVar: 'importantEnvVar'85 }),86 @args()87 envOther: () => ({88 type: 'crud'89 }),90 @args()91 someNum: () => 1,92 @defer(93 {94 @args({$ref: 'envRenamedKey'})95 a: () => 'a',96 @args({$ref: 'envOtherRenamedKey'})97 b: () => 'b',98 @args({$ref: 'someFn'})99 c: (someFn) => someFn(),100 @args({$ref: 'someArray'})101 d: (someArray) => someArray[0]102 },103 /* provide: */104 {}, /* empty object is not provided - no error should be thrown */105 {$ref: 'someNum'},106 {107 envRenamedKey: {$ref: 'env'},108 envOtherRenamedKey: {$ref: 'envOther'},109 someFn: () => 'c',110 someArray: ['d']111 }112 )113 deferredComponent: {},114 @args({$ref: 'deferredComponent'})115 A: (injectedFunc) => injectedFunc()116}117describe('Create context with deferred component & provided spec & renamed components', async () => {118 let context;119 before(async function() {120 try {121 context = await createContext(specOne);122 } catch (error) {123 console.log('ERROR:' , error);124 }125 });126 it('context should be an object', () => {127 expect(context).to.be.an('object');128 });129 it('context A.a value', () => {130 expect(context.A.a).to.equal('a');131 });132 it('context A.b value', () => {133 expect(context.A.b).to.equal('b');134 });135 it('context A.c value', () => {136 expect(context.A.c).to.equal('c');137 });138 it('context A.d value', () => {139 expect(context.A.d).to.equal('d');140 });141 after(async function() {142 try {143 context.destroy();144 } catch (error) {145 console.log('ERROR on destroy:' , error);146 }147 });148});149const specTwo = {150 @args()151 A: () => 1,152 @defer(153 {154 @args({$ref: 'A'}, {$ref: 'B'})155 a: (a, b) => a + b156 },157 /* provide A now, provide B later when func is invoked */158 {$ref: 'A'}159 )160 deferredComponent: {},161 @args({$ref: 'deferredComponent'})162 response: (injectedFunc) => injectedFunc({B: 2})163}164describe('Create context with deferred spec & args provided when function is invoked', async () => {165 let context;166 before(async function() {167 try {168 context = await createContext(specTwo);169 } catch (error) {170 console.log('ERROR:' , error);171 }172 });173 it('context should be an object', () => {174 expect(context).to.be.an('object');175 });176 it('context response value', () => {177 expect(context.response.a).to.equal(3);178 });179 after(async function() {180 try {181 context.destroy();182 } catch (error) {183 console.log('ERROR on destroy:' , error);184 }185 });...

Full Screen

Full Screen

configure.ts

Source:configure.ts Github

copy

Full Screen

1import { A } from "ts-toolbelt"2import { Constructor } from "@fp-app/framework"3import { injectSymbol, Key } from "./SimpleContainer"4/**5 * Configures a function for dependency injection, dependency types are automatically inferred based on6 * the passed `deps` configuration. Dependency configuration is provided as last argument.7 */8export function configure<9 TDependencies extends DependencyDefinitions,10 TFunctionConstructor extends (11 dependencies: A.Compute<Dependencies<TDependencies>>,12 ) => TFunction,13 TFunction14>(func: TFunctionConstructor, deps: () => TDependencies) {15 return configureDepsFirst<TDependencies, TFunctionConstructor, TFunction>(deps, func)16}17/**18 * Configures a function for dependency injection, dependency types are automatically inferred based on19 * the passed `deps` configuration. Dependency configuration is provided as first argument.20 */21function configureDepsFirst<22 TDependencies extends DependencyDefinitions,23 TFunctionConstructor extends (24 dependencies: A.Compute<Dependencies<TDependencies>>,25 ) => TFunction,26 TFunction27>(deps: () => TDependencies, func: TFunctionConstructor) {28 const injectedFunc = func as ConfiguredFunction<29 TDependencies,30 TFunctionConstructor,31 TFunction32 >33 injectedFunc[injectSymbol] = deps34 return injectedFunc35}36export function createGroupOfDependencies<TDependencies extends DependencyDefinitions>(37 deps: () => TDependencies,38) {39 return configure(function (resolvedDependencies) {40 return resolvedDependencies41 }, deps)42}43// export function useInstanceForFunction(container: DependencyInjectionContainer) {44// return <T, TFunction extends Function>(cls: Constructor<T>, selector: (instance: T) => TFunction) => () => {45// const instance = container.get(cls)46// return selector(instance).bind(instance)47// }48// }49export interface DependencyDefinitions {50 // eslint-disable-next-line @typescript-eslint/no-explicit-any51 [key: string]: Constructor | ConfiguredFunction<any, any, unknown> | unknown52}53export type Dependencies<T extends DependencyDefinitions> = {54 [P in keyof T]: T[P] extends Constructor55 ? InstanceType<T[P]>56 : T[P] extends Key<infer X>57 ? X58 : T[P] extends SomeFunction59 ? ReturnType<T[P]>60 : T[P]["prototype"]61}62// eslint-disable-next-line @typescript-eslint/no-explicit-any63type SomeFunction = (...args: any[]) => any64export type ConfiguredFunction<65 TDependencies extends DependencyDefinitions,66 TFunctionConstructor extends (67 dependencies: A.Compute<Dependencies<TDependencies>>,68 ) => TFunction,69 TFunction70> = TFunctionConstructor & {71 [injectSymbol]: (() => TDependencies) | TDependencies72}73// Workaround for container register* signature not setup to support functions yet.74export const adaptFunctionForRegistration = <TFunction>(func: {75 (...args: unknown[]): TFunction76 [injectSymbol]: DependencyDefinitions...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1chromy.evaluate(function(){2 InjectedFunc();3});4chromy.evaluate(function(){5 InjectedFunc();6});7chromy.evaluate(function(){8 InjectedFunc();9});10chromy.evaluate(function(){11 InjectedFunc();12});13chromy.evaluate(function(){14 InjectedFunc();15});16chromy.evaluate(function(){17 InjectedFunc();18});19chromy.evaluate(function(){20 InjectedFunc();21});22chromy.evaluate(function(){23 InjectedFunc();24});25chromy.evaluate(function(){26 InjectedFunc();27});28chromy.evaluate(function(){29 InjectedFunc();30});31chromy.evaluate(function(){32 InjectedFunc();33});34chromy.evaluate(function(){35 InjectedFunc();36});37chromy.evaluate(function(){38 InjectedFunc();39});40chromy.evaluate(function(){41 InjectedFunc();42});43chromy.evaluate(function(){44 InjectedFunc();45});46chromy.evaluate(function(){47 InjectedFunc();48});49chromy.evaluate(function(){50 InjectedFunc();51});52chromy.evaluate(function(){

Full Screen

Using AI Code Generation

copy

Full Screen

1var chromy = new Chromy({visible: true});2chromy.chain()3 .evaluate(function() {4 return window.location.href;5 })6 .result(function(result) {7 console.log(result);8 })9 .end()10 .then(function() {11 chromy.close();12 });13const puppeteer = require('puppeteer');14(async () => {15 const browser = await puppeteer.launch({16 });17 const page = await browser.newPage();18 const result = await page.evaluate(() => {19 return window.location.href;20 });21 console.log(result);22 await browser.close();23})();

Full Screen

Using AI Code Generation

copy

Full Screen

1var chromy = require('chromy');2chromy.chain()3 .evaluate(function() {4 return document.title;5 })6 .end()7 .result(function(result) {8 console.log(result);9 });10const puppeteer = require('puppeteer');11(async() => {12 const browser = await puppeteer.launch();13 const page = await browser.newPage();14 const title = await page.evaluate(() => document.title);15 console.log(title);16 await browser.close();17})();

Full Screen

Using AI Code Generation

copy

Full Screen

1var chromy = require('chromy');2 .chain()3 .evaluate(function() {4 return window.location.href;5 })6 .result(function(result) {7 console.log(result);8 })9 .end()10 .then(function() {11 console.log('done');12 });13var chromy = require('chromy');14 .chain()15 .evaluate(function() {16 return window.location.href;17 })18 .result(function(result) {19 console.log(result);20 })21 .end()22 .then(function() {23 console.log('done');24 });25var chromy = require('chromy');26 .chain()27 .evaluate(function() {28 return window.location.href;29 })30 .result(function(result) {31 console.log(result);32 })33 .end()34 .then(function() {35 console.log('done');36 });37var chromy = require('chromy');38 .chain()39 .evaluate(function() {40 return window.location.href;41 })42 .result(function(result) {43 console.log(result);44 })45 .end()46 .then(function() {47 console.log('done');48 });49var chromy = require('chromy');50 .chain()51 .evaluate(function() {52 return window.location.href;53 })54 .result(function(result) {55 console.log(result);56 })57 .end()58 .then(function() {59 console.log('done');60 });61var chromy = require('chromy');62 .chain()63 .evaluate(function() {64 return window.location.href;65 })66 .result(function(result) {

Full Screen

Using AI Code Generation

copy

Full Screen

1var chromy = require('chromy');2var chromy2 = require('chromy');3chromy = new chromy();4chromy2 = new chromy2();5chromy.chain()6 .evaluate(function(){7 return document.title;8 })9 .result(function(result){10 console.log(result);11 })12 .end()13 .then(function(){14 chromy.close();15 });16chromy2.chain()17 .evaluate(function(){18 return document.title;19 })20 .result(function(result){21 console.log(result);22 })23 .end()24 .then(function(){25 chromy2.close();26 });27chromy.chain()28 .screenshot('google.png')29 .end()30 .then(function(){31 chromy.close();32 });33The problem is that the screenshot is not being taken. I have tried using the .then() method after .end() but it does not seem to work. Is there a way to take a screenshot of the current page using chromy?34var fs = require('fs');35fs.readFile('test.txt', 'utf8', function(err, data){36 if(err){37 throw err;38 }39 console.log(data

Full Screen

Using AI Code Generation

copy

Full Screen

1chromy.evaluate(function() {2 return InjectedFunc();3});4chromy.evaluate(function() {5 return InjectedFunc();6});7chromy.evaluate(function() {8 return InjectedFunc();9});10chromy.evaluate(function() {11 return InjectedFunc();12});13chromy.evaluate(function() {14 return InjectedFunc();15});16chromy.evaluate(function() {17 return InjectedFunc();18});19chromy.evaluate(function() {20 return InjectedFunc();21});22chromy.evaluate(function() {23 return InjectedFunc();24});25chromy.evaluate(function() {26 return InjectedFunc();27});28chromy.evaluate(function() {29 return InjectedFunc();30});31chromy.evaluate(function() {32 return InjectedFunc();33});34chromy.evaluate(function() {35 return InjectedFunc();36});

Full Screen

Using AI Code Generation

copy

Full Screen

1chromy.evaluate(function() {2 var result = InjectedFunc();3 console.log(result);4 return result;5}).result(function(result) {6 console.log(result);7});8function InjectedFunc() {9 return 'hello world!';10}

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