 Chromium Code Reviews
 Chromium Code Reviews Issue 2538043006:
  Settings: About: Fix cros channel info.  (Closed)
    
  
    Issue 2538043006:
  Settings: About: Fix cros channel info.  (Closed) 
  | OLD | NEW | 
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 cr.define('settings_about_page', function() { | 5 cr.define('settings_about_page', function() { | 
| 6 /** | 6 /** | 
| 7 * @constructor | 7 * @constructor | 
| 8 * @implements {settings.AboutPageBrowserProxy} | 8 * @implements {settings.AboutPageBrowserProxy} | 
| 9 * @extends {settings.TestBrowserProxy} | 9 * @extends {settings.TestBrowserProxy} | 
| 10 */ | 10 */ | 
| 11 var TestAboutPageBrowserProxy = function() { | 11 var TestAboutPageBrowserProxy = function() { | 
| 12 var methodNames = [ | 12 var methodNames = [ | 
| 13 'pageReady', | 13 'pageReady', | 
| 14 'refreshUpdateStatus', | 14 'refreshUpdateStatus', | 
| 15 'openHelpPage', | 15 'openHelpPage', | 
| 16 'openFeedbackDialog', | 16 'openFeedbackDialog', | 
| 17 ]; | 17 ]; | 
| 18 | 18 | 
| 19 if (cr.isChromeOS) { | 19 if (cr.isChromeOS) { | 
| 20 methodNames.push( | 20 methodNames.push( | 
| 21 'getCurrentChannel', | 21 'getChannelInfo', | 
| 22 'getTargetChannel', | |
| 23 'getVersionInfo', | 22 'getVersionInfo', | 
| 24 'getRegulatoryInfo', | 23 'getRegulatoryInfo', | 
| 25 'setChannel'); | 24 'setChannel'); | 
| 26 } | 25 } | 
| 27 | 26 | 
| 28 settings.TestBrowserProxy.call(this, methodNames); | 27 settings.TestBrowserProxy.call(this, methodNames); | 
| 29 | 28 | 
| 30 /** @private {!UpdateStatus} */ | 29 /** @private {!UpdateStatus} */ | 
| 31 this.updateStatus_ = UpdateStatus.UPDATED; | 30 this.updateStatus_ = UpdateStatus.UPDATED; | 
| 32 | 31 | 
| 33 if (cr.isChromeOS) { | 32 if (cr.isChromeOS) { | 
| 34 /** @type {!VersionInfo} */ | 33 /** @private {!VersionInfo} */ | 
| 35 this.versionInfo_ = { | 34 this.versionInfo_ = { | 
| 36 arcVersion: '', | 35 arcVersion: '', | 
| 37 osFirmware: '', | 36 osFirmware: '', | 
| 38 osVersion: '', | 37 osVersion: '', | 
| 39 }; | 38 }; | 
| 40 | 39 | 
| 41 /** @private {!BrowserChannel} */ | 40 /** @private {!ChannelInfo} */ | 
| 42 this.currentChannel_ = BrowserChannel.BETA; | 41 this.channelInfo_ = { | 
| 43 | 42 currentChannel: BrowserChannel.BETA, | 
| 44 /** @private {!BrowserChannel} */ | 43 targetChannel: BrowserChannel.BETA, | 
| 45 this.targetChannel_ = BrowserChannel.BETA; | 44 canChangeChannel: true, | 
| 45 }; | |
| 46 | 46 | 
| 47 /** @private {?RegulatoryInfo} */ | 47 /** @private {?RegulatoryInfo} */ | 
| 48 this.regulatoryInfo_ = null; | 48 this.regulatoryInfo_ = null; | 
| 49 } | 49 } | 
| 50 }; | 50 }; | 
| 51 | 51 | 
| 52 TestAboutPageBrowserProxy.prototype = { | 52 TestAboutPageBrowserProxy.prototype = { | 
| 53 __proto__: settings.TestBrowserProxy.prototype, | 53 __proto__: settings.TestBrowserProxy.prototype, | 
| 54 | 54 | 
| 55 /** @param {!UpdateStatus} updateStatus */ | 55 /** @param {!UpdateStatus} updateStatus */ | 
| (...skipping 25 matching lines...) Expand all Loading... | |
| 81 this.methodCalled('openHelpPage'); | 81 this.methodCalled('openHelpPage'); | 
| 82 }, | 82 }, | 
| 83 }; | 83 }; | 
| 84 | 84 | 
| 85 if (cr.isChromeOS) { | 85 if (cr.isChromeOS) { | 
| 86 /** @param {!VersionInfo} */ | 86 /** @param {!VersionInfo} */ | 
| 87 TestAboutPageBrowserProxy.prototype.setVersionInfo = function(versionInfo) { | 87 TestAboutPageBrowserProxy.prototype.setVersionInfo = function(versionInfo) { | 
| 88 this.versionInfo_ = versionInfo; | 88 this.versionInfo_ = versionInfo; | 
| 89 }; | 89 }; | 
| 90 | 90 | 
| 91 /** @param {boolean} canChangeChannel */ | |
| 92 TestAboutPageBrowserProxy.prototype.setCanChangeChannel = function( | |
| 
dpapad
2016/12/07 01:42:23
Nit: Can we combine the setCanChangeChannel() and
 
stevenjb
2016/12/07 20:59:17
I did that initially but it actually ends up being
 | |
| 93 canChangeChannel) { | |
| 94 this.channelInfo_.canChangeChannel = canChangeChannel; | |
| 95 }; | |
| 96 | |
| 91 /** | 97 /** | 
| 92 * @param {!BrowserChannel} current | 98 * @param {!BrowserChannel} current | 
| 93 * @param {!BrowserChannel} target | 99 * @param {!BrowserChannel} target | 
| 94 */ | 100 */ | 
| 95 TestAboutPageBrowserProxy.prototype.setChannels = function( | 101 TestAboutPageBrowserProxy.prototype.setChannels = function( | 
| 96 current, target) { | 102 current, target) { | 
| 97 this.currentChannel_ = current; | 103 this.channelInfo_.currentChannel = current; | 
| 98 this.targetChannel_ = target; | 104 this.channelInfo_.targetChannel = target; | 
| 99 }; | 105 }; | 
| 100 | 106 | 
| 101 | |
| 102 /** @param {?RegulatoryInfo} regulatoryInfo */ | 107 /** @param {?RegulatoryInfo} regulatoryInfo */ | 
| 103 TestAboutPageBrowserProxy.prototype.setRegulatoryInfo = function( | 108 TestAboutPageBrowserProxy.prototype.setRegulatoryInfo = function( | 
| 104 regulatoryInfo) { | 109 regulatoryInfo) { | 
| 105 this.regulatoryInfo_ = regulatoryInfo; | 110 this.regulatoryInfo_ = regulatoryInfo; | 
| 106 }; | 111 }; | 
| 107 | 112 | 
| 108 /** @override */ | 113 /** @override */ | 
| 109 TestAboutPageBrowserProxy.prototype.getCurrentChannel = function() { | 114 TestAboutPageBrowserProxy.prototype.getChannelInfo = function() { | 
| 110 this.methodCalled('getCurrentChannel'); | 115 this.methodCalled('getChannelInfo'); | 
| 111 return Promise.resolve(this.currentChannel_); | 116 return Promise.resolve(this.channelInfo_); | 
| 112 }; | 117 }; | 
| 113 | 118 | 
| 114 /** @override */ | 119 /** @override */ | 
| 115 TestAboutPageBrowserProxy.prototype.getTargetChannel = function() { | |
| 116 this.methodCalled('getTargetChannel'); | |
| 117 return Promise.resolve(this.targetChannel_); | |
| 118 }; | |
| 119 | |
| 120 /** @override */ | |
| 121 TestAboutPageBrowserProxy.prototype.getVersionInfo = function() { | 120 TestAboutPageBrowserProxy.prototype.getVersionInfo = function() { | 
| 122 this.methodCalled('getVersionInfo'); | 121 this.methodCalled('getVersionInfo'); | 
| 123 return Promise.resolve(this.versionInfo_); | 122 return Promise.resolve(this.versionInfo_); | 
| 124 }; | 123 }; | 
| 125 | 124 | 
| 126 /** @override */ | 125 /** @override */ | 
| 127 TestAboutPageBrowserProxy.prototype.getRegulatoryInfo = function() { | 126 TestAboutPageBrowserProxy.prototype.getRegulatoryInfo = function() { | 
| 128 this.methodCalled('getRegulatoryInfo'); | 127 this.methodCalled('getRegulatoryInfo'); | 
| 129 return Promise.resolve(this.regulatoryInfo_); | 128 return Promise.resolve(this.regulatoryInfo_); | 
| 130 }; | 129 }; | 
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 179 }); | 178 }); | 
| 180 | 179 | 
| 181 /** @return {!Promise} */ | 180 /** @return {!Promise} */ | 
| 182 function initNewPage() { | 181 function initNewPage() { | 
| 183 aboutBrowserProxy.reset(); | 182 aboutBrowserProxy.reset(); | 
| 184 lifetimeBrowserProxy.reset(); | 183 lifetimeBrowserProxy.reset(); | 
| 185 PolymerTest.clearBody(); | 184 PolymerTest.clearBody(); | 
| 186 page = document.createElement('settings-about-page'); | 185 page = document.createElement('settings-about-page'); | 
| 187 settings.navigateTo(settings.Route.ABOUT); | 186 settings.navigateTo(settings.Route.ABOUT); | 
| 188 document.body.appendChild(page); | 187 document.body.appendChild(page); | 
| 189 return aboutBrowserProxy.whenCalled('refreshUpdateStatus'); | 188 return Promise.all([ | 
| 189 aboutBrowserProxy.whenCalled('getChannelInfo'), | |
| 190 aboutBrowserProxy.whenCalled('refreshUpdateStatus'), | |
| 191 ]); | |
| 190 } | 192 } | 
| 191 | 193 | 
| 192 /** | 194 /** | 
| 193 * Test that the status icon and status message update according to | 195 * Test that the status icon and status message update according to | 
| 194 * incoming 'update-status-changed' events. | 196 * incoming 'update-status-changed' events. | 
| 195 */ | 197 */ | 
| 196 test('IconAndMessageUpdates', function() { | 198 test('IconAndMessageUpdates', function() { | 
| 197 var icon = page.$$('iron-icon'); | 199 var icon = page.$$('iron-icon'); | 
| 198 assertTrue(!!icon); | 200 assertTrue(!!icon); | 
| 199 var statusMessageEl = page.$.updateStatusMessage; | 201 var statusMessageEl = page.$.updateStatusMessage; | 
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 573 osVersion: 'dummyOsVersion', | 575 osVersion: 'dummyOsVersion', | 
| 574 }; | 576 }; | 
| 575 browserProxy.setVersionInfo(versionInfo); | 577 browserProxy.setVersionInfo(versionInfo); | 
| 576 | 578 | 
| 577 page = document.createElement('settings-detailed-build-info'); | 579 page = document.createElement('settings-detailed-build-info'); | 
| 578 document.body.appendChild(page); | 580 document.body.appendChild(page); | 
| 579 | 581 | 
| 580 return Promise.all([ | 582 return Promise.all([ | 
| 581 browserProxy.whenCalled('pageReady'), | 583 browserProxy.whenCalled('pageReady'), | 
| 582 browserProxy.whenCalled('getVersionInfo'), | 584 browserProxy.whenCalled('getVersionInfo'), | 
| 583 browserProxy.whenCalled('getCurrentChannel'), | 585 browserProxy.whenCalled('getChannelInfo'), | 
| 584 ]).then(function() { | 586 ]).then(function() { | 
| 585 assertEquals(versionInfo.arcVersion, page.$.arcVersion.textContent); | 587 assertEquals(versionInfo.arcVersion, page.$.arcVersion.textContent); | 
| 586 assertEquals(versionInfo.osVersion, page.$.osVersion.textContent); | 588 assertEquals(versionInfo.osVersion, page.$.osVersion.textContent); | 
| 587 assertEquals(versionInfo.osFirmware, page.$.osFirmware.textContent); | 589 assertEquals(versionInfo.osFirmware, page.$.osFirmware.textContent); | 
| 588 }); | 590 }); | 
| 589 }); | 591 }); | 
| 590 | 592 | 
| 591 /** | 593 /** | 
| 592 * Checks whether the "change channel" button state (enabled/disabled) | 594 * Checks whether the "change channel" button state (enabled/disabled) | 
| 593 * correctly reflects whether the user is allowed to change channel (as | 595 * correctly reflects whether the user is allowed to change channel (as | 
| 594 * dictated by the browser via loadTimeData boolean). | 596 * dictated by the browser via loadTimeData boolean). | 
| 595 * @param {boolean} canChangeChannel Whether to simulate the case where | 597 * @param {boolean} canChangeChannel Whether to simulate the case where | 
| 596 * changing channels is allowed. | 598 * changing channels is allowed. | 
| 599 * @return {!Promise} | |
| 597 */ | 600 */ | 
| 598 function checkChangeChannelButton(canChangeChannel) { | 601 function checkChangeChannelButton(canChangeChannel) { | 
| 599 loadTimeData.overrideValues({ | 602 browserProxy.setCanChangeChannel(canChangeChannel); | 
| 600 aboutCanChangeChannel: canChangeChannel | |
| 601 }); | |
| 602 page = document.createElement('settings-detailed-build-info'); | 603 page = document.createElement('settings-detailed-build-info'); | 
| 603 document.body.appendChild(page); | 604 document.body.appendChild(page); | 
| 604 | 605 return browserProxy.whenCalled('getChannelInfo').then(function() { | 
| 605 var changeChannelButton = page.$$('paper-button'); | 606 var changeChannelButton = page.$$('paper-button'); | 
| 606 assertTrue(!!changeChannelButton); | 607 assertTrue(!!changeChannelButton); | 
| 607 assertEquals(canChangeChannel, !changeChannelButton.disabled) | 608 assertEquals(canChangeChannel, !changeChannelButton.disabled); | 
| 609 }); | |
| 608 } | 610 } | 
| 609 | 611 | 
| 610 test('ChangeChannel_Enabled', function() { | 612 test('ChangeChannel_Enabled', function() { | 
| 611 checkChangeChannelButton(true); | 613 return checkChangeChannelButton(true); | 
| 612 }); | 614 }); | 
| 613 | 615 | 
| 614 test('ChangeChannel_Disabled', function() { | 616 test('ChangeChannel_Disabled', function() { | 
| 615 checkChangeChannelButton(false); | 617 return checkChangeChannelButton(false); | 
| 616 }); | 618 }); | 
| 617 }); | 619 }); | 
| 618 } | 620 } | 
| 619 | 621 | 
| 620 function registerChannelSwitcherDialogTests() { | 622 function registerChannelSwitcherDialogTests() { | 
| 621 suite('ChannelSwitcherDialogTest', function() { | 623 suite('ChannelSwitcherDialogTest', function() { | 
| 622 var dialog = null; | 624 var dialog = null; | 
| 623 var radioButtons = null; | 625 var radioButtons = null; | 
| 624 var browserProxy = null; | 626 var browserProxy = null; | 
| 625 var currentChannel = BrowserChannel.BETA; | 627 var currentChannel = BrowserChannel.BETA; | 
| 626 | 628 | 
| 627 setup(function() { | 629 setup(function() { | 
| 628 browserProxy = new TestAboutPageBrowserProxy(); | 630 browserProxy = new TestAboutPageBrowserProxy(); | 
| 629 browserProxy.setChannels(currentChannel, currentChannel); | 631 browserProxy.setChannels(currentChannel, currentChannel); | 
| 630 settings.AboutPageBrowserProxyImpl.instance_ = browserProxy; | 632 settings.AboutPageBrowserProxyImpl.instance_ = browserProxy; | 
| 631 PolymerTest.clearBody(); | 633 PolymerTest.clearBody(); | 
| 632 dialog = document.createElement('settings-channel-switcher-dialog'); | 634 dialog = document.createElement('settings-channel-switcher-dialog'); | 
| 633 document.body.appendChild(dialog); | 635 document.body.appendChild(dialog); | 
| 634 | 636 | 
| 635 radioButtons = dialog.shadowRoot.querySelectorAll( | 637 radioButtons = dialog.shadowRoot.querySelectorAll( | 
| 636 'paper-radio-button'); | 638 'paper-radio-button'); | 
| 637 assertEquals(3, radioButtons.length); | 639 assertEquals(3, radioButtons.length); | 
| 638 return browserProxy.whenCalled('getCurrentChannel'); | 640 return browserProxy.whenCalled('getChannelInfo'); | 
| 639 }); | 641 }); | 
| 640 | 642 | 
| 641 teardown(function() { dialog.remove(); }); | 643 teardown(function() { dialog.remove(); }); | 
| 642 | 644 | 
| 643 test('Initialization', function() { | 645 test('Initialization', function() { | 
| 644 var radioGroup = dialog.$$('paper-radio-group'); | 646 var radioGroup = dialog.$$('paper-radio-group'); | 
| 645 assertTrue(!!radioGroup); | 647 assertTrue(!!radioGroup); | 
| 646 assertTrue(!!dialog.$.warning); | 648 assertTrue(!!dialog.$.warning); | 
| 647 assertTrue(!!dialog.$.changeChannel); | 649 assertTrue(!!dialog.$.changeChannel); | 
| 648 assertTrue(!!dialog.$.changeChannelAndPowerwash); | 650 assertTrue(!!dialog.$.changeChannelAndPowerwash); | 
| 649 | 651 | 
| 650 // Check that upon initialization the radio button corresponding to | 652 // Check that upon initialization the radio button corresponding to | 
| 651 // the current release channel is pre-selected. | 653 // the current release channel is pre-selected. | 
| 652 assertEquals(currentChannel, radioGroup.selected); | 654 assertEquals(currentChannel, radioGroup.selected); | 
| 653 assertTrue(dialog.$.warning.hidden); | 655 assertTrue(dialog.$.warning.hidden); | 
| 654 | 656 | 
| 655 // Check that action buttons are hidden when current and target | 657 // Check that action buttons are hidden when current and target | 
| 656 // channel are the same. | 658 // channel are the same. | 
| 657 assertTrue(dialog.$.changeChannel.hidden); | 659 assertTrue(dialog.$.changeChannel.hidden); | 
| 658 assertTrue(dialog.$.changeChannelAndPowerwash.hidden); | 660 assertTrue(dialog.$.changeChannelAndPowerwash.hidden); | 
| 659 }); | 661 }); | 
| 660 | 662 | 
| 661 // Test case where user switches to a less stable channel. | 663 // Test case where user switches to a less stable channel. | 
| 662 test('ChangeChannel_LessStable', function() { | 664 test('ChangeChannel_LessStable', function() { | 
| 663 assertEquals(BrowserChannel.DEV, radioButtons.item(2).name); | 665 assertEquals(BrowserChannel.DEV, radioButtons.item(2).name); | 
| 664 MockInteractions.tap(radioButtons.item(2)); | 666 MockInteractions.tap(radioButtons.item(2)); | 
| 665 Polymer.dom.flush(); | 667 Polymer.dom.flush(); | 
| 666 | 668 | 
| 667 assertFalse(dialog.$.warning.hidden); | 669 return browserProxy.whenCalled('getChannelInfo').then(function() { | 
| 668 // Check that only the "Change channel" button becomes visible. | 670 assertFalse(dialog.$.warning.hidden); | 
| 669 assertTrue(dialog.$.changeChannelAndPowerwash.hidden); | 671 // Check that only the "Change channel" button becomes visible. | 
| 670 assertFalse(dialog.$.changeChannel.hidden); | 672 assertTrue(dialog.$.changeChannelAndPowerwash.hidden); | 
| 673 assertFalse(dialog.$.changeChannel.hidden); | |
| 671 | 674 | 
| 672 var whenTargetChannelChangedFired = test_util.eventToPromise( | 675 var whenTargetChannelChangedFired = test_util.eventToPromise( | 
| 673 'target-channel-changed', dialog); | 676 'target-channel-changed', dialog); | 
| 674 | 677 | 
| 675 MockInteractions.tap(dialog.$.changeChannel); | 678 MockInteractions.tap(dialog.$.changeChannel); | 
| 676 return browserProxy.whenCalled('setChannel').then(function(args) { | 679 return browserProxy.whenCalled('setChannel').then(function(args) { | 
| 677 assertEquals(BrowserChannel.DEV, args[0]); | 680 assertEquals(BrowserChannel.DEV, args[0]); | 
| 678 assertFalse(args[1]); | 681 assertFalse(args[1]); | 
| 679 return whenTargetChannelChangedFired; | 682 return whenTargetChannelChangedFired; | 
| 680 }).then(function(event) { | 683 }).then(function(event) { | 
| 681 assertEquals(BrowserChannel.DEV, event.detail); | 684 assertEquals(BrowserChannel.DEV, event.detail); | 
| 685 }); | |
| 682 }); | 686 }); | 
| 683 }); | 687 }); | 
| 684 | 688 | 
| 685 // Test case where user switches to a more stable channel. | 689 // Test case where user switches to a more stable channel. | 
| 686 test('ChangeChannel_MoreStable', function() { | 690 test('ChangeChannel_MoreStable', function() { | 
| 687 assertEquals(BrowserChannel.STABLE, radioButtons.item(0).name); | 691 assertEquals(BrowserChannel.STABLE, radioButtons.item(0).name); | 
| 688 MockInteractions.tap(radioButtons.item(0)); | 692 MockInteractions.tap(radioButtons.item(0)); | 
| 689 Polymer.dom.flush(); | 693 Polymer.dom.flush(); | 
| 690 | 694 | 
| 691 assertFalse(dialog.$.warning.hidden); | 695 return browserProxy.whenCalled('getChannelInfo').then(function() { | 
| 692 // Check that only the "Change channel and Powerwash" button becomes | 696 assertFalse(dialog.$.warning.hidden); | 
| 693 // visible. | 697 // Check that only the "Change channel and Powerwash" button becomes | 
| 694 assertFalse(dialog.$.changeChannelAndPowerwash.hidden); | 698 // visible. | 
| 695 assertTrue(dialog.$.changeChannel.hidden); | 699 assertFalse(dialog.$.changeChannelAndPowerwash.hidden); | 
| 700 assertTrue(dialog.$.changeChannel.hidden); | |
| 696 | 701 | 
| 697 var whenTargetChannelChangedFired = test_util.eventToPromise( | 702 var whenTargetChannelChangedFired = test_util.eventToPromise( | 
| 698 'target-channel-changed', dialog); | 703 'target-channel-changed', dialog); | 
| 699 | 704 | 
| 700 MockInteractions.tap(dialog.$.changeChannelAndPowerwash); | 705 MockInteractions.tap(dialog.$.changeChannelAndPowerwash); | 
| 701 return browserProxy.whenCalled('setChannel').then(function(args) { | 706 return browserProxy.whenCalled('setChannel').then(function(args) { | 
| 702 assertEquals(BrowserChannel.STABLE, args[0]); | 707 assertEquals(BrowserChannel.STABLE, args[0]); | 
| 703 assertTrue(args[1]); | 708 assertTrue(args[1]); | 
| 704 return whenTargetChannelChangedFired; | 709 return whenTargetChannelChangedFired; | 
| 705 }).then(function(event) { | 710 }).then(function(event) { | 
| 706 assertEquals(BrowserChannel.STABLE, event.detail); | 711 assertEquals(BrowserChannel.STABLE, event.detail); | 
| 712 }); | |
| 707 }); | 713 }); | 
| 708 }); | 714 }); | 
| 709 }); | 715 }); | 
| 710 } | 716 } | 
| 711 } | 717 } | 
| 712 | 718 | 
| 713 return { | 719 return { | 
| 714 registerTests: function() { | 720 registerTests: function() { | 
| 715 if (cr.isChromeOS) { | 721 if (cr.isChromeOS) { | 
| 716 registerDetailedBuildInfoTests(); | 722 registerDetailedBuildInfoTests(); | 
| 717 registerChannelSwitcherDialogTests(); | 723 registerChannelSwitcherDialogTests(); | 
| 718 } | 724 } | 
| 719 registerAboutPageTests(); | 725 registerAboutPageTests(); | 
| 720 }, | 726 }, | 
| 721 registerOfficialBuildTests: registerOfficialBuildTests, | 727 registerOfficialBuildTests: registerOfficialBuildTests, | 
| 722 }; | 728 }; | 
| 723 }); | 729 }); | 
| OLD | NEW |