How to use aeskw method in wpt

Best JavaScript code snippet using wpt

ekt.js

Source:ekt.js Github

copy

Full Screen

1/** 2* @fileOverview SRTP-EKT implementation 3* @author <a href="jamol@live.com">Fengping Bao</a>4* @version 0.1 5*/6; (function (SrtpJS, undefined) {7 var exports = SrtpJS,8 logger = SrtpJS.logger,9 defs = SrtpJS.defs,10 crypto = SrtpJS.crypto,11 srtp = SrtpJS.srtp || {}12 ;1314 var AESKW_BLOCK_SIZE = 8;1516 function ektEncode(o, ektKey) {17 var plainText,18 cipherText,19 outData,20 spi21 ;22 if (defs.ektType.EKT_TYPE_SHORT == o.type) {23 outData = new Uint8Array(o.data.length + 1);24 outData.set(o.data);25 outData[outData.length - 1] = 0;26 return outData;27 }28 // full EKT field29 plainText = new Uint8Array(o.masterKey.length + 10);30 plainText.set(o.masterKey, 0);31 plainText[o.masterKey.length] = (o.ssrc >>> 24) & 0xFF;32 plainText[o.masterKey.length + 1] = (o.ssrc >>> 16) & 0xFF;33 plainText[o.masterKey.length + 2] = (o.ssrc >>> 8) & 0xFF;34 plainText[o.masterKey.length + 3] = o.ssrc & 0xFF;35 plainText[o.masterKey.length + 4] = (o.roc >>> 24) & 0xFF;36 plainText[o.masterKey.length + 5] = (o.roc >>> 16) & 0xFF;37 plainText[o.masterKey.length + 6] = (o.roc >>> 8) & 0xFF;38 plainText[o.masterKey.length + 7] = o.roc & 0xFF;39 plainText[o.masterKey.length + 8] = (o.isn >>> 8) & 0xFF;40 plainText[o.masterKey.length + 9] = o.isn & 0xFF;4142 cipherText = aeskwWrap(plainText, ektKey);43 spi = o.spi;44 spi = spi << 1;45 spi = spi | 0x01;46 outData = new Uint8Array(o.data.length + cipherText.length + 2);47 outData.set(o.data);48 outData.set(cipherText, o.data.length);49 outData[outData.length - 2] = (spi >>> 8) & 0xFF;50 outData[outData.length - 1] = spi & 0xFF;51 return outData;52 }5354 function ektDecode(data, ektKey) {55 var spi,56 cipherText,57 plainText,58 m, r, o59 ;60 if (data.length <= 2) {61 logger.error("[EKT] ektDecode, invlaid data length: " + data.length);62 return { type: defs.ektType.EKT_TYPE_NULL, desc: "invalid data" };63 }64 if ((data[data.length - 1] & 0x01) == 0) {65 return { type: defs.ektType.EKT_TYPE_SHORT, data: data.subarray(0, data.length - 1) };66 }67 spi = ((data[data.length - 2] & 0xFF) << 8) | (data[data.length - 1] & 0xFF);68 spi = spi >>> 1;69 // TODO: calculate m based on SPI70 m = 16 + 4 + 4 + 2;71 r = (m + 8 + 7) & 0xFFFFFFF8;72 if (data.length < r + 2) {73 logger.error("[EKT] ektDecode, the length is incorrect, length=" + data.length + ", r=" + r);74 return { type: defs.ektType.EKT_TYPE_NULL, desc: "invalid data" };75 }76 cipherText = data.subarray(data.length - r - 2, data.length - 2);77 plainText = aeskwUnwrap(cipherText, ektKey);78 if (null == plainText) {79 return { type: defs.ektType.EKT_TYPE_NULL, desc: "failed to unwrap the key" };80 }81 if (plainText.length != m) {82 logger.error("[EKT] ektDecode, the length is incorrect, length=" + plainText.length + ", m=" + m);83 return { type: defs.ektType.EKT_TYPE_NULL, desc: "invalid data" };84 }85 o = {};86 o.type = defs.ektType.EKT_TYPE_FULL;87 o.isn = ((plainText[plainText.length - 2] & 0xFF) << 8) | (plainText[plainText.length - 1] & 0xFF);88 o.roc = plainText[plainText.length - 3] & 0xFF;89 o.roc |= (plainText[plainText.length - 4] & 0xFF << 8);90 o.roc |= (plainText[plainText.length - 5] & 0xFF << 16);91 o.roc |= (plainText[plainText.length - 6] & 0xFF << 24);92 o.ssrc = plainText[plainText.length - 7] & 0xFF;93 o.ssrc |= (plainText[plainText.length - 8] & 0xFF << 8);94 o.ssrc |= (plainText[plainText.length - 9] & 0xFF << 16);95 o.ssrc |= (plainText[plainText.length - 10] & 0xFF << 24);96 o.masterKey = plainText.subarray(0, plainText.length - 10);97 o.data = data.subarray(0, data.length - r - 2);98 return o;99 }100101 function aeskwWrap(data, key) {102 var dataLength,103 m, n, r, A, B, R, S, t, i, j104 ;105 m = data.length;106 n = Math.ceil(m / AESKW_BLOCK_SIZE);107 r = n * AESKW_BLOCK_SIZE;108 if (r > m) {109 var d1 = new Uint8Array(r);110 d1.set(data);111 for (i = 0; i < r - m; ++i) {112 d1[m + i] = 0;113 }114 data = d1;115 }116 A = new Uint8Array(AESKW_BLOCK_SIZE);117 A.set([0xA6, 0x59, 0x59, 0xA6]);118 A[4] = (m >>> 24) & 0xFF;119 A[5] = (m >>> 16) & 0xFF;120 A[6] = (m >>> 8) & 0xFF;121 A[7] = m & 0xFF;122 S = new Uint8Array(2 * AESKW_BLOCK_SIZE);123124 if (1 == n) {125 S.set(A);126 S.set(data, AESKW_BLOCK_SIZE);127 B = crypto.aesEcbEncrypt(S, key);128 return B;129 }130131 R = new Uint8Array(r + AESKW_BLOCK_SIZE);132 R.set(A);133 R.set(data, AESKW_BLOCK_SIZE);134 A = R.subarray(0, 8);135 for (j = 0; j < 6; ++j) {136 for (i = 1; i < n + 1; ++i) {137 S.set(A);138 S.set(R.subarray(8 * i, 8 * i + 8), 8);139 B = crypto.aesEcbEncrypt(S, key);140 A.set(B.subarray(0, 8));141 t = n * j + i;142 A[4] = A[4] ^ ((t >>> 24) & 0xFF);143 A[5] = A[5] ^ ((t >>> 16) & 0xFF);144 A[6] = A[6] ^ ((t >>> 8) & 0xFF);145 A[7] = A[7] ^ (t & 0xFF);146 R.set(B.subarray(8, 16), 8 * i);147 }148 }149 return R;150 }151152 function aeskwUnwrap(data, key) {153 var m, n, P, A, B, S, padded, r, t, i, j;154 m = data.length;155 if (m < 2 * AESKW_BLOCK_SIZE) {156 logger.error("[EKT] aeskwUnwrap, invalid data length, m=" + m);157 return null;158 }159 n = Math.ceil(m / AESKW_BLOCK_SIZE);160 r = n * AESKW_BLOCK_SIZE;161 --n;162 if (r != m) {163 logger.error("[EKT] aeskwUnwrap, invalid data, r=" + r + ", m=" + m);164 return null; // invalid data165 }166 if (1 == n) {167 B = crypto.aesEcbDecrypt(data, key);168 A = B.subarray(0, 8);169 P = B.subarray(8, 16);170 } else {171 P = new Uint8Array(r);172 P.set(data.subarray(0, r));173 A = P.subarray(0, 8);174 S = new Uint8Array(2 * AESKW_BLOCK_SIZE);175 for (j = 5; j >= 0; --j) {176 for (i = n; i >= 1; --i) {177 t = n * j + i;178 A[4] = A[4] ^ ((t >>> 24) & 0xFF);179 A[5] = A[5] ^ ((t >>> 16) & 0xFF);180 A[6] = A[6] ^ ((t >>> 8) & 0xFF);181 A[7] = A[7] ^ (t & 0xFF);182 S.set(A);183 S.set(P.subarray(8 * i, 8 * i + 8), 8);184 B = crypto.aesEcbDecrypt(S, key);185 A.set(B.subarray(0, 8));186 P.set(B.subarray(8, 16), 8 * i);187 }188 }189 P = P.subarray(8, r); // remove the A190 }191 if (A[0] != 0xA6 || A[1] != 0x59 || A[2] != 0x59 || A[3] != 0xA6) {192 logger.error("[EKT] aeskwUnwrap, failed to authenticate A: ", A);193 return null;194 }195 var l = (A[4] << 24) | (A[5] << 16) | (A[6] << 8) | A[7];196 if (l > 8 * n || l <= 8 * (n - 1)) {197 logger.error("[EKT] aeskwUnwrap, failed to authenticate length, l=" + l);198 return null;199 }200 var b = 8*n - l;201 if (b > 0) {202 for (i = 0; i < b; ++i) {203 if (P[l + i] != 0) {204 logger.error("[EKT] aeskwUnwrap, failed to authenticate padding data");205 return null;206 }207 }208 P = P.subarray(0, l);209 }210 return P;211 }212213 srtp.ektEncode = ektEncode;214 srtp.ektDecode = ektDecode;215 exports.srtp = srtp;216 return srtp; ...

Full Screen

Full Screen

aes-kw.js

Source:aes-kw.js Github

copy

Full Screen

1//*******************************************************************************2//3// Copyright 2020 Microsoft4//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//*******************************************************************************18var msrcryptoAESKW = function (blockCipher) {19 function encrypt(buffer) {20 // Inputs: Plaintext, n 64-bit values {P1, P2, ..., Pn}, and21 // Key, K (the KEK).22 // Outputs: Ciphertext, (n+1) 64-bit values {C0, C1, ..., Cn}.23 var plain = [[0]];24 for (var i = 0; i < buffer.length; i += 8) {25 plain.push(buffer.slice(i, i + 8));26 }27 // 1) Initialize variables.28 // Set A = IV, an initial value (see 2.2.3)29 // For i = 1 to n30 // R[i] = P[i]31 var A = [166, 166, 166, 166, 166, 166, 166, 166]; // A = IV = A6A6A6A6A6A6A6A632 var n = plain.length - 1;33 var registers = [];34 for (var i = 1; i <= n; i++) {35 registers[i] = plain[i];36 }37 // 2) Calculate intermediate values.38 // For j = 0 to 539 // For i=1 to n40 // B = AES(K, A | R[i])41 // A = MSB(64, B) ^ t where t = (n*j)+i42 // R[i] = LSB(64, B)43 for (var j = 0; j <= 5; j++) {44 for (var i = 1; i <= n; i++) {45 var t = n * j + i;46 var enc = blockCipher.encrypt(A.concat(registers[i]));47 registers[i] = enc.slice(8);48 A = enc.slice(0, 8);49 for (var ai = 7; t > 0; ai--, t >>>= 8) {50 A[ai] ^= t & 255;51 }52 }53 }54 // 3) Output the results.55 // Set C[0] = A56 // For i = 1 to n57 // C[i] = R[i]58 var C = A;59 for (var i = 1; i <= n; i++) {60 C = C.concat(registers[i]);61 }62 return C;63 }64 function decrypt(buffer) {65 var cipher = [];66 for (var i = 0; i < buffer.length; i += 8) {67 cipher.push(buffer.slice(i, i + 8));68 }69 var n = cipher.length - 1;70 var registers = [];71 var plain = [];72 // 1) Initialize variables.73 // Set A = C[0]74 // For i = 1 to n75 // R[i] = C[i]76 var A = cipher[0];77 for (var i = 1; i <= n; i++) {78 registers[i] = cipher[i];79 }80 // 2) Compute intermediate values.81 // For j = 5 to 082 // For i = n to 183 // B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i84 // A = MSB(64, B)85 // R[i] = LSB(64, B)86 for (var j = 5; j >= 0; j--) {87 for (var i = n; i >= 1; i--) {88 var t = n * j + i;89 for (var ai = 7; t > 0; ai--, t >>>= 8) {90 A[ai] ^= t & 255;91 }92 var B = blockCipher.decrypt(A.concat(registers[i]));93 A = B.slice(0, 8);94 registers[i] = B.slice(8);95 }96 }97 if (A.join(",") !== "166,166,166,166,166,166,166,166") {98 throw msrcryptoUtilities.error("OperationError", "");99 }100 for (var i = 1; i <= n; i++) {101 plain = plain.concat(registers[i]);102 }103 return plain;104 }105 return {106 encrypt: encrypt,107 decrypt: decrypt108 };109};110if (typeof operations !== "undefined") {111 var aeskwInstances = {};112 msrcryptoAESKW.workerEncrypt = function (p) {113 var result,114 id = p.workerid;115 if (p.buffer.length % 8 !== 0) {116 throw msrcryptoUtilities.error(117 "DataError",118 "The AES-KW input data length is invalid: not a multiple of 8 bytes"119 );120 }121 if (!aeskwInstances[id]) {122 aeskwInstances[id] = msrcryptoAESKW(msrcryptoBlockCipher.aes(p.keyData));123 }124 result = aeskwInstances[id].encrypt(p.buffer);125 aeskwInstances[id] = null;126 return result;127 };128 msrcryptoAESKW.workerDecrypt = function (p) {129 var result,130 id = p.workerid;131 if (p.buffer.length % 8 !== 0) {132 throw msrcryptoUtilities.error(133 "DataError",134 "The AES-KW input data length is invalid: not a multiple of 8 bytes"135 );136 }137 if (!aeskwInstances[id]) {138 aeskwInstances[id] = msrcryptoAESKW(msrcryptoBlockCipher.aes(p.keyData));139 }140 result = aeskwInstances[id].decrypt(p.buffer);141 aeskwInstances[id] = null;142 return result;143 };144 msrcryptoAESKW.generateKey = function (p) {145 if (p.algorithm.length % 8 !== 0) {146 throw msrcryptoUtilities.error("OperationError", "AES key length must be 128, 192, or 256 bits");147 }148 return {149 type: "keyGeneration",150 keyData: msrcryptoPseudoRandom.getBytes(Math.floor(p.algorithm.length / 8)),151 keyHandle: {152 algorithm: p.algorithm,153 extractable: p.extractable,154 usages: null || p.usages,155 type: "secret"156 }157 };158 };159 msrcryptoAESKW.importKey = function (p) {160 var keyObject;161 var keyBits = p.keyData.length * 8;162 if (p.format === "jwk") {163 keyObject = msrcryptoJwk.jwkToKey(p.keyData, p.algorithm, ["k"]);164 } else if (p.format === "raw") {165 if (keyBits !== 128 && keyBits !== 192 && keyBits !== 256) {166 throw msrcryptoUtilities.error("OperationError", "AES key length must be 128, 192, or 256 bits");167 }168 keyObject = { k: msrcryptoUtilities.toArray(p.keyData) };169 } else {170 throw new TypeError("Invalid keyFormat argument");171 }172 p.algorithm.length = keyObject.k.length * 8;173 return {174 keyData: keyObject.k,175 keyHandle: {176 algorithm: p.algorithm,177 extractable: p.extractable || keyObject.extractable,178 usages: null || p.usages,179 type: "secret"180 },181 type: "keyImport"182 };183 };184 msrcryptoAESKW.exportKey = function (p) {185 if (p.format === "jwk") {186 return { type: "keyExport", keyHandle: msrcryptoJwk.keyToJwk(p.keyHandle, p.keyData) };187 }188 if (p.format === "raw") {189 return { type: "keyExport", keyHandle: p.keyData };190 }191 throw new TypeError("Invalid keyFormat argument");192 };193 operations.register("importKey", "AES-KW", msrcryptoAESKW.importKey);194 operations.register("exportKey", "AES-KW", msrcryptoAESKW.exportKey);195 operations.register("generateKey", "AES-KW", msrcryptoAESKW.generateKey);196 operations.register("encrypt", "AES-KW", msrcryptoAESKW.workerEncrypt);197 operations.register("decrypt", "AES-KW", msrcryptoAESKW.workerDecrypt);...

Full Screen

Full Screen

encrypt_key_management.js

Source:encrypt_key_management.js Github

copy

Full Screen

1import {wrap as aesKw} from '../runtime/aeskw.js';2import * as ECDH from '../runtime/ecdhes.js';3import {encrypt as pbes2Kw} from '../runtime/pbes2kw.js';4import {encrypt as rsaEs} from '../runtime/rsaes.js';5import {encode as base64url} from '../runtime/base64url.js';6import generateCek, {bitLength as cekLength} from '../lib/cek.js';7import {JOSENotSupported} from '../util/errors.js';8import {exportJWK} from '../key/export.js';9import checkKeyType from './check_key_type.js';10import {wrap as aesGcmKw} from './aesgcmkw.js';11async function encryptKeyManagement(alg, enc, key, providedCek, providedParameters = {}) {12 let encryptedKey;13 let parameters;14 let cek;15 checkKeyType(alg, key, 'encrypt');16 switch (alg) {17 case 'dir': {18 cek = key;19 break;20 }21 case 'ECDH-ES':22 case 'ECDH-ES+A128KW':23 case 'ECDH-ES+A192KW':24 case 'ECDH-ES+A256KW': {25 if (!ECDH.ecdhAllowed(key)) {26 throw new JOSENotSupported('ECDH with the provided key is not allowed or not supported by your javascript runtime');27 }28 const { apu, apv } = providedParameters;29 let { epk: ephemeralKey } = providedParameters;30 ephemeralKey || (ephemeralKey = (await ECDH.generateEpk(key)).privateKey);31 const { x, y, crv, kty } = await exportJWK(ephemeralKey);32 const sharedSecret = await ECDH.deriveKey(key, ephemeralKey, alg === 'ECDH-ES' ? enc : alg, alg === 'ECDH-ES' ? cekLength(enc) : parseInt(alg.slice(-5, -2), 10), apu, apv);33 parameters = { epk: { x, crv, kty } };34 if (kty === 'EC')35 parameters.epk.y = y;36 if (apu)37 parameters.apu = base64url(apu);38 if (apv)39 parameters.apv = base64url(apv);40 if (alg === 'ECDH-ES') {41 cek = sharedSecret;42 break;43 }44 cek = providedCek || generateCek(enc);45 const kwAlg = alg.slice(-6);46 encryptedKey = await aesKw(kwAlg, sharedSecret, cek);47 break;48 }49 case 'RSA1_5':50 case 'RSA-OAEP':51 case 'RSA-OAEP-256':52 case 'RSA-OAEP-384':53 case 'RSA-OAEP-512': {54 cek = providedCek || generateCek(enc);55 encryptedKey = await rsaEs(alg, key, cek);56 break;57 }58 case 'PBES2-HS256+A128KW':59 case 'PBES2-HS384+A192KW':60 case 'PBES2-HS512+A256KW': {61 cek = providedCek || generateCek(enc);62 const { p2c, p2s } = providedParameters;63 ({ encryptedKey, ...parameters } = await pbes2Kw(alg, key, cek, p2c, p2s));64 break;65 }66 case 'A128KW':67 case 'A192KW':68 case 'A256KW': {69 cek = providedCek || generateCek(enc);70 encryptedKey = await aesKw(alg, key, cek);71 break;72 }73 case 'A128GCMKW':74 case 'A192GCMKW':75 case 'A256GCMKW': {76 cek = providedCek || generateCek(enc);77 const { iv } = providedParameters;78 ({ encryptedKey, ...parameters } = await aesGcmKw(alg, key, cek, iv));79 break;80 }81 default: {82 throw new JOSENotSupported('Invalid or unsupported "alg" (JWE Algorithm) header value');83 }84 }85 return { cek, encryptedKey, parameters };86}...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptools = require('wptools');2var wp = wptools.page('Albert Einstein');3wp.get(function(err, resp) {4 if (!err) {5 console.log(resp);6 }7});

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptools = require('wptools');2var opts = {3};4wptools.api(opts, function(err, resp) {5 console.log(resp);6});7var wptools = require('wptools');8var opts = {9};10wptools.api(opts, function(err, resp) {11 console.log(resp);12});13var wptools = require('wptools');14var opts = {15};16wptools.api(opts, function(err, resp) {17 console.log(resp);18});19var wptools = require('wptools');20var opts = {21};22wptools.api(opts, function(err, resp) {23 console.log(resp);24});

Full Screen

Using AI Code Generation

copy

Full Screen

1const wptools = require('wptools');2const fs = require('fs');3wptools.page('Eiffel Tower')4 .then(function(page) {5 return page.getWikiText();6 })7 .then(function(text) {8 console.log(text);9 fs.writeFile('test.txt', text, (err) => {10 if (err) throw err;11 console.log('The file has been saved!');12 });13 })14 .catch(function(err) {15 console.log(err);16 });

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptools = require('wptools');2wptools.page('Albert Einstein').get(function(err, response) {3 var infobox = response.infobox();4 var image = response.image();5 var imageurl = response.imageurl();6 var imageinfo = response.imageinfo();7 var label = response.label();8 var description = response.description();9 var categories = response.categories();10 var coordinates = response.coordinates();11 var extlinks = response.extlinks();12 var interwiki = response.interwiki();13 var langlinks = response.langlinks();14 var links = response.links();15 var pageid = response.pageid();16 var pagelanguage = response.pagelanguage();17 var pagelanguagehtmlcode = response.pagelanguagehtmlcode();18 var pagelanguagedir = response.pagelanguagedir();19 var pagelanguagename = response.pagelanguagename();20 var title = response.title();21 var type = response.type();22 var url = response.url();23 var wikibase = response.wikibase();24 var wikidata = response.wikidata();25 var wikitext = response.wikitext();26 var html = response.html();27 var json = response.json();28 console.log(infobox);29 console.log(image);30 console.log(imageurl);31 console.log(imageinfo);32 console.log(label);33 console.log(description);34 console.log(categories);35 console.log(coordinates);36 console.log(extlinks);37 console.log(interwiki);38 console.log(lang

Full Screen

Using AI Code Generation

copy

Full Screen

1function aeskw(key, plaintext) {2 var keylen = key.length;3 var iv = new Uint8Array(8);4 var aeskw = new AesKw(key);5 var ciphertext = aeskw.wrap(iv, plaintext);6 return ciphertext;7}8function aeskw_inv(key, ciphertext) {9 var keylen = key.length;10 var iv = new Uint8Array(8);11 var aeskw = new AesKw(key);12 var plaintext = aeskw.unwrap(iv, ciphertext);13 return plaintext;14}15function aeskw_inv(key, ciphertext) {16 var keylen = key.length;17 var iv = new Uint8Array(8);18 var aeskw = new AesKw(key);19 var plaintext = aeskw.unwrap(iv, ciphertext);20 return plaintext;21}22function aeskw_inv(key, ciphertext) {23 var keylen = key.length;24 var iv = new Uint8Array(8);25 var aeskw = new AesKw(key);26 var plaintext = aeskw.unwrap(iv, ciphertext);27 return plaintext;28}29function aeskw_inv(key, ciphertext) {30 var keylen = key.length;31 var iv = new Uint8Array(8);32 var aeskw = new AesKw(key);33 var plaintext = aeskw.unwrap(iv, ciphertext);34 return plaintext;35}36function aeskw_inv(key, ciphertext) {37 var keylen = key.length;38 var iv = new Uint8Array(8);39 var aeskw = new AesKw(key);40 var plaintext = aeskw.unwrap(iv, ciphertext);41 return plaintext;42}43function aeskw_inv(key, ciphertext) {44 var keylen = key.length;45 var iv = new Uint8Array(8);46 var aeskw = new AesKw(key);47 var plaintext = aeskw.unwrap(iv, ciphertext);48 return plaintext;49}50function aeskw_inv(key, ciphertext) {51 var keylen = key.length;52 var iv = new Uint8Array(8);

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