Best Python code snippet using toolium_python
logger.js
Source:logger.js
1// Copyright 2006 The Closure Library Authors. All Rights Reserved.2//3// Licensed under the Apache License, Version 2.0 (the "License");4// you may not use this file except in compliance with the License.5// You may obtain a copy of the License at6//7// http://www.apache.org/licenses/LICENSE-2.08//9// Unless required by applicable law or agreed to in writing, software10// distributed under the License is distributed on an "AS-IS" BASIS,11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12// See the License for the specific language governing permissions and13// limitations under the License.14/**15 * @fileoverview Definition of the Logger class. Please minimize dependencies16 * this file has on other closure classes as any dependency it takes won't be17 * able to use the logging infrastructure.18 *19 * @see ../demos/debug.html20 */21goog.provide('goog.debug.LogManager');22goog.provide('goog.debug.Logger');23goog.provide('goog.debug.Logger.Level');24goog.require('goog.array');25goog.require('goog.asserts');26goog.require('goog.debug');27goog.require('goog.debug.LogBuffer');28goog.require('goog.debug.LogRecord');29/**30 * The Logger is an object used for logging debug messages. Loggers are31 * normally named, using a hierarchical dot-separated namespace. Logger names32 * can be arbitrary strings, but they should normally be based on the package33 * name or class name of the logged component, such as goog.net.BrowserChannel.34 *35 * The Logger object is loosely based on the java class36 * java.util.logging.Logger. It supports different levels of filtering for37 * different loggers.38 *39 * The logger object should never be instantiated by application code. It40 * should always use the goog.debug.Logger.getLogger function.41 *42 * @constructor43 * @param {string} name The name of the Logger.44 */45goog.debug.Logger = function(name) {46 /**47 * Name of the Logger. Generally a dot-separated namespace48 * @type {string}49 * @private50 */51 this.name_ = name;52};53/**54 * Parent Logger.55 * @type {goog.debug.Logger}56 * @private57 */58goog.debug.Logger.prototype.parent_ = null;59/**60 * Level that this logger only filters above. Null indicates it should61 * inherit from the parent.62 * @type {goog.debug.Logger.Level}63 * @private64 */65goog.debug.Logger.prototype.level_ = null;66/**67 * Map of children loggers. The keys are the leaf names of the children and68 * the values are the child loggers.69 * @type {Object}70 * @private71 */72goog.debug.Logger.prototype.children_ = null;73/**74 * Handlers that are listening to this logger.75 * @type {Array.<Function>}76 * @private77 */78goog.debug.Logger.prototype.handlers_ = null;79/**80 * @define {boolean} Toggles whether loggers other than the root logger can have81 * log handlers attached to them and whether they can have their log level82 * set. Logging is a bit faster when this is set to false.83 */84goog.debug.Logger.ENABLE_HIERARCHY = true;85if (!goog.debug.Logger.ENABLE_HIERARCHY) {86 /**87 * @type {!Array.<Function>}88 * @private89 */90 goog.debug.Logger.rootHandlers_ = [];91 /**92 * @type {goog.debug.Logger.Level}93 * @private94 */95 goog.debug.Logger.rootLevel_;96}97/**98 * The Level class defines a set of standard logging levels that99 * can be used to control logging output. The logging Level objects100 * are ordered and are specified by ordered integers. Enabling logging101 * at a given level also enables logging at all higher levels.102 * <p>103 * Clients should normally use the predefined Level constants such104 * as Level.SEVERE.105 * <p>106 * The levels in descending order are:107 * <ul>108 * <li>SEVERE (highest value)109 * <li>WARNING110 * <li>INFO111 * <li>CONFIG112 * <li>FINE113 * <li>FINER114 * <li>FINEST (lowest value)115 * </ul>116 * In addition there is a level OFF that can be used to turn117 * off logging, and a level ALL that can be used to enable118 * logging of all messages.119 *120 * @param {string} name The name of the level.121 * @param {number} value The numeric value of the level.122 * @constructor123 */124goog.debug.Logger.Level = function(name, value) {125 /**126 * The name of the level127 * @type {string}128 */129 this.name = name;130 /**131 * The numeric value of the level132 * @type {number}133 */134 this.value = value;135};136/**137 * @return {string} String representation of the logger level.138 */139goog.debug.Logger.Level.prototype.toString = function() {140 return this.name;141};142/**143 * OFF is a special level that can be used to turn off logging.144 * This level is initialized to <CODE>Number.MAX_VALUE</CODE>.145 * @type {!goog.debug.Logger.Level}146 */147goog.debug.Logger.Level.OFF =148 new goog.debug.Logger.Level('OFF', Infinity);149/**150 * SHOUT is a message level for extra debugging loudness.151 * This level is initialized to <CODE>1200</CODE>.152 * @type {!goog.debug.Logger.Level}153 */154goog.debug.Logger.Level.SHOUT = new goog.debug.Logger.Level('SHOUT', 1200);155/**156 * SEVERE is a message level indicating a serious failure.157 * This level is initialized to <CODE>1000</CODE>.158 * @type {!goog.debug.Logger.Level}159 */160goog.debug.Logger.Level.SEVERE = new goog.debug.Logger.Level('SEVERE', 1000);161/**162 * WARNING is a message level indicating a potential problem.163 * This level is initialized to <CODE>900</CODE>.164 * @type {!goog.debug.Logger.Level}165 */166goog.debug.Logger.Level.WARNING = new goog.debug.Logger.Level('WARNING', 900);167/**168 * INFO is a message level for informational messages.169 * This level is initialized to <CODE>800</CODE>.170 * @type {!goog.debug.Logger.Level}171 */172goog.debug.Logger.Level.INFO = new goog.debug.Logger.Level('INFO', 800);173/**174 * CONFIG is a message level for static configuration messages.175 * This level is initialized to <CODE>700</CODE>.176 * @type {!goog.debug.Logger.Level}177 */178goog.debug.Logger.Level.CONFIG = new goog.debug.Logger.Level('CONFIG', 700);179/**180 * FINE is a message level providing tracing information.181 * This level is initialized to <CODE>500</CODE>.182 * @type {!goog.debug.Logger.Level}183 */184goog.debug.Logger.Level.FINE = new goog.debug.Logger.Level('FINE', 500);185/**186 * FINER indicates a fairly detailed tracing message.187 * This level is initialized to <CODE>400</CODE>.188 * @type {!goog.debug.Logger.Level}189 */190goog.debug.Logger.Level.FINER = new goog.debug.Logger.Level('FINER', 400);191/**192 * FINEST indicates a highly detailed tracing message.193 * This level is initialized to <CODE>300</CODE>.194 * @type {!goog.debug.Logger.Level}195 */196goog.debug.Logger.Level.FINEST = new goog.debug.Logger.Level('FINEST', 300);197/**198 * ALL indicates that all messages should be logged.199 * This level is initialized to <CODE>Number.MIN_VALUE</CODE>.200 * @type {!goog.debug.Logger.Level}201 */202goog.debug.Logger.Level.ALL = new goog.debug.Logger.Level('ALL', 0);203/**204 * The predefined levels.205 * @type {!Array.<!goog.debug.Logger.Level>}206 * @final207 */208goog.debug.Logger.Level.PREDEFINED_LEVELS = [209 goog.debug.Logger.Level.OFF,210 goog.debug.Logger.Level.SHOUT,211 goog.debug.Logger.Level.SEVERE,212 goog.debug.Logger.Level.WARNING,213 goog.debug.Logger.Level.INFO,214 goog.debug.Logger.Level.CONFIG,215 goog.debug.Logger.Level.FINE,216 goog.debug.Logger.Level.FINER,217 goog.debug.Logger.Level.FINEST,218 goog.debug.Logger.Level.ALL];219/**220 * A lookup map used to find the level object based on the name or value of221 * the level object.222 * @type {Object}223 * @private224 */225goog.debug.Logger.Level.predefinedLevelsCache_ = null;226/**227 * Creates the predefined levels cache and populates it.228 * @private229 */230goog.debug.Logger.Level.createPredefinedLevelsCache_ = function() {231 goog.debug.Logger.Level.predefinedLevelsCache_ = {};232 for (var i = 0, level; level = goog.debug.Logger.Level.PREDEFINED_LEVELS[i];233 i++) {234 goog.debug.Logger.Level.predefinedLevelsCache_[level.value] = level;235 goog.debug.Logger.Level.predefinedLevelsCache_[level.name] = level;236 }237};238/**239 * Gets the predefined level with the given name.240 * @param {string} name The name of the level.241 * @return {goog.debug.Logger.Level} The level, or null if none found.242 */243goog.debug.Logger.Level.getPredefinedLevel = function(name) {244 if (!goog.debug.Logger.Level.predefinedLevelsCache_) {245 goog.debug.Logger.Level.createPredefinedLevelsCache_();246 }247 return goog.debug.Logger.Level.predefinedLevelsCache_[name] || null;248};249/**250 * Gets the highest predefined level <= #value.251 * @param {number} value Level value.252 * @return {goog.debug.Logger.Level} The level, or null if none found.253 */254goog.debug.Logger.Level.getPredefinedLevelByValue = function(value) {255 if (!goog.debug.Logger.Level.predefinedLevelsCache_) {256 goog.debug.Logger.Level.createPredefinedLevelsCache_();257 }258 if (value in goog.debug.Logger.Level.predefinedLevelsCache_) {259 return goog.debug.Logger.Level.predefinedLevelsCache_[value];260 }261 for (var i = 0; i < goog.debug.Logger.Level.PREDEFINED_LEVELS.length; ++i) {262 var level = goog.debug.Logger.Level.PREDEFINED_LEVELS[i];263 if (level.value <= value) {264 return level;265 }266 }267 return null;268};269/**270 * Find or create a logger for a named subsystem. If a logger has already been271 * created with the given name it is returned. Otherwise a new logger is272 * created. If a new logger is created its log level will be configured based273 * on the LogManager configuration and it will configured to also send logging274 * output to its parent's handlers. It will be registered in the LogManager275 * global namespace.276 *277 * @param {string} name A name for the logger. This should be a dot-separated278 * name and should normally be based on the package name or class name of the279 * subsystem, such as goog.net.BrowserChannel.280 * @return {!goog.debug.Logger} The named logger.281 */282goog.debug.Logger.getLogger = function(name) {283 return goog.debug.LogManager.getLogger(name);284};285/**286 * Gets the name of this logger.287 * @return {string} The name of this logger.288 */289goog.debug.Logger.prototype.getName = function() {290 return this.name_;291};292/**293 * Adds a handler to the logger. This doesn't use the event system because294 * we want to be able to add logging to the event system.295 * @param {Function} handler Handler function to add.296 */297goog.debug.Logger.prototype.addHandler = function(handler) {298 if (goog.debug.Logger.ENABLE_HIERARCHY) {299 if (!this.handlers_) {300 this.handlers_ = [];301 }302 this.handlers_.push(handler);303 } else {304 goog.asserts.assert(!this.name_,305 'Cannot call addHandler on a non-root logger when ' +306 'goog.debug.Logger.ENABLE_HIERARCHY is false.');307 goog.debug.Logger.rootHandlers_.push(handler);308 }309};310/**311 * Removes a handler from the logger. This doesn't use the event system because312 * we want to be able to add logging to the event system.313 * @param {Function} handler Handler function to remove.314 * @return {boolean} Whether the handler was removed.315 */316goog.debug.Logger.prototype.removeHandler = function(handler) {317 var handlers = goog.debug.Logger.ENABLE_HIERARCHY ? this.handlers_ :318 goog.debug.Logger.rootHandlers_;319 return !!handlers && goog.array.remove(handlers, handler);320};321/**322 * Returns the parent of this logger.323 * @return {goog.debug.Logger} The parent logger or null if this is the root.324 */325goog.debug.Logger.prototype.getParent = function() {326 return this.parent_;327};328/**329 * Returns the children of this logger as a map of the child name to the logger.330 * @return {!Object} The map where the keys are the child leaf names and the331 * values are the Logger objects.332 */333goog.debug.Logger.prototype.getChildren = function() {334 if (!this.children_) {335 this.children_ = {};336 }337 return this.children_;338};339/**340 * Set the log level specifying which message levels will be logged by this341 * logger. Message levels lower than this value will be discarded.342 * The level value Level.OFF can be used to turn off logging. If the new level343 * is null, it means that this node should inherit its level from its nearest344 * ancestor with a specific (non-null) level value.345 *346 * @param {goog.debug.Logger.Level} level The new level.347 */348goog.debug.Logger.prototype.setLevel = function(level) {349 if (goog.debug.Logger.ENABLE_HIERARCHY) {350 this.level_ = level;351 } else {352 goog.asserts.assert(!this.name_,353 'Cannot call setLevel() on a non-root logger when ' +354 'goog.debug.Logger.ENABLE_HIERARCHY is false.');355 goog.debug.Logger.rootLevel_ = level;356 }357};358/**359 * Gets the log level specifying which message levels will be logged by this360 * logger. Message levels lower than this value will be discarded.361 * The level value Level.OFF can be used to turn off logging. If the level362 * is null, it means that this node should inherit its level from its nearest363 * ancestor with a specific (non-null) level value.364 *365 * @return {goog.debug.Logger.Level} The level.366 */367goog.debug.Logger.prototype.getLevel = function() {368 return this.level_;369};370/**371 * Returns the effective level of the logger based on its ancestors' levels.372 * @return {goog.debug.Logger.Level} The level.373 */374goog.debug.Logger.prototype.getEffectiveLevel = function() {375 if (!goog.debug.Logger.ENABLE_HIERARCHY) {376 return goog.debug.Logger.rootLevel_;377 }378 if (this.level_) {379 return this.level_;380 }381 if (this.parent_) {382 return this.parent_.getEffectiveLevel();383 }384 goog.asserts.fail('Root logger has no level set.');385 return null;386};387/**388 * Check if a message of the given level would actually be logged by this389 * logger. This check is based on the Loggers effective level, which may be390 * inherited from its parent.391 * @param {goog.debug.Logger.Level} level The level to check.392 * @return {boolean} Whether the message would be logged.393 */394goog.debug.Logger.prototype.isLoggable = function(level) {395 return level.value >= this.getEffectiveLevel().value;396};397/**398 * Log a message. If the logger is currently enabled for the399 * given message level then the given message is forwarded to all the400 * registered output Handler objects.401 * @param {goog.debug.Logger.Level} level One of the level identifiers.402 * @param {string} msg The string message.403 * @param {Error|Object=} opt_exception An exception associated with the404 * message.405 */406goog.debug.Logger.prototype.log = function(level, msg, opt_exception) {407 // java caches the effective level, not sure it's necessary here408 if (this.isLoggable(level)) {409 this.doLogRecord_(this.getLogRecord(level, msg, opt_exception));410 }411};412/**413 * Creates a new log record and adds the exception (if present) to it.414 * @param {goog.debug.Logger.Level} level One of the level identifiers.415 * @param {string} msg The string message.416 * @param {Error|Object=} opt_exception An exception associated with the417 * message.418 * @return {!goog.debug.LogRecord} A log record.419 */420goog.debug.Logger.prototype.getLogRecord = function(level, msg, opt_exception) {421 if (goog.debug.LogBuffer.isBufferingEnabled()) {422 var logRecord =423 goog.debug.LogBuffer.getInstance().addRecord(level, msg, this.name_);424 } else {425 logRecord = new goog.debug.LogRecord(level, String(msg), this.name_);426 }427 if (opt_exception) {428 logRecord.setException(opt_exception);429 logRecord.setExceptionText(430 goog.debug.exposeException(opt_exception, arguments.callee.caller));431 }432 return logRecord;433};434/**435 * Log a message at the Logger.Level.SHOUT level.436 * If the logger is currently enabled for the given message level then the437 * given message is forwarded to all the registered output Handler objects.438 * @param {string} msg The string message.439 * @param {Error=} opt_exception An exception associated with the message.440 */441goog.debug.Logger.prototype.shout = function(msg, opt_exception) {442 this.log(goog.debug.Logger.Level.SHOUT, msg, opt_exception);443};444/**445 * Log a message at the Logger.Level.SEVERE level.446 * If the logger is currently enabled for the given message level then the447 * given message is forwarded to all the registered output Handler objects.448 * @param {string} msg The string message.449 * @param {Error=} opt_exception An exception associated with the message.450 */451goog.debug.Logger.prototype.severe = function(msg, opt_exception) {452 this.log(goog.debug.Logger.Level.SEVERE, msg, opt_exception);453};454/**455 * Log a message at the Logger.Level.WARNING level.456 * If the logger is currently enabled for the given message level then the457 * given message is forwarded to all the registered output Handler objects.458 * @param {string} msg The string message.459 * @param {Error=} opt_exception An exception associated with the message.460 */461goog.debug.Logger.prototype.warning = function(msg, opt_exception) {462 this.log(goog.debug.Logger.Level.WARNING, msg, opt_exception);463};464/**465 * Log a message at the Logger.Level.INFO level.466 * If the logger is currently enabled for the given message level then the467 * given message is forwarded to all the registered output Handler objects.468 * @param {string} msg The string message.469 * @param {Error=} opt_exception An exception associated with the message.470 */471goog.debug.Logger.prototype.info = function(msg, opt_exception) {472 this.log(goog.debug.Logger.Level.INFO, msg, opt_exception);473};474/**475 * Log a message at the Logger.Level.CONFIG level.476 * If the logger is currently enabled for the given message level then the477 * given message is forwarded to all the registered output Handler objects.478 * @param {string} msg The string message.479 * @param {Error=} opt_exception An exception associated with the message.480 */481goog.debug.Logger.prototype.config = function(msg, opt_exception) {482 this.log(goog.debug.Logger.Level.CONFIG, msg, opt_exception);483};484/**485 * Log a message at the Logger.Level.FINE level.486 * If the logger is currently enabled for the given message level then the487 * given message is forwarded to all the registered output Handler objects.488 * @param {string} msg The string message.489 * @param {Error=} opt_exception An exception associated with the message.490 */491goog.debug.Logger.prototype.fine = function(msg, opt_exception) {492 this.log(goog.debug.Logger.Level.FINE, msg, opt_exception);493};494/**495 * Log a message at the Logger.Level.FINER level.496 * If the logger is currently enabled for the given message level then the497 * given message is forwarded to all the registered output Handler objects.498 * @param {string} msg The string message.499 * @param {Error=} opt_exception An exception associated with the message.500 */501goog.debug.Logger.prototype.finer = function(msg, opt_exception) {502 this.log(goog.debug.Logger.Level.FINER, msg, opt_exception);503};504/**505 * Log a message at the Logger.Level.FINEST level.506 * If the logger is currently enabled for the given message level then the507 * given message is forwarded to all the registered output Handler objects.508 * @param {string} msg The string message.509 * @param {Error=} opt_exception An exception associated with the message.510 */511goog.debug.Logger.prototype.finest = function(msg, opt_exception) {512 this.log(goog.debug.Logger.Level.FINEST, msg, opt_exception);513};514/**515 * Log a LogRecord. If the logger is currently enabled for the516 * given message level then the given message is forwarded to all the517 * registered output Handler objects.518 * @param {goog.debug.LogRecord} logRecord A log record to log.519 */520goog.debug.Logger.prototype.logRecord = function(logRecord) {521 if (this.isLoggable(logRecord.getLevel())) {522 this.doLogRecord_(logRecord);523 }524};525/**526 * Logs the message to speed tracer, if it is available.527 * {@see http://code.google.com/webtoolkit/speedtracer/logging-api.html}528 * @param {string} msg The message to log.529 * @private530 */531goog.debug.Logger.prototype.logToSpeedTracer_ = function(msg) {532 if (goog.global['console'] && goog.global['console']['markTimeline']) {533 goog.global['console']['markTimeline'](msg);534 }535};536/**537 * Log a LogRecord.538 * @param {goog.debug.LogRecord} logRecord A log record to log.539 * @private540 */541goog.debug.Logger.prototype.doLogRecord_ = function(logRecord) {542 this.logToSpeedTracer_('log:' + logRecord.getMessage());543 if (goog.debug.Logger.ENABLE_HIERARCHY) {544 var target = this;545 while (target) {546 target.callPublish_(logRecord);547 target = target.getParent();548 }549 } else {550 for (var i = 0, handler; handler = goog.debug.Logger.rootHandlers_[i++]; ) {551 handler(logRecord);552 }553 }554};555/**556 * Calls the handlers for publish.557 * @param {goog.debug.LogRecord} logRecord The log record to publish.558 * @private559 */560goog.debug.Logger.prototype.callPublish_ = function(logRecord) {561 if (this.handlers_) {562 for (var i = 0, handler; handler = this.handlers_[i]; i++) {563 handler(logRecord);564 }565 }566};567/**568 * Sets the parent of this logger. This is used for setting up the logger tree.569 * @param {goog.debug.Logger} parent The parent logger.570 * @private571 */572goog.debug.Logger.prototype.setParent_ = function(parent) {573 this.parent_ = parent;574};575/**576 * Adds a child to this logger. This is used for setting up the logger tree.577 * @param {string} name The leaf name of the child.578 * @param {goog.debug.Logger} logger The child logger.579 * @private580 */581goog.debug.Logger.prototype.addChild_ = function(name, logger) {582 this.getChildren()[name] = logger;583};584/**585 * There is a single global LogManager object that is used to maintain a set of586 * shared state about Loggers and log services. This is loosely based on the587 * java class java.util.logging.LogManager.588 */589goog.debug.LogManager = {};590/**591 * Map of logger names to logger objects592 *593 * @type {!Object}594 * @private595 */596goog.debug.LogManager.loggers_ = {};597/**598 * The root logger which is the root of the logger tree.599 * @type {goog.debug.Logger}600 * @private601 */602goog.debug.LogManager.rootLogger_ = null;603/**604 * Initialize the LogManager if not already initialized605 */606goog.debug.LogManager.initialize = function() {607 if (!goog.debug.LogManager.rootLogger_) {608 goog.debug.LogManager.rootLogger_ = new goog.debug.Logger('');609 goog.debug.LogManager.loggers_[''] = goog.debug.LogManager.rootLogger_;610 goog.debug.LogManager.rootLogger_.setLevel(goog.debug.Logger.Level.CONFIG);611 }612};613/**614 * Returns all the loggers615 * @return {!Object} Map of logger names to logger objects.616 */617goog.debug.LogManager.getLoggers = function() {618 return goog.debug.LogManager.loggers_;619};620/**621 * Returns the root of the logger tree namespace, the logger with the empty622 * string as its name623 *624 * @return {!goog.debug.Logger} The root logger.625 */626goog.debug.LogManager.getRoot = function() {627 goog.debug.LogManager.initialize();628 return /** @type {!goog.debug.Logger} */ (goog.debug.LogManager.rootLogger_);629};630/**631 * Method to find a named logger.632 *633 * @param {string} name A name for the logger. This should be a dot-separated634 * name and should normally be based on the package name or class name of the635 * subsystem, such as goog.net.BrowserChannel.636 * @return {!goog.debug.Logger} The named logger.637 */638goog.debug.LogManager.getLogger = function(name) {639 goog.debug.LogManager.initialize();640 var ret = goog.debug.LogManager.loggers_[name];641 return ret || goog.debug.LogManager.createLogger_(name);642};643/**644 * Creates a function that can be passed to goog.debug.catchErrors. The function645 * will log all reported errors using the given logger.646 * @param {goog.debug.Logger=} opt_logger The logger to log the errors to.647 * Defaults to the root logger.648 * @return {function(Object)} The created function.649 */650goog.debug.LogManager.createFunctionForCatchErrors = function(opt_logger) {651 return function(info) {652 var logger = opt_logger || goog.debug.LogManager.getRoot();653 logger.severe('Error: ' + info.message + ' (' + info.fileName +654 ' @ Line: ' + info.line + ')');655 };656};657/**658 * Creates the named logger. Will also create the parents of the named logger659 * if they don't yet exist.660 * @param {string} name The name of the logger.661 * @return {!goog.debug.Logger} The named logger.662 * @private663 */664goog.debug.LogManager.createLogger_ = function(name) {665 // find parent logger666 var logger = new goog.debug.Logger(name);667 if (goog.debug.Logger.ENABLE_HIERARCHY) {668 var lastDotIndex = name.lastIndexOf('.');669 var parentName = name.substr(0, lastDotIndex);670 var leafName = name.substr(lastDotIndex + 1);671 var parentLogger = goog.debug.LogManager.getLogger(parentName);672 // tell the parent about the child and the child about the parent673 parentLogger.addChild_(leafName, logger);674 logger.setParent_(parentLogger);675 }676 goog.debug.LogManager.loggers_[name] = logger;677 return logger;...
logger.spec.js
Source:logger.spec.js
1'use strict'2/*3 * adonis-framework4 *5 * (c) Harminder Virk <virk@adonisjs.com>6 *7 * For the full copyright and license information, please view the LICENSE8 * file that was distributed with this source code.9*/10const test = require('japa')11const path = require('path')12const fs = require('fs-extra')13const { ioc } = require('@adonisjs/fold')14const stdout = require('test-console').stdout15const { Config, Helpers } = require('@adonisjs/sink')16const FileDriver = require('../../src/Logger/Drivers').file17const ConsoleDriver = require('../../src/Logger/Drivers').console18const Logger = require('../../src/Logger')19const LoggerManager = require('../../src/Logger/Manager')20const LoggerFacade = require('../../src/Logger/Facade')21const sysLog = {22 emerg: 0,23 alert: 1,24 crit: 2,25 error: 3,26 warning: 4,27 notice: 5,28 info: 6,29 debug: 730}31test.group('Logger | File Driver', (group) => {32 group.beforeEach(() => {33 this.helpers = new Helpers(path.join(__dirname))34 })35 group.before((done) => {36 fs.ensureDir(path.join(__dirname, 'tmp'), done)37 })38 group.after((done) => {39 if (process.platform === 'win32') {40 return done()41 }42 fs.remove(path.join(__dirname, 'tmp'), done)43 })44 test('initiate logger with correct settings', (assert) => {45 const fileDriver = new FileDriver(this.helpers)46 fileDriver.setConfig({})47 assert.deepEqual(fileDriver.logger.levels, sysLog)48 assert.equal(fileDriver.logger.transports[0].dirname, path.join(__dirname, 'tmp'))49 })50 test('do not override filename when it is absolute path', (assert) => {51 const fileDriver = new FileDriver(this.helpers)52 fileDriver.setConfig({53 filename: path.join(__dirname, 'tmp', 'my.log')54 })55 assert.equal(fileDriver.config.filename, path.join(__dirname, 'tmp', 'my.log'))56 })57 test('log info to the file', (assert, done) => {58 const fileDriver = new FileDriver(this.helpers)59 fileDriver.setConfig({})60 fileDriver.logger.on('finish', () => {61 fs.readFile(fileDriver.config.filename, (error, contents) => {62 if (error) {63 return done(error)64 }65 contents = JSON.parse(contents)66 assert.equal(contents.message, 'hello')67 assert.equal(contents.level, 'info')68 done()69 })70 })71 fileDriver.log(6, 'hello')72 /**73 * Waiting for the transporter to write the file and then end74 * the logger75 */76 setTimeout(() => {77 fileDriver.logger.end()78 }, 100)79 }).timeout(3000)80 test('return active log level', (assert) => {81 const fileDriver = new FileDriver(this.helpers)82 fileDriver.setConfig({})83 assert.equal(fileDriver.level, 'info')84 })85 test('update log level', (assert) => {86 const fileDriver = new FileDriver(this.helpers)87 fileDriver.setConfig({})88 fileDriver.level = 'debug'89 assert.equal(fileDriver.level, 'debug')90 })91})92test.group('Logger | Console Driver', () => {93 test('initiate logger with correct settings', (assert) => {94 const consoleDriver = new ConsoleDriver()95 consoleDriver.setConfig({})96 assert.deepEqual(consoleDriver.logger.levels, sysLog)97 })98 test('log info to the console', (assert, done) => {99 const consoleDriver = new ConsoleDriver()100 consoleDriver.setConfig({})101 const inspect = stdout.inspect()102 consoleDriver.logger.on('finish', () => {103 inspect.restore()104 assert.include(inspect.output[0], 'hello')105 done()106 })107 consoleDriver.log(6, 'hello')108 consoleDriver.logger.end()109 }).timeout(3000)110 test('return active log level', (assert) => {111 const consoleDriver = new ConsoleDriver()112 consoleDriver.setConfig({})113 assert.equal(consoleDriver.level, 'info')114 })115 test('update log level', (assert) => {116 const consoleDriver = new ConsoleDriver()117 consoleDriver.setConfig({})118 consoleDriver.level = 'debug'119 assert.equal(consoleDriver.level, 'debug')120 })121})122test.group('Logger | Instance', (group) => {123 test('log info using defined driver', (assert, done) => {124 const consoleDriver = new ConsoleDriver()125 consoleDriver.setConfig({})126 const logger = new Logger(consoleDriver)127 const inspect = stdout.inspect()128 consoleDriver.logger.on('finish', () => {129 inspect.restore()130 assert.include(inspect.output[0], 'info')131 done()132 })133 logger.info('hello')134 consoleDriver.logger.end()135 })136 test('log warning using defined driver', (assert) => {137 const consoleDriver = new ConsoleDriver()138 consoleDriver.setConfig({})139 const logger = new Logger(consoleDriver)140 const inspect = stdout.inspect()141 logger.warning('hello')142 inspect.restore()143 assert.include(inspect.output[0], 'warning')144 })145 test('do not log level before the level defined on the driver', (assert) => {146 const consoleDriver = new ConsoleDriver()147 consoleDriver.setConfig({ level: 'info' })148 const logger = new Logger(consoleDriver)149 const inspect = stdout.inspect()150 logger.debug('hello')151 inspect.restore()152 assert.lengthOf(inspect.output, 0)153 })154 test('update log level', (assert) => {155 const consoleDriver = new ConsoleDriver()156 consoleDriver.setConfig({})157 const logger = new Logger(consoleDriver)158 logger.level = 'debug'159 const inspect = stdout.inspect()160 logger.debug('hello')161 inspect.restore()162 assert.include(inspect.output[0], 'debug')163 })164 test('get current log level', (assert) => {165 const consoleDriver = new ConsoleDriver()166 consoleDriver.setConfig({})167 const logger = new Logger(consoleDriver)168 assert.equal(logger.level, 'info')169 })170})171test.group('Logger | Manager', (group) => {172 group.before(() => {173 ioc.fake('Adonis/Src/Config', () => new Config())174 ioc.fake('Adonis/Src/Helpers', () => new Helpers(path.join(__dirname)))175 })176 test('extend logger by adding drivers', (assert) => {177 const myDriver = {}178 LoggerManager.extend('myDriver', myDriver)179 assert.deepEqual(LoggerManager._drivers, { myDriver })180 })181 test('throw error when trying to access invalid driver', (assert) => {182 const fn = () => LoggerManager.driver('foo')183 assert.throw(fn, 'E_INVALID_LOGGER_DRIVER: Logger driver foo does not exists')184 })185 test('return driver instance for a given driver', (assert) => {186 const consoleDriver = LoggerManager.driver('console')187 assert.instanceOf(consoleDriver, ConsoleDriver)188 })189})190test.group('Logger | Facade', (group) => {191 group.before(() => {192 ioc.fake('Adonis/Src/Config', () => new Config())193 ioc.fake('Adonis/Src/Helpers', () => new Helpers(path.join(__dirname)))194 })195 test('return logger instance with selected driver', (assert) => {196 const config = new Config()197 config.set('app.logger.file', {198 driver: 'file'199 })200 const logger = new LoggerFacade(config)201 assert.instanceOf(logger.transport('file'), Logger)202 assert.instanceOf(logger.transport('file').driver, FileDriver)203 })204 test('return logger instance with extended driver', (assert) => {205 const myDriver = {206 setConfig () {}207 }208 LoggerManager.extend('mydriver', myDriver)209 const config = new Config()210 config.set('app.logger.mydriver', {211 driver: 'mydriver'212 })213 const logger = new LoggerFacade(config)214 assert.instanceOf(logger.transport('mydriver'), Logger)215 assert.deepEqual(logger.transport('mydriver').driver, myDriver)216 })217 test('create singleton logger instances', (assert) => {218 const config = new Config()219 config.set('app.logger.file', {220 driver: 'file'221 })222 const logger = new LoggerFacade(config)223 logger.transport('file')224 assert.lengthOf(Object.keys(logger._loggerInstances), 1)225 logger.transport('file')226 assert.lengthOf(Object.keys(logger._loggerInstances), 1)227 })228 test('create different instance when transport is different', (assert) => {229 const config = new Config()230 config.set('app.logger.file', {231 driver: 'file'232 })233 config.set('app.logger.anotherFile', {234 driver: 'file'235 })236 const logger = new LoggerFacade(config)237 logger.transport('file')238 assert.lengthOf(Object.keys(logger._loggerInstances), 1)239 logger.transport('anotherFile')240 assert.lengthOf(Object.keys(logger._loggerInstances), 2)241 })242 test('proxy logger instance methods', (assert) => {243 const config = new Config()244 config.set('app.logger', {245 transport: 'console',246 console: {247 driver: 'console'248 }249 })250 const logger = new LoggerFacade(config)251 const inspect = stdout.inspect()252 logger.info('hello')253 inspect.restore()254 assert.include(inspect.output[0], 'hello')255 })256 test('throw exception when driver is invalid', (assert) => {257 const config = new Config()258 config.set('app.logger', {259 transport: 'console',260 console: {261 driver: 'foo'262 }263 })264 const logger = new LoggerFacade(config)265 const fn = () => logger.debug('')266 assert.throw(fn, 'E_INVALID_LOGGER_DRIVER: Logger driver foo does not exists')267 })268 test('throw exception when no transport is defined', (assert) => {269 const config = new Config()270 config.set('app.logger', {271 })272 const logger = new LoggerFacade(config)273 const fn = () => logger.debug('')274 assert.throw(fn, 'E_MISSING_CONFIG: logger.transport is not defined inside config/app.js file')275 })276 test('access loglevels from facade', (assert) => {277 const config = new Config()278 config.set('app.logger', {279 transport: 'file',280 file: {281 driver: 'file'282 }283 })284 const logger = new LoggerFacade(config)285 assert.deepEqual(logger.levels, {286 alert: 1,287 crit: 2,288 debug: 7,289 emerg: 0,290 error: 3,291 info: 6,292 notice: 5,293 warning: 4294 })295 })296 test('update log level from facade', (assert) => {297 const config = new Config()298 config.set('app.logger', {299 transport: 'console',300 console: {301 driver: 'console'302 }303 })304 const logger = new LoggerFacade(config)305 const inspect = stdout.inspect()306 logger.level = 'debug'307 logger.debug('foo')308 inspect.restore()309 assert.include(inspect.output[0], 'foo')310 })...
test_logger.py
Source:test_logger.py
...23 self.closed = True24class TestLogger(unittest.TestCase):25 def setUp(self):26 self.logger = Logger(register_console_logger=False)27 def test_write_to_one_logger(self):28 logger = LoggerMock(('Hello, world!', 'INFO'))29 self.logger.register_logger(logger)30 self.logger.write('Hello, world!', 'INFO')31 assert_true(logger.msg.timestamp.startswith('20'))32 def test_write_to_one_logger_with_trace_level(self):33 logger = LoggerMock(('expected message', 'TRACE'))34 self.logger.register_logger(logger)35 self.logger.write('expected message', 'TRACE')36 assert_true(hasattr(logger, 'msg'))37 def test_write_to_multiple_loggers(self):38 logger = LoggerMock(('Hello, world!', 'INFO'))39 logger2 = logger.copy()40 logger3 = logger.copy()41 self.logger.register_logger(logger, logger2, logger3)42 self.logger.message(MessageMock('', 'INFO', 'Hello, world!'))43 assert_true(logger.msg is logger2.msg)44 assert_true(logger.msg is logger.msg)45 def test_write_multiple_messages(self):46 msgs = [('0', 'ERROR'), ('1', 'WARN'), ('2', 'INFO'), ('3', 'DEBUG'), ('4', 'TRACE')]47 logger = LoggerMock(*msgs)48 self.logger.register_logger(logger)49 for msg, level in msgs:50 self.logger.write(msg, level)51 assert_equals(logger.msg.message, msg)52 assert_equals(logger.msg.level, level)53 def test_all_methods(self):54 logger = LoggerMock2(('Hello, world!', 'INFO'))55 self.logger.register_logger(logger)56 self.logger.output_file('name', 'path')57 self.logger.close()58 assert_equals(logger.output_file, ('name', 'path'))59 assert_true(logger.closed)60 def test_registered_logger_does_not_need_all_methods(self):61 logger = LoggerMock(('Hello, world!', 'INFO'))62 self.logger.register_logger(logger)63 self.logger.output_file('name', 'path')64 self.logger.close()65 def test_close_removes_registered_loggers(self):66 logger = LoggerMock(('Hello, world!', 'INFO'))67 logger2 = LoggerMock2(('Hello, world!', 'INFO'))68 self.logger.register_logger(logger, logger2)69 self.logger.close()70 assert_equals(self.logger._loggers.all_loggers(), [])71 def test_registering_file_logger_with_none_path_does_nothing(self):72 self.logger.register_file_logger('None')73 assert_equals(self.logger._loggers.all_loggers(), [])74 def test_cached_messages_are_given_to_registered_writers(self):75 self.logger.write('This is a cached message', 'INFO')76 self.logger.write('Another cached message', 'TRACE')77 logger = LoggerMock(('This is a cached message', 'INFO'),78 ('Another cached message', 'TRACE'))79 self.logger.register_logger(logger)80 assert_equals(logger.msg.message, 'Another cached message')81 def test_message_cache_can_be_turned_off(self):82 self.logger.disable_message_cache()83 self.logger.write('This message is not cached', 'INFO')84 logger = LoggerMock(('', ''))85 self.logger.register_logger(logger)86 assert_false(hasattr(logger, 'msg'))87 def test_start_and_end_suite_test_and_keyword(self):88 class MyLogger:89 def start_suite(self, suite): self.started_suite = suite90 def end_suite(self, suite): self.ended_suite = suite91 def start_test(self, test): self.started_test = test92 def end_test(self, test): self.ended_test = test93 def start_keyword(self, keyword): self.started_keyword = keyword94 def end_keyword(self, keyword): self.ended_keyword = keyword95 logger = MyLogger()96 self.logger.register_logger(logger)97 for name in 'suite', 'test', 'keyword':98 for stend in 'start', 'end':99 getattr(self.logger, stend + '_' + name)(name)100 assert_equals(getattr(logger, stend + 'ed_' + name), name)101 def test_console_logger_is_automatically_registered(self):102 logger = Logger()103 assert_true(logger._loggers.all_loggers()[0].start_suite.im_class is CommandLineMonitor)104 def test_loggercollection_is_iterable(self):105 logger = Logger()106 for log in logger._loggers:107 assert_true(log)108 def test_logger_is_iterable(self):109 logger = Logger()110 for log in logger:111 assert_true(log)112 assert_equals(list(logger), list(logger._loggers))113 def test_automatic_console_logger_can_be_disabled(self):114 logger = Logger()115 logger.unregister_console_logger()116 assert_equals(logger._loggers.all_loggers(), [])117 def test_automatic_console_logger_can_be_disabled_after_registering_logger(self):118 logger = Logger()119 mock = LoggerMock()120 logger.register_logger(mock)121 logger.unregister_console_logger()122 self._number_of_registered_loggers_should_be(1, logger)123 assert_true(logger._loggers.all_loggers()[0].message.im_class is LoggerMock)124 def test_disabling_automatic_logger_multiple_times_has_no_effect(self):125 logger = Logger()126 logger.unregister_console_logger()127 self._number_of_registered_loggers_should_be(0, logger)128 logger.unregister_console_logger()129 logger.unregister_console_logger()130 self._number_of_registered_loggers_should_be(0, logger)131 logger.register_logger(LoggerMock())132 logger.unregister_console_logger()133 self._number_of_registered_loggers_should_be(1, logger)134 def test_registering_console_logger_disables_automatic_console_logger(self):135 logger = Logger()136 logger.register_console_logger(width=42)137 self._number_of_registered_loggers_should_be(1, logger)138 assert_equals(logger._loggers.all_loggers()[0].start_suite.im_self._writer._width, 42)139 def test_unregister_logger(self):140 logger1, logger2, logger3 = LoggerMock(), LoggerMock(), LoggerMock()141 self.logger.register_logger(logger1, logger2, logger3)142 self.logger.unregister_logger(logger2)143 self._number_of_registered_loggers_should_be(2)144 self.logger.unregister_logger(logger3, logger1)145 self._number_of_registered_loggers_should_be(0)146 def test_unregistering_non_registered_logger_is_ok(self):147 logger1, logger2 = LoggerMock(), LoggerMock()148 self.logger.register_logger(logger1)149 self.logger.unregister_logger(logger2)150 self.logger.unregister_logger(None)151 def test_registering_context_changing_logger(self):152 self.logger.register_context_changing_logger(LoggerMock())153 self._number_of_registered_loggers_should_be(1)154 def test_messages_to_context_chagning_loggers(self):155 log = LoggerMock(('msg', 'INFO'))156 self.logger.register_context_changing_logger(log)157 self.logger.write('msg', 'INFO')158 assert_true(log.msg is not None)159 def test_start_methods_are_called_first_for_context_changing_loggers(self):160 class FirstLogger:161 def start_suite(self, suite): self.suite = suite162 def start_test(self, test): self.test = test163 def start_keyword(self, kw): self.kw = kw164 class SecondLogger:165 def __init__(self, logger): self._reference = logger166 def start_suite(self, suite): assert_equals(suite, self._reference.suite)167 def start_test(self, test): assert_equals(test, self._reference.test)168 def start_keyword(self, kw): assert_equals(kw, self._reference.kw)169 log1 = FirstLogger()170 log2 = SecondLogger(log1)171 self.logger.register_logger(log2)172 self.logger.register_context_changing_logger(log1)173 self.logger.start_suite('Suite')174 self.logger.start_test('Test')175 self.logger.start_keyword('Keyword')176 def test_end_methods_are_called_last_for_context_changing_loggers(self):177 class FirstLogger:178 def end_suite(self, suite): self.suite = suite179 def end_test(self, test): self.test = test180 def end_keyword(self, kw): self.kw = kw181 class SecondLogger:182 def __init__(self, logger): self._reference = logger183 def end_suite(self, suite): self.suite = suite; assert_equals(suite, self._reference.suite)184 def end_test(self, test): assert_equals(test, self._reference.test)185 def end_keyword(self, kw): assert_equals(kw, self._reference.kw)186 log1 = FirstLogger()187 log2 = SecondLogger(log1)188 self.logger.register_logger(log1)189 self.logger.register_context_changing_logger(log2)190 self.logger.end_suite('Suite')191 self.logger.end_test('Test')192 self.logger.end_keyword('Keyword')193 assert_true(log2.suite is not None)194 def _number_of_registered_loggers_should_be(self, number, logger=None):195 logger = logger or self.logger196 assert_equals(len(logger._loggers.all_loggers()), number)197if __name__ == "__main__":...
cloudinaryCon.js
Source:cloudinaryCon.js
1/**2 * #k_infinityIII@Echwood3 *4 * cloudinaryCon:5 * sets up enviroment to upload images and videos6 *7 * Fucntions:8 *9 *10 */11// Config settings12import config from '../utils/config'13import schoolEvent from '../../interfaces/Events/schoolEvents'14import winstonLogger from '../utils/winstonLogger'15import cloudinary from 'cloudinary'16// const cloudinary = require('cloudinary').v217cloudinary.config({ 18 cloud_name: config.cloudinaryName, 19 api_key: config.cloudinaryAPIKey, 20 api_secret: config.cloudinarySecret 21})22const cloudinaryCon = {23 async uploadSchoolLogo(Logo, Name, schoolID){24 let res = null 25 const schoolID0 = schoolID + "Logo"26 winstonLogger.info("CLOUDINARY")27 winstonLogger.info(JSON.stringify(cloudinary.v2,null,4))28 await cloudinary.v2.uploader.upload(29 Logo, 30 {31 folder: Name,32 public_id: schoolID0,33 overwrite: true,34 invalidate: true,35 width: 810, height: 456, crop: "fill"36 }).37 then((result) => {38 res = result39 }).40 catch((e) => {41 winstonLogger.error('Error uploading Image')42 winstonLogger.error(JSON.stringify(e,null,4))43 return res = false44 })45 // Emit event for LogoPersistence46 try {47 48 winstonLogger.info('Upload Result')49 winstonLogger.info(JSON.stringify(res.url, null,4))50 51 if(res !== null && res !== false){52 } 53 const schoolName = Name54 const logoURL = res.url55 winstonLogger.info('EVENT PARAMETERS')56 winstonLogger.info(Name)57 winstonLogger.info(schoolID)58 winstonLogger.info(res.url)59 // fire Events then send payload60 schoolEvent.61 emit('school-logoUploaded',62 {// send params63 schoolName,64 schoolID, 65 logoURL66 })67 return res = true68 } catch (e) {69 70 winstonLogger.error('Error emitting event')71 winstonLogger.error(JSON.stringify(e,null,4))72 return res = false73 }74 // Check if the db url was updated else persist the picture to local storage[serialise] and try again later75 76 return res77 }, 78 async uploadSchoolImages(Images){79 cloudinary.v2.uploader.upload(80 Image,81 {82 },83 (e,res) => {84 if( e != null ){85 86 winstonLogger.error(e)87 }88 winstonLogger.info(res)89 return res90 })91 },92 //uploadNotificationImages93 async uploadNotificationImages(noteTitle,notificationID,notificationImage, Name, schoolID){94 let res = null 95 winstonLogger.info("CLOUDINARY")96 winstonLogger.info(noteTitle)97 winstonLogger.info(notificationID)98 winstonLogger.info(notificationImage)99 winstonLogger.info(schoolID)100 winstonLogger.info(Name)101 102 await cloudinary.v2.uploader.upload(103 notificationImage, 104 {105 folder: Name+"/"+"notifications",106 public_id: noteTitle,107 overwrite: true,108 invalidate: true,109 // width: 810, height: 456, crop: "fill"110 }).111 then((result) => {112 winstonLogger.info('UPLOADING...')113 winstonLogger.info(JSON.stringify(result,null,4))114 res = result115 }).116 catch((e) => {117 winstonLogger.error('Error uploading Image')118 winstonLogger.error(JSON.stringify(e,null,4))119 return res = false120 })121 // Emit event for Persistence122 try {123 124 winstonLogger.info('Upload Result')125 winstonLogger.info(JSON.stringify(res.url, null,4))126 127 if(res !== null && res !== false){128 } 129 const schoolName = Name130 const notificationURL = res.url131 winstonLogger.info('EVENT PARAMETERS')132 winstonLogger.info(Name)133 winstonLogger.info(schoolID)134 winstonLogger.info(res.url)135 // fire Events then send payload136 schoolEvent.137 emit('school-notificationImageUploaded',138 {// send params139 schoolName,140 schoolID,141 notificationID, 142 notificationURL143 })144 return res = true145 } catch (e) {146 147 winstonLogger.error('Error emitting event')148 winstonLogger.error(JSON.stringify(e,null,4))149 return res = false150 }151 // Check if the db url was updated else persist the picture to local storage[serialise] and try again later152 return res153 },154 //155 async uploadLectureNote(schoolName,schoolID,subjectName,lectureNoteTitle,lectureNoteData,teacherID,classAlias){156 let res = null 157 winstonLogger.info("CLOUDINARY")158 winstonLogger.info(schoolName)159 winstonLogger.info(schoolID)160 winistsonLogger.info(subjectName)161 winstonLogger.info(lectureNoteTitle)162 winstonLogger.info(lectureNoteData)163 winstonLogger.info(teacherID)164 winstonLogger.info(classAlias)165 166 await cloudinary.v2.uploader.upload(// PDF167 lectureNoteData, 168 {169 folder: schoolName+"/"+classAlias+"/"+subjectName,170 public_id: lectureNoteTitle,171 overwrite: true,172 invalidate: true,173 // width: 810, height: 456, crop: "fill"174 }).175 then((result) => {176 winstonLogger.info('UPLOADING...')177 winstonLogger.info(JSON.stringify(result,null,4))178 res = result179 }).180 catch((e) => {181 winstonLogger.error('Error uploading Image')182 winstonLogger.error(JSON.stringify(e,null,4))183 return res = false184 })185 // Emit event for Persistence186 try {187 188 winstonLogger.info('Upload Result')189 winstonLogger.info(JSON.stringify(res.url, null,4))190 191 if(res){192 193 const lectureNoteURL = res.url194 winstonLogger.info('EVENT PARAMETERS')195 winstonLogger.info(schoolName)196 winstonLogger.info(schoolID)197 winstonLogger.info(lectureNoteTitle)198 winstonLogger.info(lectureNoteData)199 winstonLogger.info(teacherID)200 winstonLogger.info(classAlias)201 // fire Events then send payload202 schoolEvent.203 emit('school-lectureNoteUpdloaded',204 {// send params205 schoolName,206 schoolID,207 classAlias,208 teacherID,209 subjectName,210 lectureNoteTitle,211 lectureNoteUrl212 })213 return res = true214 }215 } catch (e) {216 217 winstonLogger.error('Error emitting event')218 winstonLogger.error(JSON.stringify(e,null,4))219 return res = false220 }221 // Check if the db url was updated else persist the picture to local storage[serialise] and try again later222 return res223 }224}...
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!!