Best JavaScript code snippet using storybook-root
HttpConnection.ts
Source:HttpConnection.ts
1// Copyright (c) .NET Foundation. All rights reserved.2// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.3import { DefaultHttpClient } from "./DefaultHttpClient";4import { HttpClient } from "./HttpClient";5import { IConnection } from "./IConnection";6import { IHttpConnectionOptions } from "./IHttpConnectionOptions";7import { ILogger, LogLevel } from "./ILogger";8import { HttpTransportType, ITransport, TransferFormat } from "./ITransport";9import { LongPollingTransport } from "./LongPollingTransport";10import { ServerSentEventsTransport } from "./ServerSentEventsTransport";11import { Arg, createLogger } from "./Utils";12import { WebSocketTransport } from "./WebSocketTransport";13/** @private */14const enum ConnectionState {15 Connecting,16 Connected,17 Disconnected,18}19/** @private */20export interface INegotiateResponse {21 connectionId?: string;22 availableTransports?: IAvailableTransport[];23 url?: string;24 accessToken?: string;25 error?: string;26}27/** @private */28export interface IAvailableTransport {29 transport: keyof typeof HttpTransportType;30 transferFormats: Array<keyof typeof TransferFormat>;31}32const MAX_REDIRECTS = 100;33let WebSocketModule: any = null;34let EventSourceModule: any = null;35if (typeof window === "undefined" && typeof require !== "undefined") {36 // In order to ignore the dynamic require in webpack builds we need to do this magic37 // @ts-ignore: TS doesn't know about these names38 const requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require;39 WebSocketModule = requireFunc("ws");40 EventSourceModule = requireFunc("eventsource");41}42/** @private */43export class HttpConnection implements IConnection {44 private connectionState: ConnectionState;45 private baseUrl: string;46 private readonly httpClient: HttpClient;47 private readonly logger: ILogger;48 private readonly options: IHttpConnectionOptions;49 private transport?: ITransport;50 private startPromise?: Promise<void>;51 private stopError?: Error;52 private accessTokenFactory?: () => string | Promise<string>;53 public readonly features: any = {};54 public onreceive: ((data: string | ArrayBuffer) => void) | null;55 public onclose: ((e?: Error) => void) | null;56 constructor(url: string, options: IHttpConnectionOptions = {}) {57 Arg.isRequired(url, "url");58 this.logger = createLogger(options.logger);59 this.baseUrl = this.resolveUrl(url);60 options = options || {};61 options.logMessageContent = options.logMessageContent || false;62 const isNode = typeof window === "undefined";63 if (!isNode && typeof WebSocket !== "undefined" && !options.WebSocket) {64 options.WebSocket = WebSocket;65 } else if (isNode && !options.WebSocket) {66 if (WebSocketModule) {67 options.WebSocket = WebSocketModule;68 }69 }70 if (!isNode && typeof EventSource !== "undefined" && !options.EventSource) {71 options.EventSource = EventSource;72 } else if (isNode && !options.EventSource) {73 if (typeof EventSourceModule !== "undefined") {74 options.EventSource = EventSourceModule;75 }76 }77 this.httpClient = options.httpClient || new DefaultHttpClient(this.logger);78 this.connectionState = ConnectionState.Disconnected;79 this.options = options;80 this.onreceive = null;81 this.onclose = null;82 }83 public start(): Promise<void>;84 public start(transferFormat: TransferFormat): Promise<void>;85 public start(transferFormat?: TransferFormat): Promise<void> {86 transferFormat = transferFormat || TransferFormat.Binary;87 Arg.isIn(transferFormat, TransferFormat, "transferFormat");88 this.logger.log(LogLevel.Debug, `Starting connection with transfer format '${TransferFormat[transferFormat]}'.`);89 if (this.connectionState !== ConnectionState.Disconnected) {90 return Promise.reject(new Error("Cannot start a connection that is not in the 'Disconnected' state."));91 }92 this.connectionState = ConnectionState.Connecting;93 this.startPromise = this.startInternal(transferFormat);94 return this.startPromise;95 }96 public send(data: string | ArrayBuffer): Promise<void> {97 if (this.connectionState !== ConnectionState.Connected) {98 throw new Error("Cannot send data if the connection is not in the 'Connected' State.");99 }100 // Transport will not be null if state is connected101 return this.transport!.send(data);102 }103 public async stop(error?: Error): Promise<void> {104 this.connectionState = ConnectionState.Disconnected;105 // Set error as soon as possible otherwise there is a race between106 // the transport closing and providing an error and the error from a close message107 // We would prefer the close message error.108 this.stopError = error;109 try {110 await this.startPromise;111 } catch (e) {112 // this exception is returned to the user as a rejected Promise from the start method113 }114 // The transport's onclose will trigger stopConnection which will run our onclose event.115 if (this.transport) {116 await this.transport.stop();117 this.transport = undefined;118 }119 }120 private async startInternal(transferFormat: TransferFormat): Promise<void> {121 // Store the original base url and the access token factory since they may change122 // as part of negotiating123 let url = this.baseUrl;124 this.accessTokenFactory = this.options.accessTokenFactory;125 try {126 if (this.options.skipNegotiation) {127 if (this.options.transport === HttpTransportType.WebSockets) {128 // No need to add a connection ID in this case129 this.transport = this.constructTransport(HttpTransportType.WebSockets);130 // We should just call connect directly in this case.131 // No fallback or negotiate in this case.132 await this.transport!.connect(url, transferFormat);133 } else {134 throw Error("Negotiation can only be skipped when using the WebSocket transport directly.");135 }136 } else {137 let negotiateResponse: INegotiateResponse | null = null;138 let redirects = 0;139 do {140 negotiateResponse = await this.getNegotiationResponse(url);141 // the user tries to stop the connection when it is being started142 if (this.connectionState === ConnectionState.Disconnected) {143 return;144 }145 if (negotiateResponse.error) {146 throw Error(negotiateResponse.error);147 }148 if ((negotiateResponse as any).ProtocolVersion) {149 throw Error("Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.");150 }151 if (negotiateResponse.url) {152 url = negotiateResponse.url;153 }154 if (negotiateResponse.accessToken) {155 // Replace the current access token factory with one that uses156 // the returned access token157 const accessToken = negotiateResponse.accessToken;158 this.accessTokenFactory = () => accessToken;159 }160 redirects++;161 }162 while (negotiateResponse.url && redirects < MAX_REDIRECTS);163 if (redirects === MAX_REDIRECTS && negotiateResponse.url) {164 throw Error("Negotiate redirection limit exceeded.");165 }166 await this.createTransport(url, this.options.transport, negotiateResponse, transferFormat);167 }168 if (this.transport instanceof LongPollingTransport) {169 this.features.inherentKeepAlive = true;170 }171 this.transport!.onreceive = this.onreceive;172 this.transport!.onclose = (e) => this.stopConnection(e);173 // only change the state if we were connecting to not overwrite174 // the state if the connection is already marked as Disconnected175 this.changeState(ConnectionState.Connecting, ConnectionState.Connected);176 } catch (e) {177 this.logger.log(LogLevel.Error, "Failed to start the connection: " + e);178 this.connectionState = ConnectionState.Disconnected;179 this.transport = undefined;180 throw e;181 }182 }183 private async getNegotiationResponse(url: string): Promise<INegotiateResponse> {184 let headers;185 if (this.accessTokenFactory) {186 const token = await this.accessTokenFactory();187 if (token) {188 headers = {189 ["Authorization"]: `Bearer ${token}`,190 };191 }192 }193 const negotiateUrl = this.resolveNegotiateUrl(url);194 this.logger.log(LogLevel.Debug, `Sending negotiation request: ${negotiateUrl}.`);195 try {196 const response = await this.httpClient.post(negotiateUrl, {197 content: "",198 headers,199 });200 if (response.statusCode !== 200) {201 throw Error(`Unexpected status code returned from negotiate ${response.statusCode}`);202 }203 return JSON.parse(response.content as string) as INegotiateResponse;204 } catch (e) {205 this.logger.log(LogLevel.Error, "Failed to complete negotiation with the server: " + e);206 throw e;207 }208 }209 private createConnectUrl(url: string, connectionId: string | null | undefined) {210 if (!connectionId) {211 return url;212 }213 return url + (url.indexOf("?") === -1 ? "?" : "&") + `id=${connectionId}`;214 }215 private async createTransport(url: string, requestedTransport: HttpTransportType | ITransport | undefined, negotiateResponse: INegotiateResponse, requestedTransferFormat: TransferFormat): Promise<void> {216 let connectUrl = this.createConnectUrl(url, negotiateResponse.connectionId);217 if (this.isITransport(requestedTransport)) {218 this.logger.log(LogLevel.Debug, "Connection was provided an instance of ITransport, using that directly.");219 this.transport = requestedTransport;220 await this.transport.connect(connectUrl, requestedTransferFormat);221 // only change the state if we were connecting to not overwrite222 // the state if the connection is already marked as Disconnected223 this.changeState(ConnectionState.Connecting, ConnectionState.Connected);224 return;225 }226 const transports = negotiateResponse.availableTransports || [];227 for (const endpoint of transports) {228 this.connectionState = ConnectionState.Connecting;229 const transport = this.resolveTransport(endpoint, requestedTransport, requestedTransferFormat);230 if (typeof transport === "number") {231 this.transport = this.constructTransport(transport);232 if (!negotiateResponse.connectionId) {233 negotiateResponse = await this.getNegotiationResponse(url);234 connectUrl = this.createConnectUrl(url, negotiateResponse.connectionId);235 }236 try {237 await this.transport!.connect(connectUrl, requestedTransferFormat);238 this.changeState(ConnectionState.Connecting, ConnectionState.Connected);239 return;240 } catch (ex) {241 this.logger.log(LogLevel.Error, `Failed to start the transport '${HttpTransportType[transport]}': ${ex}`);242 this.connectionState = ConnectionState.Disconnected;243 negotiateResponse.connectionId = undefined;244 }245 }246 }247 throw new Error("Unable to initialize any of the available transports.");248 }249 private constructTransport(transport: HttpTransportType) {250 switch (transport) {251 case HttpTransportType.WebSockets:252 if (!this.options.WebSocket) {253 throw new Error("'WebSocket' is not supported in your environment.");254 }255 return new WebSocketTransport(this.httpClient, this.accessTokenFactory, this.logger, this.options.logMessageContent || false, this.options.WebSocket);256 case HttpTransportType.ServerSentEvents:257 if (!this.options.EventSource) {258 throw new Error("'EventSource' is not supported in your environment.");259 }260 return new ServerSentEventsTransport(this.httpClient, this.accessTokenFactory, this.logger, this.options.logMessageContent || false, this.options.EventSource);261 case HttpTransportType.LongPolling:262 return new LongPollingTransport(this.httpClient, this.accessTokenFactory, this.logger, this.options.logMessageContent || false);263 default:264 throw new Error(`Unknown transport: ${transport}.`);265 }266 }267 private resolveTransport(endpoint: IAvailableTransport, requestedTransport: HttpTransportType | undefined, requestedTransferFormat: TransferFormat): HttpTransportType | null {268 const transport = HttpTransportType[endpoint.transport];269 if (transport === null || transport === undefined) {270 this.logger.log(LogLevel.Debug, `Skipping transport '${endpoint.transport}' because it is not supported by this client.`);271 } else {272 const transferFormats = endpoint.transferFormats.map((s) => TransferFormat[s]);273 if (transportMatches(requestedTransport, transport)) {274 if (transferFormats.indexOf(requestedTransferFormat) >= 0) {275 if ((transport === HttpTransportType.WebSockets && !this.options.WebSocket) ||276 (transport === HttpTransportType.ServerSentEvents && !this.options.EventSource)) {277 this.logger.log(LogLevel.Debug, `Skipping transport '${HttpTransportType[transport]}' because it is not supported in your environment.'`);278 } else {279 this.logger.log(LogLevel.Debug, `Selecting transport '${HttpTransportType[transport]}'.`);280 return transport;281 }282 } else {283 this.logger.log(LogLevel.Debug, `Skipping transport '${HttpTransportType[transport]}' because it does not support the requested transfer format '${TransferFormat[requestedTransferFormat]}'.`);284 }285 } else {286 this.logger.log(LogLevel.Debug, `Skipping transport '${HttpTransportType[transport]}' because it was disabled by the client.`);287 }288 }289 return null;290 }291 private isITransport(transport: any): transport is ITransport {292 return transport && typeof (transport) === "object" && "connect" in transport;293 }294 private changeState(from: ConnectionState, to: ConnectionState): boolean {295 if (this.connectionState === from) {296 this.connectionState = to;297 return true;298 }299 return false;300 }301 private stopConnection(error?: Error): void {302 this.transport = undefined;303 // If we have a stopError, it takes precedence over the error from the transport304 error = this.stopError || error;305 if (error) {306 this.logger.log(LogLevel.Error, `Connection disconnected with error '${error}'.`);307 } else {308 this.logger.log(LogLevel.Information, "Connection disconnected.");309 }310 this.connectionState = ConnectionState.Disconnected;311 if (this.onclose) {312 this.onclose(error);313 }314 }315 private resolveUrl(url: string): string {316 // startsWith is not supported in IE317 if (url.lastIndexOf("https://", 0) === 0 || url.lastIndexOf("http://", 0) === 0) {318 return url;319 }320 if (typeof window === "undefined" || !window || !window.document) {321 throw new Error(`Cannot resolve '${url}'.`);322 }323 // Setting the url to the href propery of an anchor tag handles normalization324 // for us. There are 3 main cases.325 // 1. Relative path normalization e.g "b" -> "http://localhost:5000/a/b"326 // 2. Absolute path normalization e.g "/a/b" -> "http://localhost:5000/a/b"327 // 3. Networkpath reference normalization e.g "//localhost:5000/a/b" -> "http://localhost:5000/a/b"328 const aTag = window.document.createElement("a");329 aTag.href = url;330 this.logger.log(LogLevel.Information, `Normalizing '${url}' to '${aTag.href}'.`);331 return aTag.href;332 }333 private resolveNegotiateUrl(url: string): string {334 const index = url.indexOf("?");335 let negotiateUrl = url.substring(0, index === -1 ? url.length : index);336 if (negotiateUrl[negotiateUrl.length - 1] !== "/") {337 negotiateUrl += "/";338 }339 negotiateUrl += "negotiate";340 negotiateUrl += index === -1 ? "" : url.substring(index);341 return negotiateUrl;342 }343}344function transportMatches(requestedTransport: HttpTransportType | undefined, actualTransport: HttpTransportType) {345 return !requestedTransport || ((actualTransport & requestedTransport) !== 0);...
transport.js
Source:transport.js
1import {2 TRANSPORT_SET_IS_LOADING,3 TRANSPORT_SET_ERRORS,4 SET_TRANSPORTS,5 SET_TRANSPORT,6 ADD_TRANSPORT,7 TRANSPORT_SET_TOTAL_PAGES,8 TRANSPORT_SET_TOTAL_ELEMENTS,9 TRANSPORT_SET_PAGE,10 TRANSPORT_SET_SIZE,11} from "../actions/types";12 13import TransportService from '../../service/TransportService'14export const getTransport = (transportData) => (dispatch) => {15 return TransportService.getAllTransport(transportData)16 .then((response) => {17 dispatch({18 type: TRANSPORT_SET_IS_LOADING,19 payload: true20 })21 dispatch({22 type: SET_TRANSPORTS,23 payload: response.data.objects24 })25 dispatch({26 type: TRANSPORT_SET_TOTAL_PAGES,27 payload: response.data.totalPages28 })29 dispatch({30 type: TRANSPORT_SET_TOTAL_ELEMENTS,31 payload: response.data.totalElements32 })33 dispatch({34 type: TRANSPORT_SET_IS_LOADING,35 payload: false36 })37 return Promise.resolve(response.data)38 })39 .catch(error => {40 return Promise.reject(error)41 })42}43export const addTransport = (transportData) => (dispatch) => {44 return TransportService.addTransport(transportData).then(45 response => {46 dispatch({47 type: ADD_TRANSPORT,48 payload: response.data49 })50 return Promise.resolve(response)51 },52 error => {53 return Promise.reject(error)54 }55 )56}57export const updateTransport = (id, patchData) => (dispatch) => {58 return TransportService.updateTransport(id, patchData)59 .then((data) => {60 return Promise.resolve(data)61 })62 .catch(error => {63 return Promise.reject(error)64 })65}66export const deleteTransport = (id) => (dispatch) => {67 return TransportService.deleteTransport(id).then((data) => {68 return Promise.resolve(id)69 })70}71export const setPage = (page) => (dispatch) => {72 dispatch({73 type: TRANSPORT_SET_PAGE,74 payload: page75 })76}77export const setSize = (size) => (dispatch) => {78 dispatch({79 type: TRANSPORT_SET_SIZE,80 payload: size81 })...
iframe-wrap.js
Source:iframe-wrap.js
1'use strict';2var inherits = require('inherits')3 , IframeTransport = require('../iframe')4 , objectUtils = require('../../utils/object')5 ;6module.exports = function(transport) {7 function IframeWrapTransport(transUrl, baseUrl) {8 IframeTransport.call(this, transport.transportName, transUrl, baseUrl);9 }10 inherits(IframeWrapTransport, IframeTransport);11 IframeWrapTransport.enabled = function(url, info) {12 if (!global.document) {13 return false;14 }15 var iframeInfo = objectUtils.extend({}, info);16 iframeInfo.sameOrigin = true;17 return transport.enabled(iframeInfo) && IframeTransport.enabled();18 };19 IframeWrapTransport.transportName = 'iframe-' + transport.transportName;20 IframeWrapTransport.needBody = true;21 IframeWrapTransport.roundTrips = IframeTransport.roundTrips + transport.roundTrips - 1; // html, javascript (2) + transport - no CORS (1)22 IframeWrapTransport.facadeTransport = transport;23 return IframeWrapTransport;...
Using AI Code Generation
1import { withTransport } from 'storybook-root-decorator';2import { withKnobs, text } from '@storybook/addon-knobs';3import { withA11y } from '@storybook/addon-a11y';4import { withTests } from '@storybook/addon-jest';5import results from '../.jest-test-results.json';6import { withInfo } from '@storybook/addon-info';7import { withBackgrounds } from '@storybook/addon-backgrounds';8import { withViewport } from '@storybook/addon-viewport';9import { withConsole } from '@storybook/addon-console';10import { addDecorator, addParameters } from '@storybook/react';11import { withOptions } from '@storybook/addon-options';12import { withCssResources } from '@storybook/addon-cssresources';13import { withThemesProvider } from 'storybook-addon-styled-component-theme';14import { withPaddings } from 'storybook-addon-paddings';15import { withPerformance } from 'storybook-addon-performance';16import { withStorySource } from '@storybook/addon-storysource';17import { withContexts } from '@storybook/addon-contexts/react';18import { withCode } from 'storybook-addon-code';19import { withTests as withTests2 } from '@storybook/addon-jest';20import { withReadme } from 'storybook-readme';21import { withDocs } from 'storybook-readme';22import { withNotes } from '@storybook/addon-notes';23import { withInfo2 } from '@storybook/addon-info';24import { withA11y2 } from '@storybook/addon-a11y';25import { withViewport2 } from '@storybook/addon-viewport';26import { withConsole2 } from '@storybook/addon-console';27import { withBackgrounds2 } from '@storybook/addon-backgrounds';28import { withKnobs2 } from '@storybook/addon-knobs';29import { withTests3 } from '@storybook/addon-jest';30import { withInfo3 } from '@storybook/addon-info';31import { withViewport3 } from '@storybook/addon-viewport';32import { withConsole3 } from '@storybook/addon-console';33import { withBackgrounds3 } from '@storybook/addon-backgrounds';34import { withKnobs3 } from '@storybook/addon-knobs';35import { withTests4 } from '@storybook/addon-jest';36import { withInfo4 } from '@storybook/addon-info';37import { withViewport
Using AI Code Generation
1import { addDecorator } from '@storybook/react';2import { withTransport } from 'storybook-root-decorator';3addDecorator(withTransport);4import React from 'react';5import { storiesOf } from '@storybook/react';6import { withTransport } from 'storybook-root-decorator';7import { action } from '@storybook/addon-actions';8import Button from './Button';9storiesOf('Button', module)10 .addDecorator(withTransport)11 .add('with text', () => (12 <Button onClick={action('clicked')}>Hello Button</Button>13 .add('with some emoji', () => (14 <Button onClick={action('clicked')}>15 ));16import { configure, addDecorator } from '@storybook/react';17import { withTransport } from 'storybook-root-decorator';18const req = require.context('../src', true, /.stories.tsx$/);19function loadStories() {20 req.keys().forEach(filename => req(filename));21}22addDecorator(withTransport);23configure(loadStories, module);24const path = require('path');25module.exports = (baseConfig, env, config) => {26 ...(config.resolve.modules || []),27 path.resolve(__dirname, '../src'),28 ];29 return config;30};31const path = require('path');32module.exports = (baseConfig, env, config) => {33 ...(config.resolve.modules || []),34 path.resolve(__dirname, '../src'),35 ];36 return config;37};38const path = require('path');39module.exports = (baseConfig, env, config) => {40 ...(config.resolve.modules || []),41 path.resolve(__dirname, '../src'),42 ];43 return config;44};45const path = require('path');46module.exports = (baseConfig
Using AI Code Generation
1import {decorateStory} from 'storybook-root-decorator';2import { withA11y } from '@storybook/addon-a11y';3export default {4};5export const withText = () => <button>With Text</button>;6export const withEmoji = () => <button>😀 😎 👍 💯</button>;7import { addDecorator } from '@storybook/react';8import { decorateStory } from 'storybook-root-decorator';9import { withA11y } from '@storybook/addon-a11y';10import { withKnobs } from '@storybook/addon-knobs';11addDecorator(withA11y);12addDecorator(withKnobs);13addDecorator(decorateStory);14import { addons } from '@storybook/addons';15import { create } from '@storybook/theming';16addons.setConfig({17 theme: create({18 }),19});20const path = require('path');21module.exports = async ({ config, mode }) => {22 config.module.rules.push({23 test: /\.(ts|tsx)$/,24 include: path.resolve(__dirname, '../'),25 {26 loader: require.resolve('ts-loader'),27 },28 {29 loader: require.resolve('react-docgen-typescript-loader'),30 },31 });32 config.resolve.extensions.push('.ts', '.tsx');33 return config;34};35{36 "compilerOptions": {
Using AI Code Generation
1import { addDecorator } from '@storybook/react';2import { withRootDecorator } from 'storybook-root-decorator';3const rootDecorator = withRootDecorator({4 options: {5 postMessage: {6 },7 },8});9addDecorator(rootDecorator);10import { addDecorator } from '@storybook/react';11import { withRootDecorator } from 'storybook-root-decorator';12const rootDecorator = withRootDecorator({13 options: {14 postMessage: {15 },16 },17});18addDecorator(rootDecorator);19module.exports = ({ config }) => {20 config.module.rules.push({21 loaders: [require.resolve('@storybook/source-loader')],22 });23 return config;24};25import { addDecorator } from '@storybook/react';26import { withRootDecorator } from 'storybook-root-decorator';27const rootDecorator = withRootDecorator({28 options: {29 postMessage: {30 },31 },32});33addDecorator(rootDecorator);34import { addDecorator } from '@storybook/react';35import { withRootDecorator } from 'storybook-root-decorator';36const rootDecorator = withRootDecorator({37 options: {38 postMessage: {39 },40 },41});42addDecorator(rootDecorator);43import { addDecorator } from '@storybook/react';44import { withRootDecorator } from 'storybook-root-decorator';45const rootDecorator = withRootDecorator({46 options: {47 postMessage: {48 },49 },50});51addDecorator(rootDecorator);52import { addDecorator } from '@storybook/react';53import { withRootDecorator } from 'storybook-root-decorator';54const rootDecorator = withRootDecorator({
Using AI Code Generation
1import {log} from 'storybook-root-logger';2log.info('test', 'test');3log.info('test', 'test with args', {foo: 'bar'});4log.info('test', 'test with args', {foo: 'bar'}, {foo: 'bar'});5log.info('test', 'test with args', {foo: 'bar'}, {foo: 'bar'}, {foo: 'bar'});6log.info('test', 'test with args', {foo: 'bar'}, {foo: 'bar'}, {foo: 'bar'}, {foo: 'bar'});7log.info('test', 'test with args', {foo: 'bar'}, {foo: 'bar
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!!