How to use pull method in lisa

Best Python code snippet using lisa_python

PullRequest.py

Source:PullRequest.py Github

copy

Full Screen

...26class PullRequest(Framework.TestCase):27 def setUp(self):28 Framework.TestCase.setUp(self)29 self.repo = self.g.get_user().get_repo("PyGithub")30 self.pull = self.repo.get_pull(31)31 def testAttributes(self):32 self.assertEqual(self.pull.additions, 511)33 self.assertEqual(self.pull.assignee.login, "jacquev6")34 self.assertEqual(self.pull.base.label, "jacquev6:topic/RewriteWithGeneratedCode")35 self.assertEqual(self.pull.base.sha, "ed866fc43833802ab553e5ff8581c81bb00dd433")36 self.assertEqual(self.pull.base.user.login, "jacquev6")37 self.assertEqual(self.pull.base.ref, "topic/RewriteWithGeneratedCode")38 self.assertEqual(self.pull.base.repo.full_name, "jacquev6/PyGithub")39 self.assertEqual(self.pull.body, "Body edited by PyGithub")40 self.assertEqual(self.pull.changed_files, 45)41 self.assertEqual(self.pull.closed_at, datetime.datetime(2012, 5, 27, 10, 29, 7))42 self.assertEqual(self.pull.comments, 1)43 self.assertEqual(self.pull.commits, 3)44 self.assertEqual(self.pull.created_at, datetime.datetime(2012, 5, 27, 9, 25, 36))45 self.assertEqual(self.pull.deletions, 384)46 self.assertEqual(self.pull.diff_url, "https://github.com/jacquev6/PyGithub/pull/31.diff")47 self.assertEqual(self.pull.head.label, "BeaverSoftware:master")48 self.assertEqual(self.pull.html_url, "https://github.com/jacquev6/PyGithub/pull/31")49 self.assertEqual(self.pull.id, 1436215)50 self.assertEqual(self.pull.issue_url, "https://github.com/jacquev6/PyGithub/issues/31")51 self.assertFalse(self.pull.mergeable)52 self.assertTrue(self.pull.merged)53 self.assertEqual(self.pull.merged_at, datetime.datetime(2012, 5, 27, 10, 29, 7))54 self.assertEqual(self.pull.merged_by.login, "jacquev6")55 self.assertEqual(self.pull.number, 31)56 self.assertEqual(self.pull.patch_url, "https://github.com/jacquev6/PyGithub/pull/31.patch")57 self.assertEqual(self.pull.review_comments, 1)58 self.assertEqual(self.pull.state, "closed")59 self.assertEqual(self.pull.title, "Title edited by PyGithub")60 self.assertEqual(self.pull.updated_at, datetime.datetime(2012, 11, 3, 8, 19, 40))61 self.assertEqual(self.pull.url, "https://api.github.com/repos/jacquev6/PyGithub/pulls/31")62 self.assertEqual(self.pull.user.login, "jacquev6")63 def testCreateComment(self):64 commit = self.repo.get_commit("8a4f306d4b223682dd19410d4a9150636ebe4206")65 comment = self.pull.create_comment("Comment created by PyGithub", commit, "src/github/Issue.py", 5)66 self.assertEqual(comment.id, 886298)67 def testGetComments(self):68 self.assertListKeyEqual(self.pull.get_comments(), lambda c: c.id, [886298])69 def testCreateIssueComment(self):70 comment = self.pull.create_issue_comment("Issue comment created by PyGithub")71 self.assertEqual(comment.id, 8387331)72 def testGetIssueComments(self):73 self.assertListKeyEqual(self.pull.get_issue_comments(), lambda c: c.id, [8387331])74 def testGetIssueComment(self):75 comment = self.pull.get_issue_comment(8387331)76 self.assertEqual(comment.body, "Issue comment created by PyGithub")77 def testEditWithoutArguments(self):78 self.pull.edit()79 def testEditWithAllArguments(self):80 self.pull.edit("Title edited by PyGithub", "Body edited by PyGithub", "open")81 self.assertEqual(self.pull.title, "Title edited by PyGithub")82 self.assertEqual(self.pull.body, "Body edited by PyGithub")83 self.assertEqual(self.pull.state, "open")84 def testGetCommits(self):85 self.assertListKeyEqual(self.pull.get_commits(), lambda c: c.sha, ["4aadfff21cdd2d2566b0e4bd7309c233b5f4ae23", "93dcae5cf207de376c91d0599226e7c7563e1d16", "8a4f306d4b223682dd19410d4a9150636ebe4206"])86 def testGetFiles(self):87 self.assertListKeyEqual(self.pull.get_files(), lambda f: f.filename, ["codegen/templates/GithubObject.py", "src/github/AuthenticatedUser.py", "src/github/Authorization.py", "src/github/Branch.py", "src/github/Commit.py", "src/github/CommitComment.py", "src/github/CommitFile.py", "src/github/CommitStats.py", "src/github/Download.py", "src/github/Event.py", "src/github/Gist.py", "src/github/GistComment.py", "src/github/GistHistoryState.py", "src/github/GitAuthor.py", "src/github/GitBlob.py", "src/github/GitCommit.py", "src/github/GitObject.py", "src/github/GitRef.py", "src/github/GitTag.py", "src/github/GitTree.py", "src/github/GitTreeElement.py", "src/github/Hook.py", "src/github/Issue.py", "src/github/IssueComment.py", "src/github/IssueEvent.py", "src/github/Label.py", "src/github/Milestone.py", "src/github/NamedUser.py", "src/github/Organization.py", "src/github/Permissions.py", "src/github/Plan.py", "src/github/PullRequest.py", "src/github/PullRequestComment.py", "src/github/PullRequestFile.py", "src/github/Repository.py", "src/github/RepositoryKey.py", "src/github/Tag.py", "src/github/Team.py", "src/github/UserKey.py", "test/Issue.py", "test/IssueEvent.py", "test/ReplayData/Issue.testAddAndRemoveLabels.txt", "test/ReplayData/Issue.testDeleteAndSetLabels.txt", "test/ReplayData/Issue.testGetLabels.txt", "test/ReplayData/IssueEvent.setUp.txt"])88 def testMerge(self):89 self.assertFalse(self.pull.is_merged())90 status = self.pull.merge()91 self.assertEqual(status.sha, "688208b1a5a074871d0e9376119556897439697d")92 self.assertTrue(status.merged)93 self.assertEqual(status.message, "Pull Request successfully merged")94 self.assertTrue(self.pull.is_merged())95 def testMergeWithCommitMessage(self):...

Full Screen

Full Screen

dth.py

Source:dth.py Github

copy

Full Screen

1import time2from machine import enable_irq, disable_irq, Pin3class DTHResult:4 'DHT sensor result returned by DHT.read() method'5 ERR_NO_ERROR = 06 ERR_MISSING_DATA = 17 ERR_CRC = 28 error_code = ERR_NO_ERROR9 temperature = -110 humidity = -111 def __init__(self, error_code, temperature, humidity):12 self.error_code = error_code13 self.temperature = temperature14 self.humidity = humidity15 def is_valid(self):16 return self.error_code == DTHResult.ERR_NO_ERROR17class DTH:18 'DHT sensor (dht11, dht21,dht22) reader class for Pycom'19 #__pin = Pin('P3', mode=Pin.OPEN_DRAIN)20 __dhttype = 021 def __init__(self, pin, sensor=0):22 self.__pin = pin23 self.__dhttype = sensor24 self.__pin(1)25 time.sleep(1.0)26 def read(self):27 #time.sleep(1)28 # send initial high29 #self.__send_and_sleep(1, 0.025)30 # pull down to low31 self.__send_and_sleep(0, 0.019)32 # collect data into an array33 data = self.__collect_input()34 #print(data)35 # parse lengths of all data pull up periods36 pull_up_lengths = self.__parse_data_pull_up_lengths(data)37 # if bit count mismatch, return error (4 byte data + 1 byte checksum)38 #print(pull_up_lengths)39 #print(len(pull_up_lengths))40 if len(pull_up_lengths) != 40:41 return DTHResult(DTHResult.ERR_MISSING_DATA, 0, 0)42 # calculate bits from lengths of the pull up periods43 bits = self.__calculate_bits(pull_up_lengths)44 # we have the bits, calculate bytes45 the_bytes = self.__bits_to_bytes(bits)46 #print(the_bytes)47 # calculate checksum and check48 checksum = self.__calculate_checksum(the_bytes)49 if the_bytes[4] != checksum:50 return DTHResult(DTHResult.ERR_CRC, 0, 0)51 # ok, we have valid data, return it52 [int_rh, dec_rh, int_t, dec_t, csum] = the_bytes53 if self.__dhttype==0: #dht1154 rh = int_rh #dht11 20% ~ 90%55 t = int_t #dht11 0..50°C56 else: #dht21,dht2257 rh = ((int_rh * 256) + dec_rh)/1058 t = (((int_t & 0x7F) * 256) + dec_t)/1059 if (int_t & 0x80) > 0:60 t *= -161 return DTHResult(DTHResult.ERR_NO_ERROR, t, rh)62 def __send_and_sleep(self, output, mysleep):63 self.__pin(output)64 time.sleep(mysleep)65 def __collect_input(self):66 # collect the data while unchanged found67 unchanged_count = 068 # this is used to determine where is the end of the data69 max_unchanged_count = 10070 last = -171 data = []72 m = bytearray(800) # needs long sample size to grab all the bits from the DHT73 irqf = disable_irq()74 self.__pin(1)75 for i in range(len(m)):76 m[i] = self.__pin() ## sample input and store value77 enable_irq(irqf)78 for i in range(len(m)):79 current = m[i]80 data.append(current)81 if last != current:82 unchanged_count = 083 last = current84 else:85 unchanged_count += 186 if unchanged_count > max_unchanged_count:87 break88 #print(data)89 return data90 def __parse_data_pull_up_lengths(self, data):91 STATE_INIT_PULL_DOWN = 192 STATE_INIT_PULL_UP = 293 STATE_DATA_FIRST_PULL_DOWN = 394 STATE_DATA_PULL_UP = 495 STATE_DATA_PULL_DOWN = 596 state = STATE_INIT_PULL_UP97 lengths = [] # will contain the lengths of data pull up periods98 current_length = 0 # will contain the length of the previous period99 for i in range(len(data)):100 current = data[i]101 current_length += 1102 if state == STATE_INIT_PULL_DOWN:103 if current == 0:104 # ok, we got the initial pull down105 state = STATE_INIT_PULL_UP106 continue107 else:108 continue109 if state == STATE_INIT_PULL_UP:110 if current == 1:111 # ok, we got the initial pull up112 state = STATE_DATA_FIRST_PULL_DOWN113 continue114 else:115 continue116 if state == STATE_DATA_FIRST_PULL_DOWN:117 if current == 0:118 # we have the initial pull down, the next will be the data pull up119 state = STATE_DATA_PULL_UP120 continue121 else:122 continue123 if state == STATE_DATA_PULL_UP:124 if current == 1:125 # data pulled up, the length of this pull up will determine whether it is 0 or 1126 current_length = 0127 state = STATE_DATA_PULL_DOWN128 continue129 else:130 continue131 if state == STATE_DATA_PULL_DOWN:132 if current == 0:133 # pulled down, we store the length of the previous pull up period134 lengths.append(current_length)135 state = STATE_DATA_PULL_UP136 continue137 else:138 continue139 return lengths140 def __calculate_bits(self, pull_up_lengths):141 # find shortest and longest period142 shortest_pull_up = 1000143 longest_pull_up = 0144 for i in range(0, len(pull_up_lengths)):145 length = pull_up_lengths[i]146 if length < shortest_pull_up:147 shortest_pull_up = length148 if length > longest_pull_up:149 longest_pull_up = length150 # use the halfway to determine whether the period it is long or short151 halfway = shortest_pull_up + (longest_pull_up - shortest_pull_up) / 2152 bits = []153 for i in range(0, len(pull_up_lengths)):154 bit = False155 if pull_up_lengths[i] > halfway:156 bit = True157 bits.append(bit)158 return bits159 def __bits_to_bytes(self, bits):160 the_bytes = []161 byte = 0162 for i in range(0, len(bits)):163 byte = byte << 1164 if (bits[i]):165 byte = byte | 1166 else:167 byte = byte | 0168 if ((i + 1) % 8 == 0):169 the_bytes.append(byte)170 byte = 0171 #print(the_bytes)172 return the_bytes173 def __calculate_checksum(self, the_bytes):...

Full Screen

Full Screen

__init__.py

Source:__init__.py Github

copy

Full Screen

1import time2import RPi3class DHT11Result:4 'DHT11 sensor result returned by DHT11.read() method'5 ERR_NO_ERROR = 06 ERR_MISSING_DATA = 17 ERR_CRC = 28 error_code = ERR_NO_ERROR9 temperature = -110 humidity = -111 def __init__(self, error_code, temperature, humidity):12 self.error_code = error_code13 self.temperature = temperature14 self.humidity = humidity15 def is_valid(self):16 return self.error_code == DHT11Result.ERR_NO_ERROR17class DHT11:18 'DHT11 sensor reader class for Raspberry'19 __pin = 020 def __init__(self, pin):21 self.__pin = pin22 def read(self):23 RPi.GPIO.setup(self.__pin, RPi.GPIO.OUT)24 # send initial high25 self.__send_and_sleep(RPi.GPIO.HIGH, 0.05)26 # pull down to low27 self.__send_and_sleep(RPi.GPIO.LOW, 0.02)28 # change to input using pull up29 RPi.GPIO.setup(self.__pin, RPi.GPIO.IN, RPi.GPIO.PUD_UP)30 # collect data into an array31 data = self.__collect_input()32 # parse lengths of all data pull up periods33 pull_up_lengths = self.__parse_data_pull_up_lengths(data)34 # if bit count mismatch, return error (4 byte data + 1 byte checksum)35 if len(pull_up_lengths) != 40:36 return DHT11Result(DHT11Result.ERR_MISSING_DATA, 0, 0)37 # calculate bits from lengths of the pull up periods38 bits = self.__calculate_bits(pull_up_lengths)39 # we have the bits, calculate bytes40 the_bytes = self.__bits_to_bytes(bits)41 # calculate checksum and check42 checksum = self.__calculate_checksum(the_bytes)43 if the_bytes[4] != checksum:44 return DHT11Result(DHT11Result.ERR_CRC, 0, 0)45 # ok, we have valid data46 # The meaning of the return sensor values47 # the_bytes[0]: humidity int48 # the_bytes[1]: humidity decimal49 # the_bytes[2]: temperature int50 # the_bytes[3]: temperature decimal51 temperature = the_bytes[2] + float(the_bytes[3]) / 1052 humidity = the_bytes[0] + float(the_bytes[1]) / 1053 return DHT11Result(DHT11Result.ERR_NO_ERROR, temperature, humidity)54 def __send_and_sleep(self, output, sleep):55 RPi.GPIO.output(self.__pin, output)56 time.sleep(sleep)57 def __collect_input(self):58 # collect the data while unchanged found59 unchanged_count = 060 # this is used to determine where is the end of the data61 max_unchanged_count = 10062 last = -163 data = []64 while True:65 current = RPi.GPIO.input(self.__pin)66 data.append(current)67 if last != current:68 unchanged_count = 069 last = current70 else:71 unchanged_count += 172 if unchanged_count > max_unchanged_count:73 break74 return data75 def __parse_data_pull_up_lengths(self, data):76 STATE_INIT_PULL_DOWN = 177 STATE_INIT_PULL_UP = 278 STATE_DATA_FIRST_PULL_DOWN = 379 STATE_DATA_PULL_UP = 480 STATE_DATA_PULL_DOWN = 581 state = STATE_INIT_PULL_DOWN82 lengths = [] # will contain the lengths of data pull up periods83 current_length = 0 # will contain the length of the previous period84 for i in range(len(data)):85 current = data[i]86 current_length += 187 if state == STATE_INIT_PULL_DOWN:88 if current == RPi.GPIO.LOW:89 # ok, we got the initial pull down90 state = STATE_INIT_PULL_UP91 continue92 else:93 continue94 if state == STATE_INIT_PULL_UP:95 if current == RPi.GPIO.HIGH:96 # ok, we got the initial pull up97 state = STATE_DATA_FIRST_PULL_DOWN98 continue99 else:100 continue101 if state == STATE_DATA_FIRST_PULL_DOWN:102 if current == RPi.GPIO.LOW:103 # we have the initial pull down, the next will be the data pull up104 state = STATE_DATA_PULL_UP105 continue106 else:107 continue108 if state == STATE_DATA_PULL_UP:109 if current == RPi.GPIO.HIGH:110 # data pulled up, the length of this pull up will determine whether it is 0 or 1111 current_length = 0112 state = STATE_DATA_PULL_DOWN113 continue114 else:115 continue116 if state == STATE_DATA_PULL_DOWN:117 if current == RPi.GPIO.LOW:118 # pulled down, we store the length of the previous pull up period119 lengths.append(current_length)120 state = STATE_DATA_PULL_UP121 continue122 else:123 continue124 return lengths125 def __calculate_bits(self, pull_up_lengths):126 # find shortest and longest period127 shortest_pull_up = 1000128 longest_pull_up = 0129 for i in range(0, len(pull_up_lengths)):130 length = pull_up_lengths[i]131 if length < shortest_pull_up:132 shortest_pull_up = length133 if length > longest_pull_up:134 longest_pull_up = length135 # use the halfway to determine whether the period it is long or short136 halfway = shortest_pull_up + (longest_pull_up - shortest_pull_up) / 2137 bits = []138 for i in range(0, len(pull_up_lengths)):139 bit = False140 if pull_up_lengths[i] > halfway:141 bit = True142 bits.append(bit)143 return bits144 def __bits_to_bytes(self, bits):145 the_bytes = []146 byte = 0147 for i in range(0, len(bits)):148 byte = byte << 1149 if (bits[i]):150 byte = byte | 1151 else:152 byte = byte | 0153 if ((i + 1) % 8 == 0):154 the_bytes.append(byte)155 byte = 0156 return the_bytes157 def __calculate_checksum(self, the_bytes):...

Full Screen

Full Screen

pullToRefresh.js

Source:pullToRefresh.js Github

copy

Full Screen

1/*!2 * pull to refresh v2.03 *author:wallace4 *2015-7-225 */6var refresher = {7 info: {8 "pullDownLable": "Pull down to refresh...",9 "pullingDownLable": "Release to refresh...",10 "pullUpLable": "上滑加载更多...",11 "pullingUpLable": "Release to load more...",12 "loadingLable": "Loading..."13 },14 init: function(parameter) {15 var wrapper = document.getElementById(parameter.id);16 var div = document.createElement("div");17 div.className = "scroller";18 wrapper.appendChild(div);19 var scroller = wrapper.querySelector(".scroller");20 var list = wrapper.querySelector("#" + parameter.id + " ul");21 scroller.insertBefore(list, scroller.childNodes[0]);22 var pullDown = document.createElement("div");23 pullDown.className = "pullDown";24 var loader = document.createElement("div");25 loader.className = "loader";26 for (var i = 0; i < 4; i++) {27 var span = document.createElement("span");28 loader.appendChild(span);29 }30 pullDown.appendChild(loader);31 var pullDownLabel = document.createElement("div");32 pullDownLabel.className = "pullDownLabel";33 pullDown.appendChild(pullDownLabel);34 scroller.insertBefore(pullDown, scroller.childNodes[0]);35 var pullUp = document.createElement("div");36 pullUp.className = "pullUp";37 var loader = document.createElement("div");38 loader.className = "loader";39 for (var i = 0; i < 4; i++) {40 var span = document.createElement("span");41 loader.appendChild(span);42 }43 pullUp.appendChild(loader);44 var pullUpLabel = document.createElement("div");45 pullUpLabel.className = "pullUpLabel";46 var content = document.createTextNode(refresher.info.pullUpLable);47 pullUpLabel.appendChild(content);48 pullUp.appendChild(pullUpLabel);49 scroller.appendChild(pullUp);50 var pullDownEl = wrapper.querySelector(".pullDown");51 var pullDownOffset = pullDownEl.offsetHeight;52 var pullUpEl = wrapper.querySelector(".pullUp");53 var pullUpOffset = pullUpEl.offsetHeight;54 this.scrollIt(parameter, pullDownEl, pullDownOffset, pullUpEl, pullUpOffset);55 },56 scrollIt: function(parameter, pullDownEl, pullDownOffset, pullUpEl, pullUpOffset) {57 eval(parameter.id + "= new iScroll(parameter.id, {useTransition: true,vScrollbar: false,topOffset: pullDownOffset,onRefresh: function () {refresher.onRelease(pullDownEl,pullUpEl);},onScrollMove: function () {refresher.onScrolling(this,pullDownEl,pullUpEl,pullUpOffset);},onScrollEnd: function () {refresher.onPulling(pullDownEl,parameter.pullDownAction,pullUpEl,parameter.pullUpAction);},})");58 pullDownEl.querySelector('.pullDownLabel').innerHTML = refresher.info.pullDownLable;59 document.addEventListener('touchmove', function(e) {60 e.preventDefault();61 }, false);62 },63 onScrolling: function(e, pullDownEl, pullUpEl, pullUpOffset) {64 if (e.y > -(pullUpOffset)) {65 pullDownEl.id = '';66 pullDownEl.querySelector('.pullDownLabel').innerHTML = refresher.info.pullDownLable;67 e.minScrollY = -pullUpOffset;68 }69 if (e.y > 0) {70 pullDownEl.classList.add("flip");71 pullDownEl.querySelector('.pullDownLabel').innerHTML = refresher.info.pullingDownLable;72 e.minScrollY = 0;73 }74 if (e.scrollerH < e.wrapperH && e.y < (e.minScrollY - pullUpOffset) || e.scrollerH > e.wrapperH && e.y < (e.maxScrollY - pullUpOffset)) {75 pullUpEl.style.display = "block";76 pullUpEl.classList.add("flip");77 pullUpEl.querySelector('.pullUpLabel').innerHTML = refresher.info.pullingUpLable;78 }79 if (e.scrollerH < e.wrapperH && e.y > (e.minScrollY - pullUpOffset) && pullUpEl.id.match('flip') || e.scrollerH > e.wrapperH && e.y > (e.maxScrollY - pullUpOffset) && pullUpEl.id.match('flip')) {80 pullDownEl.classList.remove("flip");81 pullUpEl.querySelector('.pullUpLabel').innerHTML = refresher.info.pullUpLable;82 }83 },84 onRelease: function(pullDownEl, pullUpEl) {85 if (pullDownEl.className.match('loading')) {86 pullDownEl.classList.toggle("loading");87 pullDownEl.querySelector('.pullDownLabel').innerHTML = refresher.info.pullDownLable;88 pullDownEl.querySelector('.loader').style.display = "none"89 pullDownEl.style.lineHeight = pullDownEl.offsetHeight + "px";90 }91 if (pullUpEl.className.match('loading')) {92 pullUpEl.classList.toggle("loading");93 pullUpEl.querySelector('.pullUpLabel').innerHTML = refresher.info.pullUpLable;94 pullUpEl.querySelector('.loader').style.display = "none"95 pullUpEl.style.lineHeight = pullUpEl.offsetHeight + "px";96 }97 },98 onPulling: function(pullDownEl, pullDownAction, pullUpEl, pullUpAction) {99 if (pullDownEl.className.match('flip') /*&&!pullUpEl.className.match('loading')*/ ) {100 pullDownEl.classList.add("loading");101 pullDownEl.classList.remove("flip");102 pullDownEl.querySelector('.pullDownLabel').innerHTML = refresher.info.loadingLable;103 pullDownEl.querySelector('.loader').style.display = "block"104 pullDownEl.style.lineHeight = "20px";105 if (pullDownAction) pullDownAction();106 }107 if (pullUpEl.className.match('flip') /*&&!pullDownEl.className.match('loading')*/ ) {108 pullUpEl.classList.add("loading");109 pullUpEl.classList.remove("flip");110 pullUpEl.querySelector('.pullUpLabel').innerHTML = refresher.info.loadingLable;111 pullUpEl.querySelector('.loader').style.display = "block"112 pullUpEl.style.lineHeight = "20px";113 if (pullUpAction) pullUpAction();114 }115 } ...

Full Screen

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