How to use CipherTransform method in wpt

Best JavaScript code snippet using wpt

parser.js

Source:parser.js Github

copy

Full Screen

1/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */2/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */3/* Copyright 2012 Mozilla Foundation4 *5 * Licensed under the Apache License, Version 2.0 (the "License");6 * you may not use this file except in compliance with the License.7 * You may obtain a copy of the License at8 *9 * http://www.apache.org/licenses/LICENSE-2.010 *11 * Unless required by applicable law or agreed to in writing, software12 * distributed under the License is distributed on an "AS IS" BASIS,13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.14 * See the License for the specific language governing permissions and15 * limitations under the License.16 */17/* globals Ascii85Stream, AsciiHexStream, CCITTFaxStream, Cmd, Dict, error,18 FlateStream, isArray, isCmd, isDict, isInt, isName, isNum, isRef,19 isString, Jbig2Stream, JpegStream, JpxStream, LZWStream, Name,20 NullStream, PredictorStream, Ref, RunLengthStream, warn */21'use strict';22var EOF = {};23function isEOF(v) {24 return v == EOF;25}26var Parser = (function ParserClosure() {27 function Parser(lexer, allowStreams, xref) {28 this.lexer = lexer;29 this.allowStreams = allowStreams;30 this.xref = xref;31 this.refill();32 }33 Parser.prototype = {34 refill: function Parser_refill() {35 this.buf1 = this.lexer.getObj();36 this.buf2 = this.lexer.getObj();37 },38 shift: function Parser_shift() {39 if (isCmd(this.buf2, 'ID')) {40 this.buf1 = this.buf2;41 this.buf2 = null;42 // skip byte after ID43 this.lexer.skip();44 } else {45 this.buf1 = this.buf2;46 this.buf2 = this.lexer.getObj();47 }48 },49 getObj: function Parser_getObj(cipherTransform) {50 if (isCmd(this.buf1, 'BI')) { // inline image51 this.shift();52 return this.makeInlineImage(cipherTransform);53 }54 if (isCmd(this.buf1, '[')) { // array55 this.shift();56 var array = [];57 while (!isCmd(this.buf1, ']') && !isEOF(this.buf1))58 array.push(this.getObj());59 if (isEOF(this.buf1))60 error('End of file inside array');61 this.shift();62 return array;63 }64 if (isCmd(this.buf1, '<<')) { // dictionary or stream65 this.shift();66 var dict = new Dict(this.xref);67 while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) {68 if (!isName(this.buf1))69 error('Dictionary key must be a name object');70 var key = this.buf1.name;71 this.shift();72 if (isEOF(this.buf1))73 break;74 dict.set(key, this.getObj(cipherTransform));75 }76 if (isEOF(this.buf1))77 error('End of file inside dictionary');78 // stream objects are not allowed inside content streams or79 // object streams80 if (isCmd(this.buf2, 'stream')) {81 return this.allowStreams ?82 this.makeStream(dict, cipherTransform) : dict;83 }84 this.shift();85 return dict;86 }87 if (isInt(this.buf1)) { // indirect reference or integer88 var num = this.buf1;89 this.shift();90 if (isInt(this.buf1) && isCmd(this.buf2, 'R')) {91 var ref = new Ref(num, this.buf1);92 this.shift();93 this.shift();94 return ref;95 }96 return num;97 }98 if (isString(this.buf1)) { // string99 var str = this.buf1;100 this.shift();101 if (cipherTransform)102 str = cipherTransform.decryptString(str);103 return str;104 }105 // simple object106 var obj = this.buf1;107 this.shift();108 return obj;109 },110 makeInlineImage: function Parser_makeInlineImage(cipherTransform) {111 var lexer = this.lexer;112 var stream = lexer.stream;113 // parse dictionary114 var dict = new Dict();115 while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) {116 if (!isName(this.buf1))117 error('Dictionary key must be a name object');118 var key = this.buf1.name;119 this.shift();120 if (isEOF(this.buf1))121 break;122 dict.set(key, this.getObj(cipherTransform));123 }124 // parse image stream125 var startPos = stream.pos;126 // searching for the /EI\s/127 var state = 0, ch;128 while (state != 4 &&129 (ch = stream.getByte()) !== null && ch !== undefined) {130 switch (ch) {131 case 0x20:132 case 0x0D:133 case 0x0A:134 state = state === 3 ? 4 : 0;135 break;136 case 0x45:137 state = 2;138 break;139 case 0x49:140 state = state === 2 ? 3 : 0;141 break;142 default:143 state = 0;144 break;145 }146 }147 var length = (stream.pos - 4) - startPos;148 var imageStream = stream.makeSubStream(startPos, length, dict);149 if (cipherTransform)150 imageStream = cipherTransform.createStream(imageStream);151 imageStream = this.filter(imageStream, dict, length);152 imageStream.parameters = dict;153 this.buf2 = Cmd.get('EI');154 this.shift();155 return imageStream;156 },157 fetchIfRef: function Parser_fetchIfRef(obj) {158 // not relying on the xref.fetchIfRef -- xref might not be set159 return isRef(obj) ? this.xref.fetch(obj) : obj;160 },161 makeStream: function Parser_makeStream(dict, cipherTransform) {162 var lexer = this.lexer;163 var stream = lexer.stream;164 // get stream start position165 lexer.skipToNextLine();166 var pos = stream.pos;167 // get length168 var length = this.fetchIfRef(dict.get('Length'));169 if (!isInt(length))170 error('Bad ' + length + ' attribute in stream');171 // skip over the stream data172 stream.pos = pos + length;173 this.shift(); // '>>'174 this.shift(); // 'stream'175 if (!isCmd(this.buf1, 'endstream'))176 error('Missing endstream');177 this.shift();178 stream = stream.makeSubStream(pos, length, dict);179 if (cipherTransform)180 stream = cipherTransform.createStream(stream);181 stream = this.filter(stream, dict, length);182 stream.parameters = dict;183 return stream;184 },185 filter: function Parser_filter(stream, dict, length) {186 var filter = this.fetchIfRef(dict.get('Filter', 'F'));187 var params = this.fetchIfRef(dict.get('DecodeParms', 'DP'));188 if (isName(filter))189 return this.makeFilter(stream, filter.name, length, params);190 if (isArray(filter)) {191 var filterArray = filter;192 var paramsArray = params;193 for (var i = 0, ii = filterArray.length; i < ii; ++i) {194 filter = filterArray[i];195 if (!isName(filter))196 error('Bad filter name: ' + filter);197 params = null;198 if (isArray(paramsArray) && (i in paramsArray))199 params = paramsArray[i];200 stream = this.makeFilter(stream, filter.name, length, params);201 // after the first stream the length variable is invalid202 length = null;203 }204 }205 return stream;206 },207 makeFilter: function Parser_makeFilter(stream, name, length, params) {208 if (stream.dict.get('Length') === 0) {209 return new NullStream(stream);210 }211 if (name == 'FlateDecode' || name == 'Fl') {212 if (params) {213 return new PredictorStream(new FlateStream(stream), params);214 }215 return new FlateStream(stream);216 }217 if (name == 'LZWDecode' || name == 'LZW') {218 var earlyChange = 1;219 if (params) {220 if (params.has('EarlyChange'))221 earlyChange = params.get('EarlyChange');222 return new PredictorStream(223 new LZWStream(stream, earlyChange), params);224 }225 return new LZWStream(stream, earlyChange);226 }227 if (name == 'DCTDecode' || name == 'DCT') {228 var bytes = stream.getBytes(length);229 return new JpegStream(bytes, stream.dict, this.xref);230 }231 if (name == 'JPXDecode' || name == 'JPX') {232 var bytes = stream.getBytes(length);233 return new JpxStream(bytes, stream.dict);234 }235 if (name == 'ASCII85Decode' || name == 'A85') {236 return new Ascii85Stream(stream);237 }238 if (name == 'ASCIIHexDecode' || name == 'AHx') {239 return new AsciiHexStream(stream);240 }241 if (name == 'CCITTFaxDecode' || name == 'CCF') {242 return new CCITTFaxStream(stream, params);243 }244 if (name == 'RunLengthDecode' || name == 'RL') {245 return new RunLengthStream(stream);246 }247 if (name == 'JBIG2Decode') {248 var bytes = stream.getBytes(length);249 return new Jbig2Stream(bytes, stream.dict);250 }251 warn('filter "' + name + '" not supported yet');252 return stream;253 }254 };255 return Parser;256})();257var Lexer = (function LexerClosure() {258 function Lexer(stream, knownCommands) {259 this.stream = stream;260 // The PDFs might have "glued" commands with other commands, operands or261 // literals, e.g. "q1". The knownCommands is a dictionary of the valid262 // commands and their prefixes. The prefixes are built the following way:263 // if there a command that is a prefix of the other valid command or264 // literal (e.g. 'f' and 'false') the following prefixes must be included,265 // 'fa', 'fal', 'fals'. The prefixes are not needed, if the command has no266 // other commands or literals as a prefix. The knowCommands is optional.267 this.knownCommands = knownCommands;268 }269 Lexer.isSpace = function Lexer_isSpace(ch) {270 return ch == ' ' || ch == '\t' || ch == '\x0d' || ch == '\x0a';271 };272 // A '1' in this array means the character is white space. A '1' or273 // '2' means the character ends a name or command.274 var specialChars = [275 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x276 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x277 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x278 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x279 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x280 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x281 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x282 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x283 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x284 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x285 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax286 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx287 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx288 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx289 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex290 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx291 ];292 function toHexDigit(ch) {293 if (ch >= '0' && ch <= '9')294 return ch.charCodeAt(0) - 48;295 ch = ch.toUpperCase();296 if (ch >= 'A' && ch <= 'F')297 return ch.charCodeAt(0) - 55;298 return -1;299 }300 Lexer.prototype = {301 getNumber: function Lexer_getNumber(ch) {302 var floating = false;303 var str = ch;304 var stream = this.stream;305 while ((ch = stream.lookChar())) {306 if (ch == '.' && !floating) {307 str += ch;308 floating = true;309 } else if (ch == '-') {310 // ignore minus signs in the middle of numbers to match311 // Adobe's behavior312 warn('Badly formated number');313 } else if (ch >= '0' && ch <= '9') {314 str += ch;315 } else if (ch == 'e' || ch == 'E') {316 floating = true;317 } else {318 // the last character doesn't belong to us319 break;320 }321 stream.skip();322 }323 var value = parseFloat(str);324 if (isNaN(value))325 error('Invalid floating point number: ' + value);326 return value;327 },328 getString: function Lexer_getString() {329 var numParen = 1;330 var done = false;331 var str = '';332 var stream = this.stream;333 var ch;334 do {335 ch = stream.getChar();336 switch (ch) {337 case undefined:338 warn('Unterminated string');339 done = true;340 break;341 case '(':342 ++numParen;343 str += ch;344 break;345 case ')':346 if (--numParen === 0) {347 done = true;348 } else {349 str += ch;350 }351 break;352 case '\\':353 ch = stream.getChar();354 switch (ch) {355 case undefined:356 warn('Unterminated string');357 done = true;358 break;359 case 'n':360 str += '\n';361 break;362 case 'r':363 str += '\r';364 break;365 case 't':366 str += '\t';367 break;368 case 'b':369 str += '\b';370 break;371 case 'f':372 str += '\f';373 break;374 case '\\':375 case '(':376 case ')':377 str += ch;378 break;379 case '0': case '1': case '2': case '3':380 case '4': case '5': case '6': case '7':381 var x = ch - '0';382 ch = stream.lookChar();383 if (ch >= '0' && ch <= '7') {384 stream.skip();385 x = (x << 3) + (ch - '0');386 ch = stream.lookChar();387 if (ch >= '0' && ch <= '7') {388 stream.skip();389 x = (x << 3) + (ch - '0');390 }391 }392 str += String.fromCharCode(x);393 break;394 case '\r':395 ch = stream.lookChar();396 if (ch == '\n')397 stream.skip();398 break;399 case '\n':400 break;401 default:402 str += ch;403 }404 break;405 default:406 str += ch;407 }408 } while (!done);409 return str;410 },411 getName: function Lexer_getName(ch) {412 var str = '';413 var stream = this.stream;414 while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {415 stream.skip();416 if (ch == '#') {417 ch = stream.lookChar();418 var x = toHexDigit(ch);419 if (x != -1) {420 stream.skip();421 var x2 = toHexDigit(stream.getChar());422 if (x2 == -1)423 error('Illegal digit in hex char in name: ' + x2);424 str += String.fromCharCode((x << 4) | x2);425 } else {426 str += '#';427 str += ch;428 }429 } else {430 str += ch;431 }432 }433 if (str.length > 128)434 error('Warning: name token is longer than allowed by the spec: ' +435 str.length);436 return new Name(str);437 },438 getHexString: function Lexer_getHexString(ch) {439 var str = '';440 var stream = this.stream;441 var isFirstHex = true;442 var firstDigit;443 var secondDigit;444 while (true) {445 ch = stream.getChar();446 if (!ch) {447 warn('Unterminated hex string');448 break;449 } else if (ch === '>') {450 break;451 } else if (specialChars[ch.charCodeAt(0)] === 1) {452 continue;453 } else {454 if (isFirstHex) {455 firstDigit = toHexDigit(ch);456 if (firstDigit === -1) {457 warn('Ignoring invalid character "' + ch + '" in hex string');458 continue;459 }460 } else {461 secondDigit = toHexDigit(ch);462 if (secondDigit === -1) {463 warn('Ignoring invalid character "' + ch + '" in hex string');464 continue;465 }466 str += String.fromCharCode((firstDigit << 4) | secondDigit);467 }468 isFirstHex = !isFirstHex;469 }470 }471 return str;472 },473 getObj: function Lexer_getObj() {474 // skip whitespace and comments475 var comment = false;476 var stream = this.stream;477 var ch;478 while (true) {479 if (!(ch = stream.getChar()))480 return EOF;481 if (comment) {482 if (ch == '\r' || ch == '\n')483 comment = false;484 } else if (ch == '%') {485 comment = true;486 } else if (specialChars[ch.charCodeAt(0)] != 1) {487 break;488 }489 }490 // start reading token491 switch (ch) {492 case '0': case '1': case '2': case '3': case '4':493 case '5': case '6': case '7': case '8': case '9':494 case '+': case '-': case '.':495 return this.getNumber(ch);496 case '(':497 return this.getString();498 case '/':499 return this.getName(ch);500 // array punctuation501 case '[':502 case ']':503 return Cmd.get(ch);504 // hex string or dict punctuation505 case '<':506 ch = stream.lookChar();507 if (ch == '<') {508 // dict punctuation509 stream.skip();510 return Cmd.get('<<');511 }512 return this.getHexString(ch);513 // dict punctuation514 case '>':515 ch = stream.lookChar();516 if (ch == '>') {517 stream.skip();518 return Cmd.get('>>');519 }520 return Cmd.get(ch);521 case '{':522 case '}':523 return Cmd.get(ch);524 // fall through525 case ')':526 error('Illegal character: ' + ch);527 }528 // command529 var str = ch;530 var knownCommands = this.knownCommands;531 var knownCommandFound = knownCommands && (str in knownCommands);532 while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {533 // stop if known command is found and next character does not make534 // the str a command535 if (knownCommandFound && !((str + ch) in knownCommands))536 break;537 stream.skip();538 if (str.length == 128)539 error('Command token too long: ' + str.length);540 str += ch;541 knownCommandFound = knownCommands && (str in knownCommands);542 }543 if (str == 'true')544 return true;545 if (str == 'false')546 return false;547 if (str == 'null')548 return null;549 return Cmd.get(str);550 },551 skipToNextLine: function Lexer_skipToNextLine() {552 var stream = this.stream;553 while (true) {554 var ch = stream.getChar();555 if (!ch || ch == '\n')556 return;557 if (ch == '\r') {558 if ((ch = stream.lookChar()) == '\n')559 stream.skip();560 return;561 }562 }563 },564 skip: function Lexer_skip() {565 this.stream.skip();566 }567 };568 return Lexer;569})();570var Linearization = (function LinearizationClosure() {571 function Linearization(stream) {572 this.parser = new Parser(new Lexer(stream), false, null);573 var obj1 = this.parser.getObj();574 var obj2 = this.parser.getObj();575 var obj3 = this.parser.getObj();576 this.linDict = this.parser.getObj();577 if (isInt(obj1) && isInt(obj2) && isCmd(obj3, 'obj') &&578 isDict(this.linDict)) {579 var obj = this.linDict.get('Linearized');580 if (!(isNum(obj) && obj > 0))581 this.linDict = null;582 }583 }584 Linearization.prototype = {585 getInt: function Linearization_getInt(name) {586 var linDict = this.linDict;587 var obj;588 if (isDict(linDict) &&589 isInt(obj = linDict.get(name)) &&590 obj > 0) {591 return obj;592 }593 error('"' + name + '" field in linearization table is invalid');594 },595 getHint: function Linearization_getHint(index) {596 var linDict = this.linDict;597 var obj1, obj2;598 if (isDict(linDict) &&599 isArray(obj1 = linDict.get('H')) &&600 obj1.length >= 2 &&601 isInt(obj2 = obj1[index]) &&602 obj2 > 0) {603 return obj2;604 }605 error('Hints table in linearization table is invalid: ' + index);606 },607 get length() {608 if (!isDict(this.linDict))609 return 0;610 return this.getInt('L');611 },612 get hintsOffset() {613 return this.getHint(0);614 },615 get hintsLength() {616 return this.getHint(1);617 },618 get hintsOffset2() {619 return this.getHint(2);620 },621 get hintsLenth2() {622 return this.getHint(3);623 },624 get objectNumberFirst() {625 return this.getInt('O');626 },627 get endFirst() {628 return this.getInt('E');629 },630 get numPages() {631 return this.getInt('N');632 },633 get mainXRefEntriesOffset() {634 return this.getInt('T');635 },636 get pageFirst() {637 return this.getInt('P');638 }639 };640 return Linearization;...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var crypto = require('crypto');2var fs = require('fs');3var wpt = require('wpt');4var cipher = crypto.createCipher('aes192', 'a password');5var input = fs.createReadStream('test.txt');6var output = fs.createWriteStream('test.txt.enc');7input.pipe(cipher).pipe(output);8var crypto = require('crypto');9var fs = require('fs');10var wpt = require('wpt');11var decipher = crypto.createDecipher('aes192', 'a password');12var input = fs.createReadStream('test.txt.enc');13var output = fs.createWriteStream('test.txt.dec');14input.pipe(decipher).pipe(output);15var crypto = require('crypto');16var fs = require('fs');17var wpt = require('wpt');18var cipher = crypto.createCipher('aes192', 'a password');19var input = fs.createReadStream('test.txt');20var output = fs.createWriteStream('test.txt.enc');21input.pipe(cipher).pipe(output);22var crypto = require('crypto');23var fs = require('fs');24var wpt = require('wpt');25var decipher = crypto.createDecipher('aes192', 'a password');26var input = fs.createReadStream('test.txt.enc');27var output = fs.createWriteStream('test.txt.dec');28input.pipe(decipher).pipe(output);29var crypto = require('crypto');30var fs = require('fs');31var wpt = require('wpt');32var cipher = crypto.createCipher('aes192', 'a password');33var input = fs.createReadStream('test.txt');34var output = fs.createWriteStream('test.txt.enc');35input.pipe(cipher).pipe(output);36var crypto = require('crypto');37var fs = require('fs');38var wpt = require('wpt');39var decipher = crypto.createDecipher('aes192', 'a password');40var input = fs.createReadStream('test.txt.enc');41var output = fs.createWriteStream('test.txt.dec');42input.pipe(decipher).pipe(output);

Full Screen

Using AI Code Generation

copy

Full Screen

1function runTest() {2 var cipher = new CipherTransform();3 var key = cipher.generateKey();4 var iv = cipher.generateIV();5 var encrypted = cipher.encrypt("Hello World", key, iv);6 var decrypted = cipher.decrypt(encrypted, key, iv);7 postMessage(decrypted);8}9Running test.js on the same machine as the server (localhost) works fine:10Running test.js on a remote machine (

Full Screen

Using AI Code Generation

copy

Full Screen

1var test = require('tape');2var wpt = require('webpage');3var page = wpt.create();4page.open(url, function(status){5 test('status is success', function(t){6 t.equal(status, 'success');7 t.end();8 });9 test('page title is google', function(t){10 var title = page.evaluate(function(){11 return document.title;12 });13 t.equal(title, 'Google');14 t.end();15 });16 test('page title is google', function(t){17 var title = page.evaluate(function(){18 return document.title;19 });20 t.equal(title, 'Google');21 t.end();22 });23 test('page title is google', function(t){24 var title = page.evaluate(function(){25 return document.title;26 });27 t.equal(title, 'Google');28 t.end();29 });30 test('page title is google', function(t){31 var title = page.evaluate(function(){32 return document.title;33 });34 t.equal(title, 'Google');35 t.end();36 });37 test('page title is google', function(t){38 var title = page.evaluate(function(){39 return document.title;40 });41 t.equal(title, 'Google');42 t.end();43 });44 test('page title is google', function(t){45 var title = page.evaluate(function(){46 return document.title;47 });48 t.equal(title, 'Google');49 t.end();50 });51 test('page title is google', function(t){52 var title = page.evaluate(function(){53 return document.title;54 });55 t.equal(title, 'Google');56 t.end();57 });58 test('page title is google', function(t){59 var title = page.evaluate(function(){60 return document.title;61 });62 t.equal(title, 'Google');63 t.end();64 });65 test('page title is google', function(t){66 var title = page.evaluate(function(){67 return document.title;68 });69 t.equal(title, 'Google');70 t.end();71 });72 test('page title is google', function(t){73 var title = page.evaluate(function(){74 return document.title;75 });76 t.equal(title, 'Google');77 t.end();78 });79 test('page title is google', function(t){80 var title = page.evaluate(function(){81 return document.title;82 });83 t.equal(title, 'Google');

Full Screen

Using AI Code Generation

copy

Full Screen

1var testString = "This is a test";2var passphrase = "password";3var encryptedString = CipherTransform(testString, passphrase, true);4var decryptedString = CipherTransform(encryptedString, passphrase, false);5WScript.Echo("Original string: " + testString);6WScript.Echo("Encrypted string: " + encryptedString);7WScript.Echo("Decrypted string: " + decryptedString);

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