Best JavaScript code snippet using playwright-internal
cpu-grid-layer.spec.js
Source:cpu-grid-layer.spec.js
1// Copyright (c) 2015 - 2017 Uber Technologies, Inc.2//3// Permission is hereby granted, free of charge, to any person obtaining a copy4// of this software and associated documentation files (the "Software"), to deal5// in the Software without restriction, including without limitation the rights6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell7// copies of the Software, and to permit persons to whom the Software is8// furnished to do so, subject to the following conditions:9//10// The above copyright notice and this permission notice shall be included in11// all copies or substantial portions of the Software.12//13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN19// THE SOFTWARE.20import test from 'tape-catch';21import {makeSpy} from '@probe.gl/test-utils';22import * as FIXTURES from 'deck.gl-test/data';23import {testLayer, testInitializeLayer, generateLayerTests} from '@deck.gl/test-utils';24import {GridCellLayer} from '@deck.gl/layers';25import {CPUGridLayer} from '@deck.gl/aggregation-layers';26test('CPUGridLayer', t => {27 const testCases = generateLayerTests({28 Layer: CPUGridLayer,29 sampleProps: {30 data: FIXTURES.points.slice(0, 3),31 getPosition: d => d.COORDINATES32 },33 assert: t.ok,34 onBeforeUpdate: ({testCase}) => t.comment(testCase.title),35 onAfterUpdate({layer}) {36 if (layer.props.data && layer.props.data.length) {37 t.ok(38 layer.state.aggregatorState.layerData.data.length > 0,39 'should update state.layerData'40 );41 }42 }43 });44 testLayer({Layer: CPUGridLayer, testCases, onError: t.notOk});45 t.end();46});47test('CPUGridLayer#renderSubLayer', t => {48 makeSpy(CPUGridLayer.prototype, '_onGetSublayerColor');49 makeSpy(CPUGridLayer.prototype, '_onGetSublayerElevation');50 const layer = new CPUGridLayer({51 data: FIXTURES.points,52 cellSize: 500,53 getPosition: d => d.COORDINATES,54 pickable: true55 });56 testInitializeLayer({layer, onError: t.notOk});57 // render sublayer58 const subLayer = layer.renderLayers();59 testInitializeLayer({layer: subLayer, onError: t.notOk});60 t.ok(subLayer instanceof GridCellLayer, 'GridCellLayer rendered');61 // should call attribute updater twice62 // because test util calls both initialize and update layer63 t.ok(CPUGridLayer.prototype._onGetSublayerColor.called, 'should call _onGetSublayerColor');64 t.ok(65 CPUGridLayer.prototype._onGetSublayerElevation.called,66 'should call _onGetSublayerElevation'67 );68 CPUGridLayer.prototype._onGetSublayerColor.restore();69 CPUGridLayer.prototype._onGetSublayerElevation.restore();70 t.end();71});72test('CPUGridLayer#updates', t => {73 // assert on state property updates after layer.prop change74 function assertStateUpdate(shouldUpdate, prop) {75 return function onAfterUpdate({layer, oldState: oldLayerState}) {76 function checkIfUpdated(state, oldState, shouldUpdateItem, previousKeys) {77 if (typeof shouldUpdateItem === 'object') {78 for (const key in shouldUpdateItem) {79 checkIfUpdated(80 state[key],81 oldState[key],82 shouldUpdateItem[key],83 `${previousKeys}.${key}`84 );85 }86 } else {87 t.ok(88 shouldUpdateItem ? state !== oldState : state === oldState,89 `update props.${prop} should ${!shouldUpdateItem ? 'not' : ''} update ${previousKeys}`90 );91 }92 }93 checkIfUpdated(94 layer.state.aggregatorState,95 oldLayerState.aggregatorState,96 shouldUpdate,97 'aggregatorState'98 );99 };100 }101 function getChecksForCellSizeChange() {102 const shouldUpdate = {103 layerData: true,104 dimensions: {105 fillColor: {106 sortedBins: true,107 valueDomain: true,108 getValue: false,109 scaleFunc: true110 },111 elevation: {112 sortedBins: true,113 valueDomain: true,114 getValue: false,115 scaleFunc: true116 }117 }118 };119 return assertStateUpdate(shouldUpdate, 'cellSize');120 }121 function getChecksForFilterChange(triggered) {122 const shouldUpdate = {123 layerData: false,124 dimensions: {125 fillColor: {126 sortedBins: triggered,127 valueDomain: triggered,128 getValue: triggered,129 scaleFunc: triggered130 },131 elevation: {132 sortedBins: triggered,133 valueDomain: triggered,134 getValue: triggered,135 scaleFunc: triggered136 }137 }138 };139 return assertStateUpdate(shouldUpdate, '_filterData');140 }141 function getChecksForPositionChange(triggerChange) {142 const shouldUpdate = {143 layerData: triggerChange,144 dimensions: {145 fillColor: {146 sortedBins: triggerChange,147 valueDomain: triggerChange,148 getValue: false,149 scaleFunc: triggerChange150 },151 elevation: {152 sortedBins: triggerChange,153 valueDomain: triggerChange,154 getValue: false,155 scaleFunc: triggerChange156 }157 }158 };159 return assertStateUpdate(160 shouldUpdate,161 `getPosition ${triggerChange ? 'w/' : 'w/o'} trigger change`162 );163 }164 function getCheckForNoBinChange(accessor, dimension) {165 const update = dimension;166 const noUpdate = ['fillColor', 'elevation'].find(k => k !== dimension);167 const shouldUpdate = {168 layerData: false,169 dimensions: {170 [update]: {171 sortedBins: false,172 valueDomain: false,173 getValue:174 accessor === 'getColorValue w/o trigger' ||175 accessor === 'getElevationValue w/o trigger',176 scaleFunc: false177 },178 [noUpdate]: {179 sortedBins: false,180 valueDomain: false,181 getValue: false,182 scaleFunc: false183 }184 }185 };186 return assertStateUpdate(shouldUpdate, accessor);187 }188 function getCheckForTriggeredBinUpdate(accessor, dimension) {189 const update = dimension;190 const noUpdate = ['fillColor', 'elevation'].find(k => k !== dimension);191 const shouldUpdate = {192 layerData: false,193 dimensions: {194 [update]: {195 sortedBins: true,196 valueDomain: true,197 getValue: true,198 scaleFunc: true199 },200 [noUpdate]: {201 sortedBins: false,202 valueDomain: false,203 getValue: false,204 scaleFunc: false205 }206 }207 };208 return assertStateUpdate(shouldUpdate, accessor);209 }210 function getChecksForPercentileUpdate(side, dimension) {211 const update = dimension;212 const noUpdate = ['fillColor', 'elevation'].find(k => k !== dimension);213 const shouldUpdate = {214 layerData: false,215 dimensions: {216 [update]: {217 sortedBins: false,218 valueDomain: true,219 getValue: false,220 scaleFunc: true221 },222 [noUpdate]: {223 sortedBins: false,224 valueDomain: false,225 getValue: false,226 scaleFunc: false227 }228 }229 };230 return assertStateUpdate(shouldUpdate, `${side}Percentile`);231 }232 function getChecksForDomainOrRangeUpdate(prop, dimension) {233 const update = dimension;234 const noUpdate = ['fillColor', 'elevation'].find(k => k !== dimension);235 const shouldUpdate = {236 layerData: false,237 dimensions: {238 [update]: {239 sortedBins: false,240 valueDomain: false,241 getValue: false,242 scaleFunc: true243 },244 [noUpdate]: {245 sortedBins: false,246 valueDomain: false,247 getValue: false,248 scaleFunc: false249 }250 }251 };252 return assertStateUpdate(shouldUpdate, `${dimension}${prop}`);253 }254 function getChecksForColorScaleTypeQuantize(scaleType) {255 const shouldUpdate = {256 dimensions: {257 colorScaleType: 'quantize'258 }259 };260 t.ok(261 shouldUpdate.dimensions.colorScaleType === scaleType,262 `update aggregatorState.dimension.colorScaleType to ${scaleType}`263 );264 }265 function getChecksForColorScaleTypeLinear(scaleType) {266 const shouldUpdate = {267 dimensions: {268 colorScaleType: 'linear'269 }270 };271 t.ok(272 shouldUpdate.dimensions.colorScaleType === scaleType,273 `update aggregatorState.dimension.colorScaleType to ${scaleType}`274 );275 }276 function getChecksForColorScaleTypeQuantile(scaleType) {277 const shouldUpdate = {278 dimensions: {279 colorScaleType: 'quantile'280 }281 };282 t.ok(283 shouldUpdate.dimensions.colorScaleType === scaleType,284 `update aggregatorState.dimension.colorScaleType to ${scaleType}`285 );286 }287 function getChecksForColorScaleTypeOrdinal(scaleType) {288 const shouldUpdate = {289 dimensions: {290 colorScaleType: 'ordinal'291 }292 };293 return t.ok(294 shouldUpdate.dimensions.colorScaleType === scaleType,295 `update aggregatorState.dimension.colorScaleType to ${scaleType}`296 );297 }298 testLayer({299 Layer: CPUGridLayer,300 onError: t.notOk,301 testCases: [302 {303 props: {304 data: FIXTURES.points,305 cellSize: 400,306 getPosition: d => d.COORDINATES,307 pickable: true308 },309 onAfterUpdate({layer}) {310 const {311 layerData,312 dimensions: {fillColor, elevation}313 } = layer.state.aggregatorState;314 t.ok(layerData.data.length > 0, 'aggregatorState.dimensions.layerDate calculated');315 t.ok(316 fillColor.sortedBins,317 'aggregatorState.dimensions.fillColor.sortedColorBins calculated'318 );319 t.ok(320 elevation.sortedBins,321 'aggregatorState.dimensions.elevation.sortedColorBins calculated'322 );323 t.ok(324 Array.isArray(fillColor.valueDomain),325 'aggregatorState.dimensions.fillColor.valueDomain calculated'326 );327 t.ok(328 Array.isArray(elevation.valueDomain),329 'aggregatorState.dimensions.elevation.valueDomain calculated'330 );331 t.ok(332 typeof fillColor.getValue === 'function',333 'aggregatorState.dimensions.fillColor.getValue calculated'334 );335 t.ok(336 typeof elevation.getValue === 'function',337 'aggregatorState.dimension.elevation.getValue calculated'338 );339 t.ok(340 Array.isArray(fillColor.sortedBins.aggregatedBins),341 'aggregatorState.dimension.fillColor.sortedBins.aggregatedBins calculated'342 );343 t.ok(344 Array.isArray(elevation.sortedBins.aggregatedBins),345 'aggregatorState.dimension.elevation.sortedBins.aggregatedBins calculated'346 );347 const firstSortedBin = fillColor.sortedBins.sortedBins[0];348 const binToCell = layerData.data.find(d => d.index === firstSortedBin.i);349 t.ok(350 fillColor.sortedBins.binMap[binToCell.index] === firstSortedBin,351 'Correct aggregatorState.dimension.fillColor.sortedBins.binMap created'352 );353 }354 },355 {356 updateProps: {357 _filterData: pt => pt.SPACES >= 4 && pt.SPACES <= 10358 },359 onAfterUpdate: ({layer, oldState}) => {360 getChecksForFilterChange(false)({layer, oldState});361 const {layerData} = layer.state.aggregatorState;362 const isPointFiltered = layerData.data.every(bin => bin.filteredPoints === null);363 t.ok(isPointFiltered, 'filteredPoints in bins should be reset to null');364 }365 },366 {367 updateProps: {368 _filterData: pt => pt.SPACES >= 4 && pt.SPACES <= 10,369 updateTriggers: {370 _filterData: 1371 }372 },373 onAfterUpdate: ({layer, oldState}) => {374 getChecksForFilterChange(true)({layer, oldState});375 const {376 layerData,377 dimensions: {fillColor, elevation}378 } = layer.state.aggregatorState;379 const isPointFiltered = layerData.data.every(bin =>380 bin.filteredPoints.every(pt => pt.SPACES >= 4 && pt.SPACES <= 10)381 );382 t.ok(isPointFiltered, 'filteredPoints in bins should be correct');383 t.ok(384 fillColor.sortedBins,385 'aggregatorState.dimensions.fillColor.sortedColorBins calculated'386 );387 t.ok(388 elevation.sortedBins,389 'aggregatorState.dimensions.elevation.sortedColorBins calculated'390 );391 }392 },393 {394 updateProps: {395 _filterData: null,396 updateTriggers: {397 _filterData: 0398 }399 },400 onAfterUpdate: ({layer, oldState}) => {401 getChecksForFilterChange(true)({layer, oldState});402 const {layerData} = layer.state.aggregatorState;403 const isPointFiltered = layerData.data.every(bin => bin.filteredPoints === null);404 t.ok(isPointFiltered, 'filteredPoints in bins should be reset to null');405 }406 },407 {408 updateProps: {409 cellSize: 800410 },411 onAfterUpdate: getChecksForCellSizeChange()412 },413 {414 updateProps: {415 getPosition: d => d.COORDINATES416 },417 onAfterUpdate: getChecksForPositionChange(false)418 },419 {420 updateProps: {421 getPosition: d => d.COORDINATES,422 updateTriggers: {423 getPosition: 1424 }425 },426 onAfterUpdate: getChecksForPositionChange(true)427 },428 {429 updateProps: {430 getColorWeight: x => 2431 },432 onAfterUpdate: getCheckForNoBinChange('getColorWeight w/o trigger', 'fillColor')433 },434 {435 updateProps: {436 getColorWeight: x => 2,437 updateTriggers: {438 getColorWeight: 1439 }440 },441 onAfterUpdate: getCheckForTriggeredBinUpdate('getColorWeight w/ trigger', 'fillColor')442 },443 {444 updateProps: {445 getColorValue: x => 2446 },447 onAfterUpdate: getCheckForNoBinChange('getColorValue w/o trigger', 'fillColor')448 },449 {450 updateProps: {451 getColorValue: x => 2,452 updateTriggers: {453 getColorValue: 1454 }455 },456 onAfterUpdate: getCheckForTriggeredBinUpdate('getColorValue w/ trigger', 'fillColor')457 },458 {459 updateProps: {460 colorAggregation: 'MEAN',461 getColorValue: null462 },463 onAfterUpdate: getCheckForTriggeredBinUpdate(464 'colorAggregation w/o getColorValue',465 'fillColor'466 )467 },468 {469 updateProps: {470 upperPercentile: 90471 },472 onAfterUpdate: getChecksForPercentileUpdate('upper', 'fillColor')473 },474 {475 updateProps: {476 lowerPercentile: 90477 },478 onAfterUpdate: getChecksForPercentileUpdate('lower', 'fillColor')479 },480 {481 updateProps: {482 colorDomain: [0, 10]483 },484 onAfterUpdate: getChecksForDomainOrRangeUpdate('Domain', 'fillColor')485 },486 {487 updateProps: {488 colorRange: [[1, 1, 1], [2, 2, 2], [3, 3, 3]]489 },490 onAfterUpdate: getChecksForDomainOrRangeUpdate('Range', 'fillColor')491 },492 {493 updateProps: {494 getElevationWeight: x => 2495 },496 onAfterUpdate: getCheckForNoBinChange('getElevationWeight', 'elevation')497 },498 {499 updateProps: {500 getElevationWeight: x => 2,501 updateTriggers: {502 getElevationWeight: 1503 }504 },505 onAfterUpdate: getCheckForTriggeredBinUpdate('getElevationWeight', 'elevation')506 },507 {508 updateProps: {509 getElevationValue: x => 2510 },511 onAfterUpdate: getCheckForNoBinChange('getElevationValue w/o trigger', 'elevation')512 },513 {514 updateProps: {515 getElevationValue: x => 2,516 updateTriggers: {517 getElevationValue: 1518 }519 },520 onAfterUpdate: getCheckForTriggeredBinUpdate('getElevationValue', 'elevation')521 },522 {523 updateProps: {524 elevationAggregation: 'MEAN',525 getElevationValue: null526 },527 onAfterUpdate: getCheckForTriggeredBinUpdate('elevationAggregation', 'elevation')528 },529 {530 updateProps: {531 elevationUpperPercentile: 80532 },533 onAfterUpdate: getChecksForPercentileUpdate('elevationUpper', 'elevation')534 },535 {536 updateProps: {537 elevationLowerPercentile: 10538 },539 onAfterUpdate: getChecksForPercentileUpdate('elevationLower', 'elevation')540 },541 {542 updateProps: {543 elevationRange: [1, 10]544 },545 onAfterUpdate: getChecksForDomainOrRangeUpdate('Range', 'elevation')546 },547 {548 updateProps: {549 elevationDomain: [0, 10]550 },551 onAfterUpdate: getChecksForDomainOrRangeUpdate('Domain', 'elevation')552 },553 {554 updateProps: {555 colorScaleType: 'quantize'556 },557 onAfterUpdate: getChecksForColorScaleTypeQuantize('quantize')558 },559 {560 updateProps: {561 colorScaleType: 'linear'562 },563 onAfterUpdate: getChecksForColorScaleTypeLinear('linear')564 },565 {566 updateProps: {567 colorScaleType: 'quantile'568 },569 onAfterUpdate: getChecksForColorScaleTypeQuantile('quantile')570 },571 {572 updateProps: {573 colorScaleType: 'ordinal'574 },575 onAfterUpdate: getChecksForColorScaleTypeOrdinal('ordinal')576 }577 ]578 });579 t.end();580});581test('CPUGridLayer#updateTriggers', t => {582 // setup spies583 const SPIES = ['_onGetSublayerColor', '_onGetSublayerElevation'];584 function getSublayerAttributeUpdateCheck(prop, result = {}) {585 return function onAfterUpdate({subLayer, spies}) {586 t.ok(587 result.color ? spies._onGetSublayerColor.called : !spies._onGetSublayerColor.called,588 `update ${prop} should ${result.color ? '' : 'not'} call _onGetSublayerColor`589 );590 t.ok(591 result.elevation592 ? spies._onGetSublayerElevation.called593 : !spies._onGetSublayerElevation.called,594 `update ${prop} should ${result.elevation ? '' : 'not'} call _onGetSublayerElevation`595 );596 };597 }598 testLayer({599 Layer: CPUGridLayer,600 spies: SPIES,601 onError: t.notOk,602 testCases: [603 {604 props: {605 data: FIXTURES.points,606 cellSize: 400,607 getColorValue: d => 3,608 getElevationValue: d => 4,609 getPosition: d => d.COORDINATES610 }611 },612 {613 updateProps: {614 cellSize: 800615 },616 onAfterUpdate: getSublayerAttributeUpdateCheck('cellSize', {color: true, elevation: true})617 },618 {619 updateProps: {620 opacity: 0.1621 },622 onAfterUpdate: getSublayerAttributeUpdateCheck('opacity', {color: false, elevation: false})623 },624 {625 updateProps: {626 coverage: 0.1627 },628 onAfterUpdate: getSublayerAttributeUpdateCheck('coverage', {color: false, elevation: false})629 },630 {631 updateProps: {632 extruded: true633 },634 onAfterUpdate: getSublayerAttributeUpdateCheck('extruded', {color: false, elevation: false})635 },636 {637 updateProps: {638 getColorWeight: x => 2639 },640 onAfterUpdate: getSublayerAttributeUpdateCheck('getColorWeight w/o triggers', {641 color: false,642 elevation: false643 })644 },645 {646 updateProps: {647 getColorWeight: x => 2,648 updateTriggers: {649 getColorWeight: 1650 }651 },652 onAfterUpdate: getSublayerAttributeUpdateCheck('getColorWeight w triggers', {653 color: true,654 elevation: false655 })656 },657 {658 updateProps: {659 getColorWeight: x => 3660 },661 onAfterUpdate: getSublayerAttributeUpdateCheck('getColorWeight w/o triggers', {662 color: false,663 elevation: false664 })665 },666 {667 updateProps: {668 getColorValue: x => 2669 },670 onAfterUpdate: getSublayerAttributeUpdateCheck('getColorValue null to assigned ', {671 color: false,672 elevation: false673 })674 },675 // {676 // updateProps: {677 // getColorValue: x => 3678 // },679 // onAfterUpdate: getSublayerAttributeUpdateCheck('getColorValue w/o triggers', {680 // color: false,681 // elevation: false682 // })683 // },684 {685 updateProps: {686 getColorValue: x => 4,687 updateTriggers: {688 getColorValue: 1689 }690 },691 onAfterUpdate: getSublayerAttributeUpdateCheck('getColorValue w triggers', {692 color: true,693 elevation: false694 })695 },696 {697 updateProps: {698 getColorValue: x => 4,699 updateTriggers: {700 getColorValue: {701 a: 1,702 b: 2703 }704 }705 },706 onAfterUpdate: getSublayerAttributeUpdateCheck('getColorValue w triggers as object', {707 color: true,708 elevation: false709 })710 },711 {712 updateProps: {713 getColorValue: x => 4,714 updateTriggers: {715 getColorValue: {716 a: 1,717 b: 2718 }719 }720 },721 onAfterUpdate: getSublayerAttributeUpdateCheck('getColorValue w triggers as object', {722 color: false,723 elevation: false724 })725 },726 {727 updateProps: {728 getColorValue: x => 4,729 updateTriggers: {730 getColorValue: {731 a: 2,732 b: 2733 }734 }735 },736 onAfterUpdate: getSublayerAttributeUpdateCheck(737 'getColorValue w triggers as changed object',738 {739 color: true,740 elevation: false741 }742 )743 },744 {745 updateProps: {746 upperPercentile: 90747 },748 onAfterUpdate: getSublayerAttributeUpdateCheck('upperPercentile', {749 color: true,750 elevation: false751 })752 },753 {754 updateProps: {755 lowerPercentile: 10756 },757 onAfterUpdate: getSublayerAttributeUpdateCheck('lowerPercentile', {758 color: true,759 elevation: false760 })761 },762 {763 updateProps: {764 colorDomain: [10, 20]765 },766 onAfterUpdate: getSublayerAttributeUpdateCheck('colorDomain', {767 color: true,768 elevation: false769 })770 },771 {772 updateProps: {773 colorRange: [[1, 2, 3], [2, 3, 4], [3, 4, 5]]774 },775 onAfterUpdate: getSublayerAttributeUpdateCheck('colorRange', {776 color: true,777 elevation: false778 })779 },780 {781 updateProps: {782 elevationAggregation: 'MEAN'783 },784 onAfterUpdate: getSublayerAttributeUpdateCheck('elevationAggregation', {785 color: false,786 elevation: true787 })788 },789 {790 updateProps: {791 getElevationWeight: x => 2792 },793 onAfterUpdate: getSublayerAttributeUpdateCheck('getElevationWeight w/o triggers', {794 color: false,795 elevation: false796 })797 },798 {799 updateProps: {800 getElevationWeight: x => 2,801 updateTriggers: {802 getElevationWeight: 1,803 // persist color updateTriggers to avoid triggering color update804 getColorValue: 1805 }806 },807 onAfterUpdate: getSublayerAttributeUpdateCheck('getElevationWeight w triggers', {808 color: true,809 elevation: true810 })811 },812 {813 updateProps: {814 getElevationWeight: x => 3815 },816 onAfterUpdate: getSublayerAttributeUpdateCheck('getElevationWeight w/o triggers', {817 color: false,818 elevation: false819 })820 },821 {822 updateProps: {823 getElevationValue: x => 2824 },825 onAfterUpdate: getSublayerAttributeUpdateCheck('getElevationValue null to assigned', {826 color: false,827 elevation: false828 })829 },830 {831 updateProps: {832 getElevationValue: x => 3833 },834 onAfterUpdate: getSublayerAttributeUpdateCheck('getElevationValue w/o triggers', {835 color: false,836 elevation: false837 })838 },839 {840 updateProps: {841 getElevationValue: x => 4,842 updateTriggers: {843 getElevationValue: 1,844 // persist getColorValue update triggers845 getColorValue: 1846 }847 },848 onAfterUpdate: getSublayerAttributeUpdateCheck('getElevationValue w triggers', {849 color: false,850 elevation: true851 })852 },853 {854 updateProps: {855 elevationUpperPercentile: 90856 },857 onAfterUpdate: getSublayerAttributeUpdateCheck('elevationUpperPercentile', {858 color: false,859 elevation: true860 })861 },862 {863 updateProps: {864 elevationLowerPercentile: 10865 },866 onAfterUpdate: getSublayerAttributeUpdateCheck('elevationLowerPercentile', {867 color: false,868 elevation: true869 })870 },871 {872 updateProps: {873 elevationDomain: [10, 20]874 },875 onAfterUpdate: getSublayerAttributeUpdateCheck('elevationDomain', {876 color: false,877 elevation: true878 })879 },880 {881 updateProps: {882 elevationRange: [2, 20]883 },884 onAfterUpdate: getSublayerAttributeUpdateCheck('elevationRange', {885 color: false,886 elevation: true887 })888 }889 ]890 });891 t.end();...
hexagon-layer.spec.js
Source:hexagon-layer.spec.js
1// Copyright (c) 2015 - 2017 Uber Technologies, Inc.2//3// Permission is hereby granted, free of charge, to any person obtaining a copy4// of this software and associated documentation files (the "Software"), to deal5// in the Software without restriction, including without limitation the rights6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell7// copies of the Software, and to permit persons to whom the Software is8// furnished to do so, subject to the following conditions:9//10// The above copyright notice and this permission notice shall be included in11// all copies or substantial portions of the Software.12//13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN19// THE SOFTWARE.20import test from 'tape-catch';21import {makeSpy} from '@probe.gl/test-utils';22import * as data from 'deck.gl-test/data';23import {testLayer, testInitializeLayer, generateLayerTests} from '@deck.gl/test-utils';24import {ColumnLayer} from '@deck.gl/layers';25import {HexagonLayer} from '@deck.gl/aggregation-layers';26test('HexagonLayer', t => {27 const testCases = generateLayerTests({28 Layer: HexagonLayer,29 sampleProps: {30 data: data.points.slice(0, 3),31 getPosition: d => d.COORDINATES32 },33 assert: t.ok,34 onBeforeUpdate: ({testCase}) => t.comment(testCase.title),35 onAfterUpdate({layer}) {36 if (layer.props.data && layer.props.data.length) {37 t.ok(layer.state.aggregatorState.layerData.data.length > 0, 'should update state.hexagons');38 }39 }40 });41 testLayer({Layer: HexagonLayer, testCases, onError: t.notOk});42 t.end();43});44// props to initialize layer with45// update props46// asserts on the resulting layer47test('HexagonLayer#updateLayer', t => {48 // assert on state property updates after layer.prop change49 function assertStateUpdate(shouldUpdate, prop) {50 return function onAfterUpdate({layer, oldState: oldLayerState}) {51 function checkIfUpdated(state, oldState, shouldUpdateItem, previousKeys) {52 if (typeof shouldUpdateItem === 'object') {53 for (const key in shouldUpdateItem) {54 checkIfUpdated(55 state[key],56 oldState[key],57 shouldUpdateItem[key],58 `${previousKeys}.${key}`59 );60 }61 } else {62 t.ok(63 shouldUpdateItem ? state !== oldState : state === oldState,64 `update props.${prop} should ${!shouldUpdateItem ? 'not' : ''} update ${previousKeys}`65 );66 }67 }68 checkIfUpdated(69 layer.state.aggregatorState,70 oldLayerState.aggregatorState,71 shouldUpdate,72 'aggregatorState'73 );74 };75 }76 function getChecksForFilterChange(triggered) {77 const shouldUpdate = {78 layerData: false,79 dimensions: {80 fillColor: {81 sortedBins: triggered,82 valueDomain: triggered,83 getValue: triggered,84 scaleFunc: triggered85 },86 elevation: {87 sortedBins: triggered,88 valueDomain: triggered,89 getValue: triggered,90 scaleFunc: triggered91 }92 }93 };94 return assertStateUpdate(shouldUpdate, 'getFitlerBy');95 }96 function getChecksForRadiusChange() {97 const shouldUpdate = {98 layerData: true,99 dimensions: {100 fillColor: {101 sortedBins: true,102 valueDomain: true,103 getValue: false,104 scaleFunc: true105 },106 elevation: {107 sortedBins: true,108 valueDomain: true,109 getValue: false,110 scaleFunc: true111 }112 }113 };114 return assertStateUpdate(shouldUpdate, 'radius');115 }116 function getChecksForPositionChange(triggerChange) {117 const shouldUpdate = {118 layerData: triggerChange,119 dimensions: {120 fillColor: {121 sortedBins: triggerChange,122 valueDomain: triggerChange,123 getValue: false,124 scaleFunc: triggerChange125 },126 elevation: {127 sortedBins: triggerChange,128 valueDomain: triggerChange,129 getValue: false,130 scaleFunc: triggerChange131 }132 }133 };134 return assertStateUpdate(135 shouldUpdate,136 `getPosition ${triggerChange ? 'w/' : 'w/o'} trigger change`137 );138 }139 function getCheckForNoBinChange(accessor, dimension) {140 const update = dimension;141 const noUpdate = ['fillColor', 'elevation'].find(k => k !== dimension);142 const shouldUpdate = {143 layerData: false,144 dimensions: {145 [update]: {146 sortedBins: false,147 valueDomain: false,148 getValue:149 accessor === 'getColorValue w/o trigger' ||150 accessor === 'getElevationValue w/o trigger',151 scaleFunc: false152 },153 [noUpdate]: {154 sortedBins: false,155 valueDomain: false,156 getValue: false,157 scaleFunc: false158 }159 }160 };161 return assertStateUpdate(shouldUpdate, accessor);162 }163 function getCheckForTriggeredBinUpdate(accessor, dimension) {164 const update = dimension;165 const noUpdate = ['fillColor', 'elevation'].find(k => k !== dimension);166 const shouldUpdate = {167 layerData: false,168 dimensions: {169 [update]: {170 sortedBins: true,171 valueDomain: true,172 getValue: true,173 scaleFunc: true174 },175 [noUpdate]: {176 sortedBins: false,177 valueDomain: false,178 getValue: false,179 scaleFunc: false180 }181 }182 };183 return assertStateUpdate(shouldUpdate, accessor);184 }185 function getChecksForPercentileUpdate(side, dimension) {186 const update = dimension;187 const noUpdate = ['fillColor', 'elevation'].find(k => k !== dimension);188 const shouldUpdate = {189 layerData: false,190 dimensions: {191 [update]: {192 sortedBins: false,193 valueDomain: true,194 getValue: false,195 scaleFunc: true196 },197 [noUpdate]: {198 sortedBins: false,199 valueDomain: false,200 getValue: false,201 scaleFunc: false202 }203 }204 };205 return assertStateUpdate(shouldUpdate, `${side}Percentile`);206 }207 function getChecksForDomainOrRangeUpdate(prop, dimension) {208 const update = dimension;209 const noUpdate = ['fillColor', 'elevation'].find(k => k !== dimension);210 const shouldUpdate = {211 layerData: false,212 dimensions: {213 [update]: {214 sortedBins: false,215 valueDomain: false,216 getValue: false,217 scaleFunc: true218 },219 [noUpdate]: {220 sortedBins: false,221 valueDomain: false,222 getValue: false,223 scaleFunc: false224 }225 }226 };227 return assertStateUpdate(shouldUpdate, `${dimension}${prop}`);228 }229 /*230 * Test layer update with test cases231 */232 testLayer({233 Layer: HexagonLayer,234 onError: t.notOk,235 testCases: [236 {237 title: 'Initialize',238 props: {239 data: data.points,240 radius: 400,241 getPosition: d => d.COORDINATES242 },243 onAfterUpdate({layer}) {244 const {245 layerData,246 dimensions: {fillColor, elevation}247 } = layer.state.aggregatorState;248 t.ok(layerData.data.length > 0, 'aggregatorState.dimensions.layerDate calculated');249 t.ok(250 fillColor.sortedBins,251 'aggregatorState.dimensions.fillColor.sortedColorBins calculated'252 );253 t.ok(254 elevation.sortedBins,255 'aggregatorState.dimensions.elevation.sortedColorBins calculated'256 );257 t.ok(258 Array.isArray(fillColor.valueDomain),259 'aggregatorState.dimensions.fillColor.valueDomain calculated'260 );261 t.ok(262 Array.isArray(elevation.valueDomain),263 'aggregatorState.dimensions.elevation.valueDomain calculated'264 );265 t.ok(266 typeof fillColor.getValue === 'function',267 'aggregatorState.dimensions.fillColor.getValue calculated'268 );269 t.ok(270 typeof elevation.getValue === 'function',271 'aggregatorState.dimension.elevation.getValue calculated'272 );273 t.ok(274 Array.isArray(fillColor.sortedBins.aggregatedBins),275 'aggregatorState.dimension.fillColor.sortedBins.aggregatedBins calculated'276 );277 t.ok(278 Array.isArray(elevation.sortedBins.aggregatedBins),279 'aggregatorState.dimension.elevation.sortedBins.aggregatedBins calculated'280 );281 const firstSortedBin = fillColor.sortedBins.aggregatedBins[0];282 const binTocell = layerData.data.find(d => d.index === firstSortedBin.i);283 t.ok(284 fillColor.sortedBins.binMap[binTocell.index] === firstSortedBin,285 'Correct aggregatorState.dimension.fillColor.sortedBins.binMap created'286 );287 }288 },289 {290 updateProps: {291 hexagonAggregator: points => ({hexagons: []})292 },293 onAfterUpdate: getChecksForRadiusChange()294 },295 {296 updateProps: {297 _filterData: pt => pt.SPACES >= 4 && pt.SPACES <= 10298 },299 onAfterUpdate: ({layer, oldState}) => {300 getChecksForFilterChange(false)({layer, oldState});301 const {layerData} = layer.state.aggregatorState;302 const isPointFiltered = layerData.data.every(bin => bin.filteredPoints === null);303 t.ok(isPointFiltered, 'filteredPoints in bins should be reset to null');304 }305 },306 {307 updateProps: {308 _filterData: pt => pt.SPACES >= 4 && pt.SPACES <= 10,309 updateTriggers: {310 _filterData: 1311 }312 },313 onAfterUpdate: ({layer, oldState}) => {314 getChecksForFilterChange(true)({layer, oldState});315 const {316 layerData,317 dimensions: {fillColor, elevation}318 } = layer.state.aggregatorState;319 const isPointFiltered = layerData.data.every(bin =>320 bin.filteredPoints.every(pt => pt.SPACES >= 4 && pt.SPACES <= 10)321 );322 t.ok(isPointFiltered, 'filteredPoints in bins should be correct');323 t.ok(324 fillColor.sortedBins,325 'aggregatorState.dimensions.fillColor.sortedColorBins calculated'326 );327 t.ok(328 elevation.sortedBins,329 'aggregatorState.dimensions.elevation.sortedColorBins calculated'330 );331 }332 },333 {334 updateProps: {335 _filterData: null,336 updateTriggers: {337 _filterData: 0338 }339 },340 onAfterUpdate: ({layer, oldState}) => {341 getChecksForFilterChange(true)({layer, oldState});342 const {layerData} = layer.state.aggregatorState;343 const isPointFiltered = layerData.data.every(bin => bin.filteredPoints === null);344 t.ok(isPointFiltered, 'filteredPoints in bins should be reset to null');345 }346 },347 {348 updateProps: {349 radius: 800350 },351 onAfterUpdate: getChecksForRadiusChange()352 },353 {354 updateProps: {355 getPosition: d => d.COORDINATES356 },357 onAfterUpdate: getChecksForPositionChange(false)358 },359 {360 updateProps: {361 getPosition: d => d.COORDINATES,362 updateTriggers: {363 getPosition: 1364 }365 },366 onAfterUpdate: getChecksForPositionChange(true)367 },368 {369 updateProps: {370 getColorWeight: x => 2371 },372 onAfterUpdate: getCheckForNoBinChange('getColorWeight w/o trigger', 'fillColor')373 },374 {375 updateProps: {376 getColorWeight: x => 2,377 updateTriggers: {378 getColorWeight: 1379 }380 },381 onAfterUpdate: getCheckForTriggeredBinUpdate('getColorWeight w/ trigger', 'fillColor')382 },383 {384 updateProps: {385 getColorValue: x => 2386 },387 onAfterUpdate: getCheckForNoBinChange('getColorValue w/o trigger', 'fillColor')388 },389 {390 updateProps: {391 getColorValue: x => 2,392 updateTriggers: {393 getColorValue: 1394 }395 },396 onAfterUpdate: getCheckForTriggeredBinUpdate('getColorValue w/ trigger', 'fillColor')397 },398 {399 updateProps: {400 colorAggregation: 'MEAN',401 getColorValue: null402 },403 onAfterUpdate: getCheckForTriggeredBinUpdate(404 'colorAggregation w/o getColorValue',405 'fillColor'406 )407 },408 {409 updateProps: {410 upperPercentile: 90411 },412 onAfterUpdate: getChecksForPercentileUpdate('upper', 'fillColor')413 },414 {415 updateProps: {416 lowerPercentile: 90417 },418 onAfterUpdate: getChecksForPercentileUpdate('lower', 'fillColor')419 },420 {421 updateProps: {422 colorDomain: [0, 10]423 },424 onAfterUpdate: getChecksForDomainOrRangeUpdate('Domain', 'fillColor')425 },426 {427 updateProps: {428 colorRange: [[1, 1, 1], [2, 2, 2], [3, 3, 3]]429 },430 onAfterUpdate: getChecksForDomainOrRangeUpdate('Range', 'fillColor')431 },432 {433 updateProps: {434 getElevationWeight: x => 2435 },436 onAfterUpdate: getCheckForNoBinChange('getElevationWeight', 'elevation')437 },438 {439 updateProps: {440 getElevationWeight: x => 2,441 updateTriggers: {442 getElevationWeight: 1443 }444 },445 onAfterUpdate: getCheckForTriggeredBinUpdate('getElevationWeight', 'elevation')446 },447 {448 updateProps: {449 getElevationValue: x => 2450 },451 onAfterUpdate: getCheckForNoBinChange('getElevationValue w/o trigger', 'elevation')452 },453 {454 updateProps: {455 getElevationValue: x => 2,456 updateTriggers: {457 getElevationValue: 1458 }459 },460 onAfterUpdate: getCheckForTriggeredBinUpdate('getElevationValue', 'elevation')461 },462 {463 updateProps: {464 elevationAggregation: 'MEAN',465 getElevationValue: null466 },467 onAfterUpdate: getCheckForTriggeredBinUpdate('elevationAggregation', 'elevation')468 },469 {470 updateProps: {471 elevationUpperPercentile: 80472 },473 onAfterUpdate: getChecksForPercentileUpdate('elevationUpper', 'elevation')474 },475 {476 updateProps: {477 elevationLowerPercentile: 10478 },479 onAfterUpdate: getChecksForPercentileUpdate('elevationLower', 'elevation')480 },481 {482 updateProps: {483 elevationRange: [1, 10]484 },485 onAfterUpdate: getChecksForDomainOrRangeUpdate('Range', 'elevation')486 },487 {488 updateProps: {489 elevationDomain: [0, 10]490 },491 onAfterUpdate: getChecksForDomainOrRangeUpdate('Domain', 'elevation')492 }493 ]494 });495 t.end();496});497test('HexagonLayer#updateTriggers', t => {498 const SPIES = ['_onGetSublayerColor', '_onGetSublayerElevation'];499 function getSublayerAttributeUpdateCheck(prop, result = {}) {500 return function onAfterUpdate({subLayer, spies}) {501 t.ok(502 result.color ? spies._onGetSublayerColor.called : !spies._onGetSublayerColor.called,503 `update ${prop} should ${result.color ? '' : 'not'} call _onGetSublayerColor`504 );505 t.ok(506 result.elevation507 ? spies._onGetSublayerElevation.called508 : !spies._onGetSublayerElevation.called,509 `update ${prop} should ${result.elevation ? '' : 'not'} call _onGetSublayerElevation`510 );511 };512 }513 testLayer({514 Layer: HexagonLayer,515 onError: t.notOk,516 spies: SPIES,517 testCases: [518 {519 // props to initialize layer with520 props: {521 data: data.points,522 radius: 400,523 getPosition: d => d.COORDINATES524 }525 },526 {527 updateProps: {528 radius: 800529 },530 onAfterUpdate: getSublayerAttributeUpdateCheck('radius', {color: true, elevation: true})531 },532 {533 updateProps: {534 opacity: 0.1535 },536 onAfterUpdate: getSublayerAttributeUpdateCheck('opacity', {color: false, elevation: false})537 },538 {539 updateProps: {540 coverage: 0.1541 },542 onAfterUpdate: getSublayerAttributeUpdateCheck('coverage', {color: false, elevation: false})543 },544 {545 updateProps: {546 extruded: true547 },548 onAfterUpdate: getSublayerAttributeUpdateCheck('extruded', {color: false, elevation: false})549 },550 {551 updateProps: {552 colorAggregation: 'MEAN'553 },554 onAfterUpdate: getSublayerAttributeUpdateCheck('colorAggregation', {555 color: true,556 elevation: false557 })558 },559 {560 updateProps: {561 getColorWeight: x => 2562 },563 onAfterUpdate: getSublayerAttributeUpdateCheck('getColorWeight w/o triggers', {564 color: false,565 elevation: false566 })567 },568 {569 updateProps: {570 getColorWeight: x => 2,571 updateTriggers: {572 getColorWeight: 1573 }574 },575 onAfterUpdate: getSublayerAttributeUpdateCheck('getColorWeight w triggers', {576 color: true,577 elevation: false578 })579 },580 {581 updateProps: {582 getColorWeight: x => 3583 },584 onAfterUpdate: getSublayerAttributeUpdateCheck('getColorWeight w/o triggers', {585 color: false,586 elevation: false587 })588 },589 {590 updateProps: {591 getColorValue: x => 2592 },593 onAfterUpdate: getSublayerAttributeUpdateCheck('getColorValue null to assigned ', {594 color: false,595 elevation: false596 })597 },598 {599 updateProps: {600 getColorValue: x => 3601 },602 onAfterUpdate: getSublayerAttributeUpdateCheck('getColorValue w/o triggers', {603 color: false,604 elevation: false605 })606 },607 {608 updateProps: {609 getColorValue: x => 4,610 updateTriggers: {611 getColorValue: 1612 }613 },614 onAfterUpdate: getSublayerAttributeUpdateCheck('getColorValue w triggers', {615 color: true,616 elevation: false617 })618 },619 {620 updateProps: {621 upperPercentile: 90622 },623 onAfterUpdate: getSublayerAttributeUpdateCheck('upperPercentile', {624 color: true,625 elevation: false626 })627 },628 {629 updateProps: {630 lowerPercentile: 10631 },632 onAfterUpdate: getSublayerAttributeUpdateCheck('lowerPercentile', {633 color: true,634 elevation: false635 })636 },637 {638 updateProps: {639 colorDomain: [10, 20]640 },641 onAfterUpdate: getSublayerAttributeUpdateCheck('colorDomain', {642 color: true,643 elevation: false644 })645 },646 {647 updateProps: {648 colorRange: [[1, 2, 3], [2, 3, 4], [3, 4, 5]]649 },650 onAfterUpdate: getSublayerAttributeUpdateCheck('colorRange', {651 color: true,652 elevation: false653 })654 },655 {656 updateProps: {657 elevationAggregation: 'MEAN'658 },659 onAfterUpdate: getSublayerAttributeUpdateCheck('elevationAggregation', {660 color: false,661 elevation: true662 })663 },664 {665 updateProps: {666 getElevationWeight: x => 2667 },668 onAfterUpdate: getSublayerAttributeUpdateCheck('getElevationWeight w/o triggers', {669 color: false,670 elevation: false671 })672 },673 {674 updateProps: {675 getElevationWeight: x => 2,676 updateTriggers: {677 getElevationWeight: 1,678 // persist color updateTriggers to avoid triggering color update679 getColorValue: 1680 }681 },682 onAfterUpdate: getSublayerAttributeUpdateCheck('getElevationWeight w triggers', {683 color: false,684 elevation: true685 })686 },687 {688 updateProps: {689 getElevationWeight: x => 3690 },691 onAfterUpdate: getSublayerAttributeUpdateCheck('getElevationWeight w/o triggers', {692 color: false,693 elevation: false694 })695 },696 {697 updateProps: {698 getElevationValue: x => 2699 },700 onAfterUpdate: getSublayerAttributeUpdateCheck('getElevationValue null to assigned', {701 color: false,702 elevation: false703 })704 },705 {706 updateProps: {707 getElevationValue: x => 3708 },709 onAfterUpdate: getSublayerAttributeUpdateCheck('getElevationValue w/o triggers', {710 color: false,711 elevation: false712 })713 },714 {715 updateProps: {716 getElevationValue: x => 4,717 updateTriggers: {718 getElevationValue: 1,719 // persist getColorValue update triggers720 getColorValue: 1721 }722 },723 onAfterUpdate: getSublayerAttributeUpdateCheck('getElevationValue w triggers', {724 color: false,725 elevation: true726 })727 },728 {729 updateProps: {730 elevationUpperPercentile: 90731 },732 onAfterUpdate: getSublayerAttributeUpdateCheck('elevationUpperPercentile', {733 color: false,734 elevation: true735 })736 },737 {738 updateProps: {739 elevationLowerPercentile: 10740 },741 onAfterUpdate: getSublayerAttributeUpdateCheck('elevationLowerPercentile', {742 color: false,743 elevation: true744 })745 },746 {747 updateProps: {748 elevationDomain: [10, 20]749 },750 onAfterUpdate: getSublayerAttributeUpdateCheck('elevationDomain', {751 color: false,752 elevation: true753 })754 },755 {756 updateProps: {757 elevationRange: [2, 20]758 },759 onAfterUpdate: getSublayerAttributeUpdateCheck('elevationRange', {760 color: false,761 elevation: true762 })763 }764 ]765 });766 t.end();767});768test('HexagonLayer#constructor', t => {769 let layer = new HexagonLayer({770 id: 'emptyGeoJsonLayer',771 data: [],772 radius: 1,773 pickable: true774 });775 t.ok(layer instanceof HexagonLayer, 'Empty HexagonLayer created');776 layer = new HexagonLayer({777 data: data.points,778 pickable: true779 });780 t.ok(layer instanceof HexagonLayer, 'HexagonLayer created');781 t.equal(layer.props.radius, 1000, 'set to default radius if not specified');782 layer = new HexagonLayer({783 data: data.points,784 radius: 500,785 getPosition: d => d.COORDINATES,786 pickable: true787 });788 t.ok(layer instanceof HexagonLayer, 'HexagonLayer created');789 testInitializeLayer({layer, onError: t.notOk});790 t.doesNotThrow(791 () =>792 new HexagonLayer({793 id: 'nullHexagonLayer',794 data: null,795 pickable: true796 }),797 'Null HexagonLayer did not throw exception'798 );799 t.end();800});801test('HexagonLayer#renderSubLayer', t => {802 makeSpy(HexagonLayer.prototype, '_onGetSublayerColor');803 makeSpy(HexagonLayer.prototype, '_onGetSublayerElevation');804 const layer = new HexagonLayer({805 data: data.points,806 radius: 500,807 getPosition: d => d.COORDINATES,808 pickable: true809 });810 testInitializeLayer({layer, onError: t.notOk});811 // render sublayer812 const subLayer = layer.renderLayers();813 testInitializeLayer({layer: subLayer, onError: t.notOk});814 t.ok(subLayer instanceof ColumnLayer, 'ColumnLayer rendered');815 // should call attribute updater twice816 // because test util calls both initialize and update layer817 t.ok(818 HexagonLayer.prototype._onGetSublayerColor.called,819 'should call _onGetSublayerColor number of hexagons times 2'820 );821 t.ok(822 HexagonLayer.prototype._onGetSublayerElevation.called,823 'should call _onGetSublayerElevation number of hexagons times 2'824 );825 HexagonLayer.prototype._onGetSublayerColor.restore();826 HexagonLayer.prototype._onGetSublayerElevation.restore();827 t.end();...
sharedUpdateXML.js
Source:sharedUpdateXML.js
1/* Any copyright is dedicated to the Public Domain.2 * http://creativecommons.org/publicdomain/zero/1.0/3 */4/**5 * Helper functions for creating xml strings used by application update tests.6 *7 * !IMPORTANT - This file contains everything needed (along with dependencies)8 * by the updates.sjs file used by the mochitest-chrome tests. Since xpcshell9 * used by the http server is launched with -v 170 this file must not use10 * features greater than JavaScript 1.7.11 */12/* eslint-disable no-undef */13const FILE_SIMPLE_MAR = "simple.mar";14const SIZE_SIMPLE_MAR = "1404";15const STATE_NONE = "null";16const STATE_DOWNLOADING = "downloading";17const STATE_PENDING = "pending";18const STATE_PENDING_SVC = "pending-service";19const STATE_APPLYING = "applying";20const STATE_APPLIED = "applied";21const STATE_APPLIED_SVC = "applied-service";22const STATE_SUCCEEDED = "succeeded";23const STATE_DOWNLOAD_FAILED = "download-failed";24const STATE_FAILED = "failed";25const LOADSOURCE_ERROR_WRONG_SIZE = 2;26const CRC_ERROR = 4;27const READ_ERROR = 6;28const WRITE_ERROR = 7;29const MAR_CHANNEL_MISMATCH_ERROR = 22;30const VERSION_DOWNGRADE_ERROR = 23;31const SERVICE_COULD_NOT_COPY_UPDATER = 49;32const SERVICE_INVALID_APPLYTO_DIR_STAGED_ERROR = 52;33const SERVICE_INVALID_APPLYTO_DIR_ERROR = 54;34const SERVICE_INVALID_INSTALL_DIR_PATH_ERROR = 55;35const SERVICE_INVALID_WORKING_DIR_PATH_ERROR = 56;36const INVALID_APPLYTO_DIR_STAGED_ERROR = 72;37const INVALID_APPLYTO_DIR_ERROR = 74;38const INVALID_INSTALL_DIR_PATH_ERROR = 75;39const INVALID_WORKING_DIR_PATH_ERROR = 76;40const INVALID_CALLBACK_PATH_ERROR = 77;41const INVALID_CALLBACK_DIR_ERROR = 78;42// Error codes 80 through 99 are reserved for nsUpdateService.js and are not43// defined in common/errors.h44const ERR_OLDER_VERSION_OR_SAME_BUILD = 90;45const ERR_UPDATE_STATE_NONE = 91;46const ERR_CHANNEL_CHANGE = 92;47const STATE_FAILED_DELIMETER = ": ";48const STATE_FAILED_LOADSOURCE_ERROR_WRONG_SIZE =49 STATE_FAILED + STATE_FAILED_DELIMETER + LOADSOURCE_ERROR_WRONG_SIZE;50const STATE_FAILED_CRC_ERROR =51 STATE_FAILED + STATE_FAILED_DELIMETER + CRC_ERROR;52const STATE_FAILED_READ_ERROR =53 STATE_FAILED + STATE_FAILED_DELIMETER + READ_ERROR;54const STATE_FAILED_WRITE_ERROR =55 STATE_FAILED + STATE_FAILED_DELIMETER + WRITE_ERROR;56const STATE_FAILED_MAR_CHANNEL_MISMATCH_ERROR =57 STATE_FAILED + STATE_FAILED_DELIMETER + MAR_CHANNEL_MISMATCH_ERROR;58const STATE_FAILED_VERSION_DOWNGRADE_ERROR =59 STATE_FAILED + STATE_FAILED_DELIMETER + VERSION_DOWNGRADE_ERROR;60const STATE_FAILED_SERVICE_COULD_NOT_COPY_UPDATER =61 STATE_FAILED + STATE_FAILED_DELIMETER + SERVICE_COULD_NOT_COPY_UPDATER;62const STATE_FAILED_SERVICE_INVALID_APPLYTO_DIR_STAGED_ERROR =63 STATE_FAILED + STATE_FAILED_DELIMETER + SERVICE_INVALID_APPLYTO_DIR_STAGED_ERROR;64const STATE_FAILED_SERVICE_INVALID_APPLYTO_DIR_ERROR =65 STATE_FAILED + STATE_FAILED_DELIMETER + SERVICE_INVALID_APPLYTO_DIR_ERROR;66const STATE_FAILED_SERVICE_INVALID_INSTALL_DIR_PATH_ERROR =67 STATE_FAILED + STATE_FAILED_DELIMETER + SERVICE_INVALID_INSTALL_DIR_PATH_ERROR;68const STATE_FAILED_SERVICE_INVALID_WORKING_DIR_PATH_ERROR =69 STATE_FAILED + STATE_FAILED_DELIMETER + SERVICE_INVALID_WORKING_DIR_PATH_ERROR;70const STATE_FAILED_INVALID_APPLYTO_DIR_STAGED_ERROR =71 STATE_FAILED + STATE_FAILED_DELIMETER + INVALID_APPLYTO_DIR_STAGED_ERROR;72const STATE_FAILED_INVALID_APPLYTO_DIR_ERROR =73 STATE_FAILED + STATE_FAILED_DELIMETER + INVALID_APPLYTO_DIR_ERROR;74const STATE_FAILED_INVALID_INSTALL_DIR_PATH_ERROR =75 STATE_FAILED + STATE_FAILED_DELIMETER + INVALID_INSTALL_DIR_PATH_ERROR;76const STATE_FAILED_INVALID_WORKING_DIR_PATH_ERROR =77 STATE_FAILED + STATE_FAILED_DELIMETER + INVALID_WORKING_DIR_PATH_ERROR;78const STATE_FAILED_INVALID_CALLBACK_PATH_ERROR =79 STATE_FAILED + STATE_FAILED_DELIMETER + INVALID_CALLBACK_PATH_ERROR;80const STATE_FAILED_INVALID_CALLBACK_DIR_ERROR =81 STATE_FAILED + STATE_FAILED_DELIMETER + INVALID_CALLBACK_DIR_ERROR;82const DEFAULT_UPDATE_VERSION = "999999.0";83/**84 * Constructs a string representing a remote update xml file.85 *86 * @param aUpdates87 * The string representing the update elements.88 * @return The string representing a remote update xml file.89 */90function getRemoteUpdatesXMLString(aUpdates) {91 return "<?xml version=\"1.0\"?>" +92 "<updates>" +93 aUpdates +94 "</updates>";95}96/**97 * Constructs a string representing an update element for a remote update xml98 * file. See getUpdateString for parameter information not provided below.99 *100 * @param aUpdateProps101 * An object containing non default test values for an nsIUpdate.102 * See updateProps names below for possible object names.103 * @param aPatches104 * String representing the application update patches.105 * @return The string representing an update element for an update xml file.106 */107function getRemoteUpdateString(aUpdateProps, aPatches) {108 const updateProps = {109 appVersion: DEFAULT_UPDATE_VERSION,110 buildID: "20080811053724",111 custom1: null,112 custom2: null,113 detailsURL: URL_HTTP_UPDATE_SJS + "?uiURL=DETAILS",114 displayVersion: null,115 name: "App Update Test",116 promptWaitTime: null,117 type: "major"118 };119 for (let name in aUpdateProps) {120 updateProps[name] = aUpdateProps[name];121 }122 return getUpdateString(updateProps) + ">" +123 aPatches +124 "</update>";125}126/**127 * Constructs a string representing a patch element for a remote update xml128 * file. See getPatchString for parameter information not provided below.129 *130 * @param aPatchProps (optional)131 * An object containing non default test values for an nsIUpdatePatch.132 * See patchProps below for possible object names.133 * @return The string representing a patch element for a remote update xml file.134 */135function getRemotePatchString(aPatchProps) {136 const patchProps = {137 type: "complete",138 _url: null,139 get url() {140 if (this._url) {141 return this._url;142 }143 if (gURLData) {144 return gURLData + FILE_SIMPLE_MAR;145 }146 return null;147 },148 set url(val) {149 this._url = val;150 },151 size: SIZE_SIMPLE_MAR152 };153 for (let name in aPatchProps) {154 patchProps[name] = aPatchProps[name];155 }156 return getPatchString(patchProps) + "/>";157}158/**159 * Constructs a string representing a local update xml file.160 *161 * @param aUpdates162 * The string representing the update elements.163 * @return The string representing a local update xml file.164 */165function getLocalUpdatesXMLString(aUpdates) {166 if (!aUpdates || aUpdates == "") {167 return "<updates xmlns=\"http://www.mozilla.org/2005/app-update\"/>";168 }169 return ("<updates xmlns=\"http://www.mozilla.org/2005/app-update\">" +170 aUpdates +171 "</updates>");172}173/**174 * Constructs a string representing an update element for a local update xml175 * file. See getUpdateString for parameter information not provided below.176 *177 * @param aUpdateProps178 * An object containing non default test values for an nsIUpdate.179 * See updateProps names below for possible object names.180 * @param aPatches181 * String representing the application update patches.182 * @return The string representing an update element for an update xml file.183 */184function getLocalUpdateString(aUpdateProps, aPatches) {185 const updateProps = {186 _appVersion: null,187 get appVersion() {188 if (this._appVersion) {189 return this._appVersion;190 }191 if (Services && Services.appinfo && Services.appinfo.version) {192 return Services.appinfo.version;193 }194 return DEFAULT_UPDATE_VERSION;195 },196 set appVersion(val) {197 this._appVersion = val;198 },199 buildID: "20080811053724",200 channel: gDefaultPrefBranch.getCharPref(PREF_APP_UPDATE_CHANNEL),201 custom1: null,202 custom2: null,203 detailsURL: URL_HTTP_UPDATE_SJS + "?uiURL=DETAILS",204 displayVersion: null,205 foregroundDownload: "true",206 installDate: "1238441400314",207 isCompleteUpdate: "true",208 name: "App Update Test",209 previousAppVersion: null,210 promptWaitTime: null,211 serviceURL: "http://test_service/",212 statusText: "Install Pending",213 type: "major"214 };215 for (let name in aUpdateProps) {216 updateProps[name] = aUpdateProps[name];217 }218 let channel = "channel=\"" + updateProps.channel + "\" ";219 let isCompleteUpdate =220 "isCompleteUpdate=\"" + updateProps.isCompleteUpdate + "\" ";221 let foregroundDownload = updateProps.foregroundDownload ?222 "foregroundDownload=\"" + updateProps.foregroundDownload + "\" " : "";223 let installDate = "installDate=\"" + updateProps.installDate + "\" ";224 let previousAppVersion = updateProps.previousAppVersion ?225 "previousAppVersion=\"" + updateProps.previousAppVersion + "\" " : "";226 let statusText = updateProps.statusText ?227 "statusText=\"" + updateProps.statusText + "\" " : "";228 let serviceURL = "serviceURL=\"" + updateProps.serviceURL + "\">";229 return getUpdateString(updateProps) +230 " " +231 channel +232 isCompleteUpdate +233 foregroundDownload +234 installDate +235 previousAppVersion +236 statusText +237 serviceURL +238 aPatches +239 "</update>";240}241/**242 * Constructs a string representing a patch element for a local update xml file.243 * See getPatchString for parameter information not provided below.244 *245 * @param aPatchProps (optional)246 * An object containing non default test values for an nsIUpdatePatch.247 * See patchProps below for possible object names.248 * @return The string representing a patch element for a local update xml file.249 */250function getLocalPatchString(aPatchProps) {251 const patchProps = {252 type: "complete",253 url: gURLData + FILE_SIMPLE_MAR,254 size: SIZE_SIMPLE_MAR,255 selected: "true",256 state: STATE_SUCCEEDED257 };258 for (let name in aPatchProps) {259 patchProps[name] = aPatchProps[name];260 }261 let selected = "selected=\"" + patchProps.selected + "\" ";262 let entityID = aPatchProps.entityID ?263 "entityID=\"" + aPatchProps.entityID + "\" " :264 "";265 let state = "state=\"" + patchProps.state + "\"/>";266 return getPatchString(patchProps) + " " +267 selected +268 entityID +269 state;270}271/**272 * Constructs a string representing an update element for a remote update xml273 * file.274 *275 * @param aUpdateProps (optional)276 * An object containing non default test values for an nsIUpdate.277 * See the aUpdateProps property names below for possible object names.278 * @return The string representing an update element for an update xml file.279 */280function getUpdateString(aUpdateProps) {281 let type = "type=\"" + aUpdateProps.type + "\" ";282 let name = "name=\"" + aUpdateProps.name + "\" ";283 let displayVersion = aUpdateProps.displayVersion ?284 "displayVersion=\"" + aUpdateProps.displayVersion + "\" " : "";285 let appVersion = "appVersion=\"" + aUpdateProps.appVersion + "\" ";286 // Not specifying a detailsURL will cause a leak due to bug 470244287 let detailsURL = "detailsURL=\"" + aUpdateProps.detailsURL + "\" ";288 let promptWaitTime = aUpdateProps.promptWaitTime ?289 "promptWaitTime=\"" + aUpdateProps.promptWaitTime + "\" " : "";290 let custom1 = aUpdateProps.custom1 ? aUpdateProps.custom1 + " " : "";291 let custom2 = aUpdateProps.custom2 ? aUpdateProps.custom2 + " " : "";292 let buildID = "buildID=\"" + aUpdateProps.buildID + "\"";293 return "<update " + type +294 name +295 displayVersion +296 appVersion +297 detailsURL +298 promptWaitTime +299 custom1 +300 custom2 +301 buildID;302}303/**304 * Constructs a string representing a patch element for an update xml file.305 *306 * @param aPatchProps (optional)307 * An object containing non default test values for an nsIUpdatePatch.308 * See the patchProps property names below for possible object names.309 * @return The string representing a patch element for an update xml file.310 */311function getPatchString(aPatchProps) {312 let type = "type=\"" + aPatchProps.type + "\" ";313 let url = "URL=\"" + aPatchProps.url + "\" ";314 let size = "size=\"" + aPatchProps.size + "\"";315 return "<patch " +316 type +317 url +318 size;...
passwords.jsm
Source:passwords.jsm
1/* This Source Code Form is subject to the terms of the Mozilla Public2 * License, v. 2.0. If a copy of the MPL was not distributed with this3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */4 /* This is a JavaScript module (JSM) to be imported via5 * Components.utils.import() and acts as a singleton. Only the following6 * listed symbols will exposed on import, and only when and where imported.7 */8var EXPORTED_SYMBOLS = ["Password", "DumpPasswords"];9const {classes: Cc, interfaces: Ci, utils: Cu} = Components;10Cu.import("resource://gre/modules/Services.jsm");11Cu.import("resource://tps/logger.jsm");12var nsLoginInfo = new Components.Constructor(13 "@mozilla.org/login-manager/loginInfo;1",14 Ci.nsILoginInfo,15 "init");16var DumpPasswords = function TPS__Passwords__DumpPasswords() {17 let logins = Services.logins.getAllLogins();18 Logger.logInfo("\ndumping password list\n", true);19 for (var i = 0; i < logins.length; i++) {20 Logger.logInfo("* host=" + logins[i].hostname + ", submitURL=" + logins[i].formSubmitURL +21 ", realm=" + logins[i].httpRealm + ", password=" + logins[i].password +22 ", passwordField=" + logins[i].passwordField + ", username=" +23 logins[i].username + ", usernameField=" + logins[i].usernameField, true);24 }25 Logger.logInfo("\n\nend password list\n", true);26};27/**28 * PasswordProps object; holds password properties.29 */30function PasswordProps(props) {31 this.hostname = null;32 this.submitURL = null;33 this.realm = null;34 this.username = "";35 this.password = "";36 this.usernameField = "";37 this.passwordField = "";38 this.delete = false;39 for (var prop in props) {40 if (prop in this)41 this[prop] = props[prop];42 }43}44/**45 * Password class constructor. Initializes instance properties.46 */47function Password(props) {48 this.props = new PasswordProps(props);49 if ("changes" in props) {50 this.updateProps = new PasswordProps(props);51 for (var prop in props.changes)52 if (prop in this.updateProps)53 this.updateProps[prop] = props.changes[prop];54 }55 else {56 this.updateProps = null;57 }58}59/**60 * Password instance methods.61 */62Password.prototype = {63 /**64 * Create65 *66 * Adds a password entry to the login manager for the password67 * represented by this object's properties. Throws on error.68 *69 * @return the new login guid70 */71 Create: function() {72 let login = new nsLoginInfo(this.props.hostname, this.props.submitURL,73 this.props.realm, this.props.username,74 this.props.password,75 this.props.usernameField,76 this.props.passwordField);77 Services.logins.addLogin(login);78 login.QueryInterface(Ci.nsILoginMetaInfo);79 return login.guid;80 },81 /**82 * Find83 *84 * Finds a password entry in the login manager, for the password85 * represented by this object's properties.86 *87 * @return the guid of the password if found, otherwise -188 */89 Find: function() {90 let logins = Services.logins.findLogins({},91 this.props.hostname,92 this.props.submitURL,93 this.props.realm);94 for (var i = 0; i < logins.length; i++) {95 if (logins[i].username == this.props.username &&96 logins[i].password == this.props.password &&97 logins[i].usernameField == this.props.usernameField &&98 logins[i].passwordField == this.props.passwordField) {99 logins[i].QueryInterface(Ci.nsILoginMetaInfo);100 return logins[i].guid;101 }102 }103 return -1;104 },105 /**106 * Update107 *108 * Updates an existing password entry in the login manager with109 * new properties. Throws on error. The 'old' properties are this110 * object's properties, the 'new' properties are the properties in111 * this object's 'updateProps' object.112 *113 * @return nothing114 */115 Update: function() {116 let oldlogin = new nsLoginInfo(this.props.hostname,117 this.props.submitURL,118 this.props.realm,119 this.props.username,120 this.props.password,121 this.props.usernameField,122 this.props.passwordField);123 let newlogin = new nsLoginInfo(this.updateProps.hostname,124 this.updateProps.submitURL,125 this.updateProps.realm,126 this.updateProps.username,127 this.updateProps.password,128 this.updateProps.usernameField,129 this.updateProps.passwordField);130 Services.logins.modifyLogin(oldlogin, newlogin);131 },132 /**133 * Remove134 *135 * Removes an entry from the login manager for a password which136 * matches this object's properties. Throws on error.137 *138 * @return nothing139 */140 Remove: function() {141 let login = new nsLoginInfo(this.props.hostname,142 this.props.submitURL,143 this.props.realm,144 this.props.username,145 this.props.password,146 this.props.usernameField,147 this.props.passwordField);148 Services.logins.removeLogin(login);149 },...
scripts.js
Source:scripts.js
...44 '--c-transZ',45 transforms.translateZ + 'vmin'46 );47}48updateProps();49gui.add(transforms, 'width', 0, 100, 1)50 .name('Width')51 .onChange(updateProps)52gui.add(transforms, 'height', 0, 100, 1)53 .name('Height')54 .onChange(updateProps)55gui.add(transforms, 'depth', 0, 50, 1)56 .name('Depth')57 .onChange(updateProps)58gui.add(transforms, 'rotate', -360, 360, 1)59 .name('Rotate')60 .onChange(updateProps)61gui.add(transforms, 'rotateX', -360, 360, 1)62 .name('Rotate X')...
slideshow.js
Source:slideshow.js
...3function addKeydownListener({ children, updateProps, currentSlide }) {4 const slides = filterChildren(children, c => {5 return c.type.name && c.type.name.toLowerCase() === 'slide';6 });7 updateProps({8 numSlides: slides.length9 });10 document.onkeydown = (e) => {11 const slides = filterChildren(children, c => {12 return c.type.name && c.type.name.toLowerCase() === 'slide';13 });14 switch (e.keyCode) {15 case 37:16 if (currentSlide > 0) {17 e.preventDefault();18 updateProps({19 currentSlide: currentSlide - 120 });21 }22 break;23 case 38:24 break;25 case 39:26 if (currentSlide < slides.length - 1) {27 e.preventDefault();28 updateProps({29 currentSlide: currentSlide + 130 });31 }32 break;33 case 40:34 break;35 }36 };37}38export default function Slideshow(props) {39 const {40 children,41 currentSlide,42 noTransition,...
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch({ headless: false });4 const page = await browser.newPage();5 await page.evaluate(() => {6 window.playwright.updateProps({ locale: 'en-GB' });7 });8 await page.reload();9 await browser.close();10})();11### `playwright.updateProps(props: Object)`12const { chromium } = require('playwright');13(async () => {14 const browser = await chromium.launch({ headless: false });
Using AI Code Generation
1const { webkit } = require('playwright-webkit');2(async () => {3 const browser = await webkit.launch();4 const context = await browser.newContext();5 const page = await context.newPage();6 const element = await page.$('text=Get started');7 await element.updateProps({ disabled: true });8 await browser.close();9})();10const { webkit } = require('playwright-webkit');11(async () => {12 const browser = await webkit.launch();13 const context = await browser.newContext();14 const page = await context.newPage();15 const element = await page.$('text=Get started');16 await element.updateStyles({ 'font-weight': 'bold' });17 await browser.close();18})();19const { webkit } = require('playwright-webkit');20(async () => {21 const browser = await webkit.launch();22 const context = await browser.newContext();23 const page = await context.newPage();24 const developerName = await page.$('#developer-name');25 await developerName.fill('John Smith');26 await browser.close();27})();28const { webkit } = require('playwright-webkit');29(async () => {30 const browser = await webkit.launch();31 const context = await browser.newContext();32 const page = await context.newPage();33 const developerName = await page.$('#developer-name');34 await developerName.type('John Smith');35 await browser.close();36})();
Using AI Code Generation
1const { Playwright } = require('playwright');2const playwright = new Playwright();3const browser = await playwright.chromium.launch();4const context = await browser.newContext();5const page = await context.newPage();6await page.updateProps({7});8await page.close();9await context.close();10await browser.close();11const { chromium } = require('playwright');12const browser = await chromium.launch();13const context = await browser.newContext();14const page = await context.newPage();15await page.updateProps({16});17await page.close();18await context.close();19await browser.close();20const { Playwright } = require('playwright');21const playwright = new Playwright();22const browser = await playwright.chromium.launch();23const context = await browser.newContext();24const page = await context.newPage();25await page.waitForEvent('foo');26await page.close();27await context.close();28await browser.close();29const { chromium } = require('playwright');30const browser = await chromium.launch();31const context = await browser.newContext();32const page = await context.newPage();33await page.waitForEvent('foo');34await page.close();35await context.close();36await browser.close();37const { Playwright } = require('playwright');38const playwright = new Playwright();39const browser = await playwright.chromium.launch();40const context = await browser.newContext();41const page = await context.newPage();42await page.waitForEventAndPromise('foo');43await page.close();44await context.close();45await browser.close();46const { chromium } = require('playwright');47const browser = await chromium.launch();48const context = await browser.newContext();49const page = await context.newPage();
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch({ headless: false });4 const page = await browser.newPage();5 const search = await page.$('header input');6 await search.evaluate(search => {7 search.updateProps({8 });9 });10 await browser.close();11})();12Please read [CONTRIBUTING.md](
Using AI Code Generation
1const { updateProps } = require('@playwright/test/lib/server/traceViewer/ui/traceModel');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch({ headless: false });5 const context = await browser.newContext();6 const page = await context.newPage();7 await page.screenshot({ path: `example.png` });8 await browser.close();9 updateProps('recording.videoSize', { width: 500, height: 500 });10})();11const { updateProps } = require('@playwright/test/lib/server/traceViewer/ui/traceModel');12const { chromium } = require('playwright');13(async () => {14 const browser = await chromium.launch({ headless: false });15 const context = await browser.newContext();16 const page = await context.newPage();17 await page.screenshot({ path: `example.png` });18 await browser.close();19 updateProps('recording.videoSize', { width: 500, height: 500 });20})();
Using AI Code Generation
1const { Playwright } = require('playwright-core');2const { chromium } = require('playwright-core');3(async () => {4 const browser = await chromium.launch();5 const page = await browser.newPage();6 const playwright = new Playwright(page);7 await playwright.updateProps({8 });9 await page.screenshot({ path: 'example.png' });10 await browser.close();11})();12const { TestCafe } = require('testcafe');13const { Role } = require('testcafe');14(async () => {15 const testcafe = new TestCafe('localhost', 1337, 1338);16 const runner = testcafe.createRunner();17 const playwright = new Playwright(testcafe);18 await playwright.updateProps({19 });20 .src('testcafe-test.js')21 .browsers('chrome')22 .run();23 await testcafe.close();24})();25const puppeteer = require('puppeteer');26(async () => {27 const browser = await puppeteer.launch();28 const page = await browser.newPage();29 const puppeteer = new Puppeteer(page);30 await puppeteer.updateProps({31 });32 await page.screenshot({ path
Using AI Code Generation
1const page = await browser.newPage();2await page.updateProps({3 viewport: { width: 500, height: 500 },4 userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/90.0.4413.0 Safari/537.36'5});6await page.screenshot({ path: 'example.png' });7- [PlaywrightInternal](#playwrightinternal)8 - [Parameters](#parameters)9 - [Examples](#examples)10- [Page](#page)11 - [Parameters](#parameters-1)12 - [Examples](#examples-1)13- [Browser](#browser)14 - [Parameters](#parameters-2)15 - [Examples](#examples-2)16- [BrowserContext](#browsercontext)17 - [Parameters](#parameters-3)18 - [Examples](#examples-3)19- [BrowserServer](#browserserver)20 - [Parameters](#parameters-4)21 - [Examples](#examples-4)22- [ElementHandle](#elementhandle)23 - [Parameters](#parameters-5)24 - [Examples](#examples-5)25- [Frame](#frame)26 - [Parameters](#parameters-6)27 - [Examples](#examples-6)28- [JSHandle](#jshandle)29 - [Parameters](#parameters-7)30 - [Examples](#examples-7)31- [Request](#request)32 - [Parameters](#parameters-8)33 - [Examples](#examples-8)34- [Response](#response)35 - [Parameters](#parameters-9)36 - [Examples](#examples-9)37- [WebSocket](#websocket)38 - [Parameters](#parameters-10)39 - [Examples](#examples-10)40- [Worker](#worker)41 - [Parameters](#parameters-11)
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!