How to use destination method in wpt

Best JavaScript code snippet using wpt

destination_store.js

Source:destination_store.js Github

copy

Full Screen

1// Copyright (c) 2012 The Chromium Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4cr.define('print_preview', function() {5 'use strict';6 /**7 * A data store that stores destinations and dispatches events when the data8 * store changes.9 * @param {!print_preview.NativeLayer} nativeLayer Used to fetch local print10 * destinations.11 * @param {!print_preview.UserInfo} userInfo User information repository.12 * @param {!print_preview.AppState} appState Application state.13 * @constructor14 * @extends {cr.EventTarget}15 */16 function DestinationStore(nativeLayer, userInfo, appState) {17 cr.EventTarget.call(this);18 /**19 * Used to fetch local print destinations.20 * @type {!print_preview.NativeLayer}21 * @private22 */23 this.nativeLayer_ = nativeLayer;24 /**25 * User information repository.26 * @type {!print_preview.UserInfo}27 * @private28 */29 this.userInfo_ = userInfo;30 /**31 * Used to load and persist the selected destination.32 * @type {!print_preview.AppState}33 * @private34 */35 this.appState_ = appState;36 /**37 * Used to track metrics.38 * @type {!print_preview.DestinationSearchMetricsContext}39 * @private40 */41 this.metrics_ = new print_preview.DestinationSearchMetricsContext();42 /**43 * Internal backing store for the data store.44 * @type {!Array<!print_preview.Destination>}45 * @private46 */47 this.destinations_ = [];48 /**49 * Cache used for constant lookup of destinations by origin and id.50 * @type {Object<!print_preview.Destination>}51 * @private52 */53 this.destinationMap_ = {};54 /**55 * Currently selected destination.56 * @type {print_preview.Destination}57 * @private58 */59 this.selectedDestination_ = null;60 /**61 * Whether the destination store will auto select the destination that62 * matches the last used destination stored in appState_.63 * @type {boolean}64 * @private65 */66 this.isInAutoSelectMode_ = false;67 /**68 * Event tracker used to track event listeners of the destination store.69 * @type {!EventTracker}70 * @private71 */72 this.tracker_ = new EventTracker();73 /**74 * Whether PDF printer is enabled. It's disabled, for example, in App Kiosk75 * mode.76 * @type {boolean}77 * @private78 */79 this.pdfPrinterEnabled_ = false;80 /**81 * Used to fetch cloud-based print destinations.82 * @type {cloudprint.CloudPrintInterface}83 * @private84 */85 this.cloudPrintInterface_ = null;86 /**87 * Maps user account to the list of origins for which destinations are88 * already loaded.89 * @type {!Object<Array<print_preview.Destination.Origin>>}90 * @private91 */92 this.loadedCloudOrigins_ = {};93 /**94 * ID of a timeout after the initial destination ID is set. If no inserted95 * destination matches the initial destination ID after the specified96 * timeout, the first destination in the store will be automatically97 * selected.98 * @type {?number}99 * @private100 */101 this.autoSelectTimeout_ = null;102 /**103 * Whether a search for local destinations is in progress.104 * @type {boolean}105 * @private106 */107 this.isLocalDestinationSearchInProgress_ = false;108 /**109 * Whether the destination store has already loaded or is loading all local110 * destinations.111 * @type {boolean}112 * @private113 */114 this.hasLoadedAllLocalDestinations_ = false;115 /**116 * Whether a search for privet destinations is in progress.117 * @type {boolean}118 * @private119 */120 this.isPrivetDestinationSearchInProgress_ = false;121 /**122 * Whether the destination store has already loaded or is loading all privet123 * destinations.124 * @type {boolean}125 * @private126 */127 this.hasLoadedAllPrivetDestinations_ = false;128 /**129 * ID of a timeout after the start of a privet search to end that privet130 * search.131 * @type {?number}132 * @private133 */134 this.privetSearchTimeout_ = null;135 /**136 * Whether a search for extension destinations is in progress.137 * @type {boolean}138 * @private139 */140 this.isExtensionDestinationSearchInProgress_ = false;141 /**142 * Whether the destination store has already loaded all extension143 * destinations.144 * @type {boolean}145 * @private146 */147 this.hasLoadedAllExtensionDestinations_ = false;148 /**149 * ID of a timeout set at the start of an extension destination search. The150 * timeout ends the search.151 * @type {?number}152 * @private153 */154 this.extensionSearchTimeout_ = null;155 /**156 * MDNS service name of destination that we are waiting to register.157 * @type {?string}158 * @private159 */160 this.waitForRegisterDestination_ = null;161 this.addEventListeners_();162 this.reset_();163 };164 /**165 * Event types dispatched by the data store.166 * @enum {string}167 */168 DestinationStore.EventType = {169 DESTINATION_SEARCH_DONE:170 'print_preview.DestinationStore.DESTINATION_SEARCH_DONE',171 DESTINATION_SEARCH_STARTED:172 'print_preview.DestinationStore.DESTINATION_SEARCH_STARTED',173 DESTINATION_SELECT: 'print_preview.DestinationStore.DESTINATION_SELECT',174 DESTINATIONS_INSERTED:175 'print_preview.DestinationStore.DESTINATIONS_INSERTED',176 PROVISIONAL_DESTINATION_RESOLVED:177 'print_preview.DestinationStore.PROVISIONAL_DESTINATION_RESOLVED',178 CACHED_SELECTED_DESTINATION_INFO_READY:179 'print_preview.DestinationStore.CACHED_SELECTED_DESTINATION_INFO_READY',180 SELECTED_DESTINATION_CAPABILITIES_READY:181 'print_preview.DestinationStore.SELECTED_DESTINATION_CAPABILITIES_READY'182 };183 /**184 * Delay in milliseconds before the destination store ignores the initial185 * destination ID and just selects any printer (since the initial destination186 * was not found).187 * @type {number}188 * @const189 * @private190 */191 DestinationStore.AUTO_SELECT_TIMEOUT_ = 15000;192 /**193 * Amount of time spent searching for privet destination, in milliseconds.194 * @type {number}195 * @const196 * @private197 */198 DestinationStore.PRIVET_SEARCH_DURATION_ = 5000;199 /**200 * Maximum amount of time spent searching for extension destinations, in201 * milliseconds.202 * @type {number}203 * @const204 * @private205 */206 DestinationStore.EXTENSION_SEARCH_DURATION_ = 5000;207 /**208 * Localizes printer capabilities.209 * @param {!Object} capabilities Printer capabilities to localize.210 * @return {!Object} Localized capabilities.211 * @private212 */213 DestinationStore.localizeCapabilities_ = function(capabilities) {214 var mediaSize = capabilities.printer.media_size;215 if (mediaSize) {216 var mediaDisplayNames = {217 'ISO_A4': 'A4',218 'ISO_A3': 'A3',219 'NA_LETTER': 'Letter',220 'NA_LEGAL': 'Legal',221 'NA_LEDGER': 'Tabloid'222 };223 for (var i = 0, media; media = mediaSize.option[i]; i++) {224 // No need to patch capabilities with localized names provided.225 if (!media.custom_display_name_localized) {226 media.custom_display_name =227 media.custom_display_name ||228 mediaDisplayNames[media.name] ||229 media.name;230 }231 }232 }233 return capabilities;234 };235 DestinationStore.prototype = {236 __proto__: cr.EventTarget.prototype,237 /**238 * @param {string=} opt_account Account to filter destinations by. When239 * omitted, all destinations are returned.240 * @return {!Array<!print_preview.Destination>} List of destinations241 * accessible by the {@code account}.242 */243 destinations: function(opt_account) {244 if (opt_account) {245 return this.destinations_.filter(function(destination) {246 return !destination.account || destination.account == opt_account;247 });248 } else {249 return this.destinations_.slice(0);250 }251 },252 /**253 * @return {print_preview.Destination} The currently selected destination or254 * {@code null} if none is selected.255 */256 get selectedDestination() {257 return this.selectedDestination_;258 },259 /** @return {boolean} Whether destination selection is pending or not. */260 get isAutoSelectDestinationInProgress() {261 return this.selectedDestination_ == null &&262 this.autoSelectTimeout_ != null;263 },264 /**265 * @return {boolean} Whether a search for local destinations is in progress.266 */267 get isLocalDestinationSearchInProgress() {268 return this.isLocalDestinationSearchInProgress_ ||269 this.isPrivetDestinationSearchInProgress_ ||270 this.isExtensionDestinationSearchInProgress_;271 },272 /**273 * @return {boolean} Whether a search for cloud destinations is in progress.274 */275 get isCloudDestinationSearchInProgress() {276 return !!this.cloudPrintInterface_ &&277 this.cloudPrintInterface_.isCloudDestinationSearchInProgress;278 },279 /**280 * Initializes the destination store. Sets the initially selected281 * destination. If any inserted destinations match this ID, that destination282 * will be automatically selected. This method must be called after the283 * print_preview.AppState has been initialized.284 * @param {boolean} isInAppKioskMode Whether the print preview is in App285 * Kiosk mode.286 */287 init: function(isInAppKioskMode) {288 this.pdfPrinterEnabled_ = !isInAppKioskMode;289 this.isInAutoSelectMode_ = true;290 this.createLocalPdfPrintDestination_();291 if (!this.appState_.selectedDestinationId ||292 !this.appState_.selectedDestinationOrigin) {293 this.selectDefaultDestination_();294 } else {295 var key = this.getDestinationKey_(296 this.appState_.selectedDestinationOrigin,297 this.appState_.selectedDestinationId,298 this.appState_.selectedDestinationAccount || '');299 var candidate = this.destinationMap_[key];300 if (candidate != null) {301 this.selectDestination(candidate);302 } else if (this.appState_.selectedDestinationOrigin ==303 print_preview.Destination.Origin.LOCAL) {304 this.nativeLayer_.startGetLocalDestinationCapabilities(305 this.appState_.selectedDestinationId);306 } else if (this.cloudPrintInterface_ &&307 (this.appState_.selectedDestinationOrigin ==308 print_preview.Destination.Origin.COOKIES ||309 this.appState_.selectedDestinationOrigin ==310 print_preview.Destination.Origin.DEVICE)) {311 this.cloudPrintInterface_.printer(312 this.appState_.selectedDestinationId,313 this.appState_.selectedDestinationOrigin,314 this.appState_.selectedDestinationAccount || '');315 } else if (this.appState_.selectedDestinationOrigin ==316 print_preview.Destination.Origin.PRIVET) {317 // TODO(noamsml): Resolve a specific printer instead of listing all318 // privet printers in this case.319 this.nativeLayer_.startGetPrivetDestinations();320 var destinationName = this.appState_.selectedDestinationName || '';321 // Create a fake selectedDestination_ that is not actually in the322 // destination store. When the real destination is created, this323 // destination will be overwritten.324 this.selectedDestination_ = new print_preview.Destination(325 this.appState_.selectedDestinationId,326 print_preview.Destination.Type.LOCAL,327 print_preview.Destination.Origin.PRIVET,328 destinationName,329 false /*isRecent*/,330 print_preview.Destination.ConnectionStatus.ONLINE);331 this.selectedDestination_.capabilities =332 this.appState_.selectedDestinationCapabilities;333 cr.dispatchSimpleEvent(334 this,335 DestinationStore.EventType.CACHED_SELECTED_DESTINATION_INFO_READY);336 } else if (this.appState_.selectedDestinationOrigin ==337 print_preview.Destination.Origin.EXTENSION) {338 // TODO(tbarzic): Add support for requesting a single extension's339 // printer list.340 this.startLoadExtensionDestinations();341 this.selectedDestination_ =342 print_preview.ExtensionDestinationParser.parse({343 extensionId: this.appState_.selectedDestinationExtensionId,344 extensionName: this.appState_.selectedDestinationExtensionName,345 id: this.appState_.selectedDestinationId,346 name: this.appState_.selectedDestinationName || ''347 });348 if (this.appState_.selectedDestinationCapabilities) {349 this.selectedDestination_.capabilities =350 this.appState_.selectedDestinationCapabilities;351 cr.dispatchSimpleEvent(352 this,353 DestinationStore.EventType354 .CACHED_SELECTED_DESTINATION_INFO_READY);355 }356 } else {357 this.selectDefaultDestination_();358 }359 }360 },361 /**362 * Sets the destination store's Google Cloud Print interface.363 * @param {!cloudprint.CloudPrintInterface} cloudPrintInterface Interface364 * to set.365 */366 setCloudPrintInterface: function(cloudPrintInterface) {367 this.cloudPrintInterface_ = cloudPrintInterface;368 this.tracker_.add(369 this.cloudPrintInterface_,370 cloudprint.CloudPrintInterface.EventType.SEARCH_DONE,371 this.onCloudPrintSearchDone_.bind(this));372 this.tracker_.add(373 this.cloudPrintInterface_,374 cloudprint.CloudPrintInterface.EventType.SEARCH_FAILED,375 this.onCloudPrintSearchDone_.bind(this));376 this.tracker_.add(377 this.cloudPrintInterface_,378 cloudprint.CloudPrintInterface.EventType.PRINTER_DONE,379 this.onCloudPrintPrinterDone_.bind(this));380 this.tracker_.add(381 this.cloudPrintInterface_,382 cloudprint.CloudPrintInterface.EventType.PRINTER_FAILED,383 this.onCloudPrintPrinterFailed_.bind(this));384 this.tracker_.add(385 this.cloudPrintInterface_,386 cloudprint.CloudPrintInterface.EventType.PROCESS_INVITE_DONE,387 this.onCloudPrintProcessInviteDone_.bind(this));388 },389 /**390 * @return {boolean} Whether only default cloud destinations have been391 * loaded.392 */393 hasOnlyDefaultCloudDestinations: function() {394 // TODO: Move the logic to print_preview.395 return this.destinations_.every(function(dest) {396 return dest.isLocal ||397 dest.id == print_preview.Destination.GooglePromotedId.DOCS ||398 dest.id == print_preview.Destination.GooglePromotedId.FEDEX;399 });400 },401 /**402 * @param {print_preview.Destination} destination Destination to select.403 */404 selectDestination: function(destination) {405 this.isInAutoSelectMode_ = false;406 // When auto select expires, DESTINATION_SELECT event has to be dispatched407 // anyway (see isAutoSelectDestinationInProgress() logic).408 if (this.autoSelectTimeout_) {409 clearTimeout(this.autoSelectTimeout_);410 this.autoSelectTimeout_ = null;411 } else if (destination == this.selectedDestination_) {412 return;413 }414 if (destination == null) {415 this.selectedDestination_ = null;416 cr.dispatchSimpleEvent(417 this, DestinationStore.EventType.DESTINATION_SELECT);418 return;419 }420 assert(!destination.isProvisional,421 'Unable to select provisonal destinations');422 // Update and persist selected destination.423 this.selectedDestination_ = destination;424 this.selectedDestination_.isRecent = true;425 if (destination.id == print_preview.Destination.GooglePromotedId.FEDEX &&426 !destination.isTosAccepted) {427 assert(this.cloudPrintInterface_ != null,428 'Selected FedEx destination, but GCP API is not available');429 destination.isTosAccepted = true;430 this.cloudPrintInterface_.updatePrinterTosAcceptance(destination, true);431 }432 this.appState_.persistSelectedDestination(this.selectedDestination_);433 // Adjust metrics.434 if (destination.cloudID &&435 this.destinations_.some(function(otherDestination) {436 return otherDestination.cloudID == destination.cloudID &&437 otherDestination != destination;438 })) {439 this.metrics_.record(destination.isPrivet ?440 print_preview.Metrics.DestinationSearchBucket.441 PRIVET_DUPLICATE_SELECTED :442 print_preview.Metrics.DestinationSearchBucket.443 CLOUD_DUPLICATE_SELECTED);444 }445 // Notify about selected destination change.446 cr.dispatchSimpleEvent(447 this, DestinationStore.EventType.DESTINATION_SELECT);448 // Request destination capabilities, of not known yet.449 if (destination.capabilities == null) {450 if (destination.isPrivet) {451 this.nativeLayer_.startGetPrivetDestinationCapabilities(452 destination.id);453 } else if (destination.isExtension) {454 this.nativeLayer_.startGetExtensionDestinationCapabilities(455 destination.id);456 } else if (destination.isLocal) {457 this.nativeLayer_.startGetLocalDestinationCapabilities(458 destination.id);459 } else {460 assert(this.cloudPrintInterface_ != null,461 'Cloud destination selected, but GCP is not enabled');462 this.cloudPrintInterface_.printer(463 destination.id, destination.origin, destination.account);464 }465 } else {466 cr.dispatchSimpleEvent(467 this,468 DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY);469 }470 },471 /**472 * Attempts to resolve a provisional destination.473 * @param {!print_preview.Destination} destinaion Provisional destination474 * that should be resolved.475 */476 resolveProvisionalDestination: function(destination) {477 assert(478 destination.provisionalType ==479 print_preview.Destination.ProvisionalType.NEEDS_USB_PERMISSION,480 'Provisional type cannot be resolved.');481 this.nativeLayer_.grantExtensionPrinterAccess(destination.id);482 },483 /**484 * Selects 'Save to PDF' destination (since it always exists).485 * @private486 */487 selectDefaultDestination_: function() {488 var saveToPdfKey = this.getDestinationKey_(489 print_preview.Destination.Origin.LOCAL,490 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,491 '');492 this.selectDestination(493 this.destinationMap_[saveToPdfKey] || this.destinations_[0] || null);494 },495 /** Initiates loading of local print destinations. */496 startLoadLocalDestinations: function() {497 if (!this.hasLoadedAllLocalDestinations_) {498 this.hasLoadedAllLocalDestinations_ = true;499 this.nativeLayer_.startGetLocalDestinations();500 this.isLocalDestinationSearchInProgress_ = true;501 cr.dispatchSimpleEvent(502 this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);503 }504 },505 /** Initiates loading of privet print destinations. */506 startLoadPrivetDestinations: function() {507 if (!this.hasLoadedAllPrivetDestinations_) {508 if (this.privetDestinationSearchInProgress_)509 clearTimeout(this.privetSearchTimeout_);510 this.isPrivetDestinationSearchInProgress_ = true;511 this.nativeLayer_.startGetPrivetDestinations();512 cr.dispatchSimpleEvent(513 this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);514 this.privetSearchTimeout_ = setTimeout(515 this.endPrivetPrinterSearch_.bind(this),516 DestinationStore.PRIVET_SEARCH_DURATION_);517 }518 },519 /** Initializes loading of extension managed print destinations. */520 startLoadExtensionDestinations: function() {521 if (this.hasLoadedAllExtensionDestinations_)522 return;523 if (this.isExtensionDestinationSearchInProgress_)524 clearTimeout(this.extensionSearchTimeout_);525 this.isExtensionDestinationSearchInProgress_ = true;526 this.nativeLayer_.startGetExtensionDestinations();527 cr.dispatchSimpleEvent(528 this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);529 this.extensionSearchTimeout_ = setTimeout(530 this.endExtensionPrinterSearch_.bind(this),531 DestinationStore.EXTENSION_SEARCH_DURATION_);532 },533 /**534 * Initiates loading of cloud destinations.535 * @param {print_preview.Destination.Origin=} opt_origin Search destinations536 * for the specified origin only.537 */538 startLoadCloudDestinations: function(opt_origin) {539 if (this.cloudPrintInterface_ != null) {540 var origins = this.loadedCloudOrigins_[this.userInfo_.activeUser] || [];541 if (origins.length == 0 ||542 (opt_origin && origins.indexOf(opt_origin) < 0)) {543 this.cloudPrintInterface_.search(544 this.userInfo_.activeUser, opt_origin);545 cr.dispatchSimpleEvent(546 this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);547 }548 }549 },550 /** Requests load of COOKIE based cloud destinations. */551 reloadUserCookieBasedDestinations: function() {552 var origins = this.loadedCloudOrigins_[this.userInfo_.activeUser] || [];553 if (origins.indexOf(print_preview.Destination.Origin.COOKIES) >= 0) {554 cr.dispatchSimpleEvent(555 this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);556 } else {557 this.startLoadCloudDestinations(558 print_preview.Destination.Origin.COOKIES);559 }560 },561 /** Initiates loading of all known destination types. */562 startLoadAllDestinations: function() {563 this.startLoadCloudDestinations();564 this.startLoadLocalDestinations();565 this.startLoadPrivetDestinations();566 this.startLoadExtensionDestinations();567 },568 /**569 * Wait for a privet device to be registered.570 */571 waitForRegister: function(id) {572 this.nativeLayer_.startGetPrivetDestinations();573 this.waitForRegisterDestination_ = id;574 },575 /**576 * Event handler for {@code577 * print_preview.NativeLayer.EventType.PROVISIONAL_DESTINATION_RESOLVED}.578 * Currently assumes the provisional destination is an extension579 * destination.580 * Called when a provisional destination resolvement attempt finishes.581 * The provisional destination is removed from the store and replaced with582 * a destination created from the resolved destination properties, if any583 * are reported.584 * Emits {@code DestinationStore.EventType.PROVISIONAL_DESTINATION_RESOLVED}585 * event.586 * @param {!Event} The event containing the provisional destination ID and587 * resolved destination description. If the destination was not588 * successfully resolved, the description will not be set.589 * @private590 */591 handleProvisionalDestinationResolved_: function(evt) {592 var provisionalDestinationIndex = -1;593 var provisionalDestination = null;594 for (var i = 0; i < this.destinations_.length; ++i) {595 if (evt.provisionalId == this.destinations_[i].id) {596 provisionalDestinationIndex = i;597 provisionalDestination = this.destinations_[i];598 break;599 }600 }601 if (!provisionalDestination)602 return;603 this.destinations_.splice(provisionalDestinationIndex, 1);604 delete this.destinationMap_[this.getKey_(provisionalDestination)];605 var destination = evt.destination ?606 print_preview.ExtensionDestinationParser.parse(evt.destination) :607 null;608 if (destination)609 this.insertIntoStore_(destination);610 var event = new Event(611 DestinationStore.EventType.PROVISIONAL_DESTINATION_RESOLVED);612 event.provisionalId = evt.provisionalId;613 event.destination = destination;614 this.dispatchEvent(event);615 },616 /**617 * Inserts {@code destination} to the data store and dispatches a618 * DESTINATIONS_INSERTED event.619 * @param {!print_preview.Destination} destination Print destination to620 * insert.621 * @private622 */623 insertDestination_: function(destination) {624 if (this.insertIntoStore_(destination)) {625 this.destinationsInserted_(destination);626 }627 },628 /**629 * Inserts multiple {@code destinations} to the data store and dispatches630 * single DESTINATIONS_INSERTED event.631 * @param {!Array<print_preview.Destination>} destinations Print632 * destinations to insert.633 * @private634 */635 insertDestinations_: function(destinations) {636 var inserted = false;637 destinations.forEach(function(destination) {638 inserted = this.insertIntoStore_(destination) || inserted;639 }, this);640 if (inserted) {641 this.destinationsInserted_();642 }643 },644 /**645 * Dispatches DESTINATIONS_INSERTED event. In auto select mode, tries to646 * update selected destination to match {@code appState_} settings.647 * @param {print_preview.Destination=} opt_destination The only destination648 * that was changed or skipped if possibly more than one destination was649 * changed. Used as a hint to limit destination search scope in650 * {@code isInAutoSelectMode_).651 */652 destinationsInserted_: function(opt_destination) {653 cr.dispatchSimpleEvent(654 this, DestinationStore.EventType.DESTINATIONS_INSERTED);655 if (this.isInAutoSelectMode_) {656 var destinationsToSearch =657 opt_destination && [opt_destination] || this.destinations_;658 destinationsToSearch.some(function(destination) {659 if (this.matchPersistedDestination_(destination)) {660 this.selectDestination(destination);661 return true;662 }663 }, this);664 }665 },666 /**667 * Updates an existing print destination with capabilities and display name668 * information. If the destination doesn't already exist, it will be added.669 * @param {!print_preview.Destination} destination Destination to update.670 * @return {!print_preview.Destination} The existing destination that was671 * updated or {@code null} if it was the new destination.672 * @private673 */674 updateDestination_: function(destination) {675 assert(destination.constructor !== Array, 'Single printer expected');676 var existingDestination = this.destinationMap_[this.getKey_(destination)];677 if (existingDestination != null) {678 existingDestination.capabilities = destination.capabilities;679 } else {680 this.insertDestination_(destination);681 }682 if (existingDestination == this.selectedDestination_ ||683 destination == this.selectedDestination_) {684 this.appState_.persistSelectedDestination(this.selectedDestination_);685 cr.dispatchSimpleEvent(686 this,687 DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY);688 }689 return existingDestination;690 },691 /**692 * Called when the search for Privet printers is done.693 * @private694 */695 endPrivetPrinterSearch_: function() {696 this.nativeLayer_.stopGetPrivetDestinations();697 this.isPrivetDestinationSearchInProgress_ = false;698 this.hasLoadedAllPrivetDestinations_ = true;699 cr.dispatchSimpleEvent(700 this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);701 },702 /**703 * Called when loading of extension managed printers is done.704 * @private705 */706 endExtensionPrinterSearch_: function() {707 this.isExtensionDestinationSearchInProgress_ = false;708 this.hasLoadedAllExtensionDestinations_ = true;709 cr.dispatchSimpleEvent(710 this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);711 // Clear initially selected (cached) extension destination if it hasn't712 // been found among reported extension destinations.713 if (this.isInAutoSelectMode_ && this.selectedDestination_.isExtension)714 this.selectDefaultDestination_();715 },716 /**717 * Inserts a destination into the store without dispatching any events.718 * @return {boolean} Whether the inserted destination was not already in the719 * store.720 * @private721 */722 insertIntoStore_: function(destination) {723 var key = this.getKey_(destination);724 var existingDestination = this.destinationMap_[key];725 if (existingDestination == null) {726 this.destinations_.push(destination);727 this.destinationMap_[key] = destination;728 return true;729 } else if (existingDestination.connectionStatus ==730 print_preview.Destination.ConnectionStatus.UNKNOWN &&731 destination.connectionStatus !=732 print_preview.Destination.ConnectionStatus.UNKNOWN) {733 existingDestination.connectionStatus = destination.connectionStatus;734 return true;735 } else {736 return false;737 }738 },739 /**740 * Binds handlers to events.741 * @private742 */743 addEventListeners_: function() {744 this.tracker_.add(745 this.nativeLayer_,746 print_preview.NativeLayer.EventType.LOCAL_DESTINATIONS_SET,747 this.onLocalDestinationsSet_.bind(this));748 this.tracker_.add(749 this.nativeLayer_,750 print_preview.NativeLayer.EventType.CAPABILITIES_SET,751 this.onLocalDestinationCapabilitiesSet_.bind(this));752 this.tracker_.add(753 this.nativeLayer_,754 print_preview.NativeLayer.EventType.GET_CAPABILITIES_FAIL,755 this.onGetCapabilitiesFail_.bind(this));756 this.tracker_.add(757 this.nativeLayer_,758 print_preview.NativeLayer.EventType.DESTINATIONS_RELOAD,759 this.onDestinationsReload_.bind(this));760 this.tracker_.add(761 this.nativeLayer_,762 print_preview.NativeLayer.EventType.PRIVET_PRINTER_CHANGED,763 this.onPrivetPrinterAdded_.bind(this));764 this.tracker_.add(765 this.nativeLayer_,766 print_preview.NativeLayer.EventType.PRIVET_CAPABILITIES_SET,767 this.onPrivetCapabilitiesSet_.bind(this));768 this.tracker_.add(769 this.nativeLayer_,770 print_preview.NativeLayer.EventType.EXTENSION_PRINTERS_ADDED,771 this.onExtensionPrintersAdded_.bind(this));772 this.tracker_.add(773 this.nativeLayer_,774 print_preview.NativeLayer.EventType.EXTENSION_CAPABILITIES_SET,775 this.onExtensionCapabilitiesSet_.bind(this));776 this.tracker_.add(777 this.nativeLayer_,778 print_preview.NativeLayer.EventType.PROVISIONAL_DESTINATION_RESOLVED,779 this.handleProvisionalDestinationResolved_.bind(this));780 },781 /**782 * Creates a local PDF print destination.783 * @return {!print_preview.Destination} Created print destination.784 * @private785 */786 createLocalPdfPrintDestination_: function() {787 // TODO(alekseys): Create PDF printer in the native code and send its788 // capabilities back with other local printers.789 if (this.pdfPrinterEnabled_) {790 this.insertDestination_(new print_preview.Destination(791 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,792 print_preview.Destination.Type.LOCAL,793 print_preview.Destination.Origin.LOCAL,794 loadTimeData.getString('printToPDF'),795 false /*isRecent*/,796 print_preview.Destination.ConnectionStatus.ONLINE));797 }798 },799 /**800 * Resets the state of the destination store to its initial state.801 * @private802 */803 reset_: function() {804 this.destinations_ = [];805 this.destinationMap_ = {};806 this.selectDestination(null);807 this.loadedCloudOrigins_ = {};808 this.hasLoadedAllLocalDestinations_ = false;809 this.hasLoadedAllPrivetDestinations_ = false;810 this.hasLoadedAllExtensionDestinations_ = false;811 clearTimeout(this.autoSelectTimeout_);812 this.autoSelectTimeout_ = setTimeout(813 this.selectDefaultDestination_.bind(this),814 DestinationStore.AUTO_SELECT_TIMEOUT_);815 },816 /**817 * Called when the local destinations have been got from the native layer.818 * @param {Event} event Contains the local destinations.819 * @private820 */821 onLocalDestinationsSet_: function(event) {822 var localDestinations = event.destinationInfos.map(function(destInfo) {823 return print_preview.LocalDestinationParser.parse(destInfo);824 });825 this.insertDestinations_(localDestinations);826 this.isLocalDestinationSearchInProgress_ = false;827 cr.dispatchSimpleEvent(828 this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);829 },830 /**831 * Called when the native layer retrieves the capabilities for the selected832 * local destination. Updates the destination with new capabilities if the833 * destination already exists, otherwise it creates a new destination and834 * then updates its capabilities.835 * @param {Event} event Contains the capabilities of the local print836 * destination.837 * @private838 */839 onLocalDestinationCapabilitiesSet_: function(event) {840 var destinationId = event.settingsInfo['printerId'];841 var key = this.getDestinationKey_(842 print_preview.Destination.Origin.LOCAL,843 destinationId,844 '');845 var destination = this.destinationMap_[key];846 var capabilities = DestinationStore.localizeCapabilities_(847 event.settingsInfo.capabilities);848 // Special case for PDF printer (until local printers capabilities are849 // reported in CDD format too).850 if (destinationId ==851 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {852 if (destination) {853 destination.capabilities = capabilities;854 }855 } else {856 if (destination) {857 // In case there were multiple capabilities request for this local858 // destination, just ignore the later ones.859 if (destination.capabilities != null) {860 return;861 }862 destination.capabilities = capabilities;863 } else {864 // TODO(rltoscano): This makes the assumption that the "deviceName" is865 // the same as "printerName". We should include the "printerName" in866 // the response. See http://crbug.com/132831.867 destination = print_preview.LocalDestinationParser.parse(868 {deviceName: destinationId, printerName: destinationId});869 destination.capabilities = capabilities;870 this.insertDestination_(destination);871 }872 }873 if (this.selectedDestination_ &&874 this.selectedDestination_.id == destinationId) {875 cr.dispatchSimpleEvent(this,876 DestinationStore.EventType.877 SELECTED_DESTINATION_CAPABILITIES_READY);878 }879 },880 /**881 * Called when a request to get a local destination's print capabilities882 * fails. If the destination is the initial destination, auto-select another883 * destination instead.884 * @param {Event} event Contains the destination ID that failed.885 * @private886 */887 onGetCapabilitiesFail_: function(event) {888 console.error('Failed to get print capabilities for printer ' +889 event.destinationId);890 if (this.isInAutoSelectMode_ &&891 this.sameAsPersistedDestination_(event.destinationId,892 event.destinationOrigin)) {893 this.selectDefaultDestination_();894 }895 },896 /**897 * Called when the /search call completes, either successfully or not.898 * In case of success, stores fetched destinations.899 * @param {Event} event Contains the request result.900 * @private901 */902 onCloudPrintSearchDone_: function(event) {903 if (event.printers) {904 this.insertDestinations_(event.printers);905 }906 if (event.searchDone) {907 var origins = this.loadedCloudOrigins_[event.user] || [];908 if (origins.indexOf(event.origin) < 0) {909 this.loadedCloudOrigins_[event.user] = origins.concat([event.origin]);910 }911 }912 cr.dispatchSimpleEvent(913 this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);914 },915 /**916 * Called when /printer call completes. Updates the specified destination's917 * print capabilities.918 * @param {Event} event Contains detailed information about the919 * destination.920 * @private921 */922 onCloudPrintPrinterDone_: function(event) {923 this.updateDestination_(event.printer);924 },925 /**926 * Called when the Google Cloud Print interface fails to lookup a927 * destination. Selects another destination if the failed destination was928 * the initial destination.929 * @param {Object} event Contains the ID of the destination that was failed930 * to be looked up.931 * @private932 */933 onCloudPrintPrinterFailed_: function(event) {934 if (this.isInAutoSelectMode_ &&935 this.sameAsPersistedDestination_(event.destinationId,936 event.destinationOrigin)) {937 console.error(938 'Failed to fetch last used printer caps: ' + event.destinationId);939 this.selectDefaultDestination_();940 }941 },942 /**943 * Called when printer sharing invitation was processed successfully.944 * @param {Event} event Contains detailed information about the invite and945 * newly accepted destination (if known).946 * @private947 */948 onCloudPrintProcessInviteDone_: function(event) {949 if (event.accept && event.printer) {950 // Hint the destination list to promote this new destination.951 event.printer.isRecent = true;952 this.insertDestination_(event.printer);953 }954 },955 /**956 * Called when a Privet printer is added to the local network.957 * @param {Object} event Contains information about the added printer.958 * @private959 */960 onPrivetPrinterAdded_: function(event) {961 if (event.printer.serviceName == this.waitForRegisterDestination_ &&962 !event.printer.isUnregistered) {963 this.waitForRegisterDestination_ = null;964 this.onDestinationsReload_();965 } else {966 this.insertDestinations_(967 print_preview.PrivetDestinationParser.parse(event.printer));968 }969 },970 /**971 * Called when capabilities for a privet printer are set.972 * @param {Object} event Contains the capabilities and printer ID.973 * @private974 */975 onPrivetCapabilitiesSet_: function(event) {976 var destinations =977 print_preview.PrivetDestinationParser.parse(event.printer);978 destinations.forEach(function(dest) {979 dest.capabilities = event.capabilities;980 this.updateDestination_(dest);981 }, this);982 },983 /**984 * Called when an extension responds to a getExtensionDestinations985 * request.986 * @param {Object} event Contains information about list of printers987 * reported by the extension.988 * {@code done} parameter is set iff this is the final list of printers989 * returned as part of getExtensionDestinations request.990 * @private991 */992 onExtensionPrintersAdded_: function(event) {993 this.insertDestinations_(event.printers.map(function(printer) {994 return print_preview.ExtensionDestinationParser.parse(printer);995 }));996 if (event.done && this.isExtensionDestinationSearchInProgress_) {997 clearTimeout(this.extensionSearchTimeout_);998 this.endExtensionPrinterSearch_();999 }1000 },1001 /**1002 * Called when capabilities for an extension managed printer are set.1003 * @param {Object} event Contains the printer's capabilities and ID.1004 * @private1005 */1006 onExtensionCapabilitiesSet_: function(event) {1007 var destinationKey = this.getDestinationKey_(1008 print_preview.Destination.Origin.EXTENSION,1009 event.printerId,1010 '' /* account */);1011 var destination = this.destinationMap_[destinationKey];1012 if (!destination)1013 return;1014 destination.capabilities = event.capabilities;1015 this.updateDestination_(destination);1016 },1017 /**1018 * Called from native layer after the user was requested to sign in, and did1019 * so successfully.1020 * @private1021 */1022 onDestinationsReload_: function() {1023 this.reset_();1024 this.isInAutoSelectMode_ = true;1025 this.createLocalPdfPrintDestination_();1026 this.startLoadAllDestinations();1027 },1028 // TODO(vitalybuka): Remove three next functions replacing Destination.id1029 // and Destination.origin by complex ID.1030 /**1031 * Returns key to be used with {@code destinationMap_}.1032 * @param {!print_preview.Destination.Origin} origin Destination origin.1033 * @param {string} id Destination id.1034 * @param {string} account User account destination is registered for.1035 * @private1036 */1037 getDestinationKey_: function(origin, id, account) {1038 return origin + '/' + id + '/' + account;1039 },1040 /**1041 * Returns key to be used with {@code destinationMap_}.1042 * @param {!print_preview.Destination} destination Destination.1043 * @private1044 */1045 getKey_: function(destination) {1046 return this.getDestinationKey_(1047 destination.origin, destination.id, destination.account);1048 },1049 /**1050 * @param {!print_preview.Destination} destination Destination to match.1051 * @return {boolean} Whether {@code destination} matches the last user1052 * selected one.1053 * @private1054 */1055 matchPersistedDestination_: function(destination) {1056 return !this.appState_.selectedDestinationId ||1057 !this.appState_.selectedDestinationOrigin ||1058 this.sameAsPersistedDestination_(1059 destination.id, destination.origin);1060 },1061 /**1062 * @param {?string} id Id of the destination.1063 * @param {?string} origin Oring of the destination.1064 * @return {boolean} Whether destination is the same as initial.1065 * @private1066 */1067 sameAsPersistedDestination_: function(id, origin) {1068 return id == this.appState_.selectedDestinationId &&1069 origin == this.appState_.selectedDestinationOrigin;1070 }1071 };1072 // Export1073 return {1074 DestinationStore: DestinationStore1075 };...

Full Screen

Full Screen

destination_settings.js

Source:destination_settings.js Github

copy

Full Screen

1// Copyright (c) 2012 The Chromium Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4cr.define('print_preview', function() {5 'use strict';6 // TODO(rltoscano): This class needs a throbber while loading the destination7 // or another solution is persist the settings of the printer so that next8 // load is fast.9 /**10 * Component used to render the print destination.11 * @param {!print_preview.DestinationStore} destinationStore Used to determine12 * the selected destination.13 * @constructor14 * @extends {print_preview.SettingsSection}15 */16 function DestinationSettings(destinationStore) {17 print_preview.SettingsSection.call(this);18 /**19 * Used to determine the selected destination.20 * @type {!print_preview.DestinationStore}21 * @private22 */23 this.destinationStore_ = destinationStore;24 /**25 * Current CSS class of the destination icon.26 * @type {?DestinationSettings.Classes_}27 * @private28 */29 this.iconClass_ = null;30 };31 /**32 * Event types dispatched by the component.33 * @enum {string}34 */35 DestinationSettings.EventType = {36 CHANGE_BUTTON_ACTIVATE:37 'print_preview.DestinationSettings.CHANGE_BUTTON_ACTIVATE'38 };39 /**40 * CSS classes used by the component.41 * @enum {string}42 * @private43 */44 DestinationSettings.Classes_ = {45 CHANGE_BUTTON: 'destination-settings-change-button',46 ICON: 'destination-settings-icon',47 ICON_CLOUD: 'destination-settings-icon-cloud',48 ICON_CLOUD_SHARED: 'destination-settings-icon-cloud-shared',49 ICON_GOOGLE_PROMOTED: 'destination-settings-icon-google-promoted',50 ICON_LOCAL: 'destination-settings-icon-local',51 ICON_MOBILE: 'destination-settings-icon-mobile',52 ICON_MOBILE_SHARED: 'destination-settings-icon-mobile-shared',53 LOCATION: 'destination-settings-location',54 NAME: 'destination-settings-name',55 STALE: 'stale',56 THOBBER_NAME: 'destination-throbber-name'57 };58 DestinationSettings.prototype = {59 __proto__: print_preview.SettingsSection.prototype,60 /** @override */61 isAvailable: function() {62 return true;63 },64 /** @override */65 hasCollapsibleContent: function() {66 return false;67 },68 /** @override */69 set isEnabled(isEnabled) {70 var changeButton = this.getElement().getElementsByClassName(71 DestinationSettings.Classes_.CHANGE_BUTTON)[0];72 changeButton.disabled = !isEnabled;73 },74 /** @override */75 enterDocument: function() {76 print_preview.SettingsSection.prototype.enterDocument.call(this);77 var changeButton = this.getElement().getElementsByClassName(78 DestinationSettings.Classes_.CHANGE_BUTTON)[0];79 this.tracker.add(80 changeButton, 'click', this.onChangeButtonClick_.bind(this));81 this.tracker.add(82 this.destinationStore_,83 print_preview.DestinationStore.EventType.DESTINATION_SELECT,84 this.onDestinationSelect_.bind(this));85 this.tracker_.add(86 this.destinationStore_,87 print_preview.DestinationStore.EventType.88 CACHED_SELECTED_DESTINATION_INFO_READY,89 this.onSelectedDestinationNameSet_.bind(this));90 },91 /**92 * Called when the "Change" button is clicked. Dispatches the93 * CHANGE_BUTTON_ACTIVATE event.94 * @private95 */96 onChangeButtonClick_: function() {97 cr.dispatchSimpleEvent(98 this, DestinationSettings.EventType.CHANGE_BUTTON_ACTIVATE);99 },100 /**101 * Called when the destination selection has changed. Updates UI elements.102 * @private103 */104 onDestinationSelect_: function() {105 var destinationSettingsBoxEl =106 this.getChildElement('.destination-settings-box');107 var destination = this.destinationStore_.selectedDestination;108 if (destination != null) {109 var nameEl = this.getElement().getElementsByClassName(110 DestinationSettings.Classes_.NAME)[0];111 nameEl.textContent = destination.displayName;112 nameEl.title = destination.displayName;113 var iconEl = this.getElement().getElementsByClassName(114 DestinationSettings.Classes_.ICON)[0];115 iconEl.src = destination.iconUrl;116 var hint = destination.hint;117 var locationEl = this.getElement().getElementsByClassName(118 DestinationSettings.Classes_.LOCATION)[0];119 locationEl.textContent = hint;120 locationEl.title = hint;121 var offlineStatusText = destination.offlineStatusText;122 var offlineStatusEl =123 this.getChildElement('.destination-settings-offline-status');124 offlineStatusEl.textContent = offlineStatusText;125 offlineStatusEl.title = offlineStatusText;126 var isOffline = destination.isOffline;127 destinationSettingsBoxEl.classList.toggle(128 DestinationSettings.Classes_.STALE, isOffline);129 setIsVisible(locationEl, !isOffline);130 setIsVisible(offlineStatusEl, isOffline);131 }132 setIsVisible(133 this.getChildElement('.throbber-container'),134 this.destinationStore_.isAutoSelectDestinationInProgress);135 setIsVisible(destinationSettingsBoxEl, !!destination);136 },137 onSelectedDestinationNameSet_: function() {138 var destinationName =139 this.destinationStore_.selectedDestination.displayName;140 var nameEl = this.getElement().getElementsByClassName(141 DestinationSettings.Classes_.THOBBER_NAME)[0];142 nameEl.textContent = destinationName;143 nameEl.title = destinationName;144 }145 };146 // Export147 return {148 DestinationSettings: DestinationSettings149 };...

Full Screen

Full Screen

local_parsers.js

Source:local_parsers.js Github

copy

Full Screen

1// Copyright (c) 2012 The Chromium Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4cr.define('print_preview', function() {5 'use strict';6 /** Namespace that contains a method to parse local print destinations. */7 function LocalDestinationParser() {};8 /**9 * Parses a local print destination.10 * @param {!Object} destinationInfo Information describing a local print11 * destination.12 * @return {!print_preview.Destination} Parsed local print destination.13 */14 LocalDestinationParser.parse = function(destinationInfo) {15 var options = {'description': destinationInfo.printerDescription};16 if (destinationInfo.printerOptions) {17 // Convert options into cloud print tags format.18 options.tags = Object.keys(destinationInfo.printerOptions).map(19 function(key) {return '__cp__' + key + '=' + this[key];},20 destinationInfo.printerOptions);21 }22 return new print_preview.Destination(23 destinationInfo.deviceName,24 print_preview.Destination.Type.LOCAL,25 print_preview.Destination.Origin.LOCAL,26 destinationInfo.printerName,27 false /*isRecent*/,28 print_preview.Destination.ConnectionStatus.ONLINE,29 options);30 };31 function PrivetDestinationParser() {}32 /**33 * Parses a privet destination as one or more local printers.34 * @param {!Object} destinationInfo Object that describes a privet printer.35 * @return {!Array<!print_preview.Destination>} Parsed destination info.36 */37 PrivetDestinationParser.parse = function(destinationInfo) {38 var returnedPrinters = [];39 if (destinationInfo.hasLocalPrinting) {40 returnedPrinters.push(new print_preview.Destination(41 destinationInfo.serviceName,42 print_preview.Destination.Type.LOCAL,43 print_preview.Destination.Origin.PRIVET,44 destinationInfo.name,45 false /*isRecent*/,46 print_preview.Destination.ConnectionStatus.ONLINE,47 { cloudID: destinationInfo.cloudID }));48 }49 if (destinationInfo.isUnregistered) {50 returnedPrinters.push(new print_preview.Destination(51 destinationInfo.serviceName,52 print_preview.Destination.Type.GOOGLE,53 print_preview.Destination.Origin.PRIVET,54 destinationInfo.name,55 false /*isRecent*/,56 print_preview.Destination.ConnectionStatus.UNREGISTERED));57 }58 return returnedPrinters;59 };60 function ExtensionDestinationParser() {}61 /**62 * Parses an extension destination from an extension supplied printer63 * description.64 * @param {!Object} destinationInfo Object describing an extension printer.65 * @return {!print_preview.Destination} Parsed destination.66 */67 ExtensionDestinationParser.parse = function(destinationInfo) {68 var provisionalType =69 destinationInfo.provisional ?70 print_preview.Destination.ProvisionalType.NEEDS_USB_PERMISSION :71 print_preview.Destination.ProvisionalType.NONE;72 return new print_preview.Destination(73 destinationInfo.id,74 print_preview.Destination.Type.LOCAL,75 print_preview.Destination.Origin.EXTENSION,76 destinationInfo.name,77 false /* isRecent */,78 print_preview.Destination.ConnectionStatus.ONLINE,79 {description: destinationInfo.description || '',80 extensionId: destinationInfo.extensionId,81 extensionName: destinationInfo.extensionName || '',82 provisionalType: provisionalType});83 };84 // Export85 return {86 LocalDestinationParser: LocalDestinationParser,87 PrivetDestinationParser: PrivetDestinationParser,88 ExtensionDestinationParser: ExtensionDestinationParser89 };...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('webpagetest');2var wptKey = 'A.3e0c7a0b6d5c7e8e2b1c6f2d2c1c6b8a';3var wpt = new wpt(wptServer, wptKey);4var options = {5};6wpt.runTest(url, options, function(err, data) {7 if (err) return console.error(err);8 console.log('Test started: %s', data.data.testId);9 wpt.getTestStatus(data.data.testId, function(err, data) {10 if (err) return console.error(err);11 console.log('Test status: %s', data.data.statusText);12 if (data.data.statusText == 'Test Complete') {13 wpt.getTestResults(data.data.testId, function(err, data) {14 if (err) return console.error(err);15 console.log('Test results: %j', data);16 });17 }18 });19});

Full Screen

Using AI Code Generation

copy

Full Screen

1var WebPageTest = require('webpagetest');2var wpt = new WebPageTest('www.webpagetest.org', 'A.9a9f3d3f3d3d3d3d3d3d3d3d3d3d3d3d');3wpt.getTesters(function(err, data) {4 if (err)5 console.log(err);6 console.log(data);7});8wpt.runTest(url, { location: 'Dulles_MotoG4:Chrome', connectivity: '3G' }, function(err, data) {9 if (err)10 console.log(err);11 console.log(data);12});

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('webpagetest');2var options = {3};4var WebPageTest = new wpt('www.webpagetest.org', options.key);5}, function (err, data) {6 if (err) {7 console.log(err)8 } else {9 console.log(data);10 }11});12var wpt = require('webpagetest');13var options = {14};15var WebPageTest = new wpt('www.webpagetest.org', options.key);16}, function (err, data) {17 if (err) {18 console.log(err)19 } else {20 console.log(data);21 }22});

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