Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,273 @@
'use strict';
var AppStoragePanel = require('./regions/app_storage');
var AppPermissionPanel = require('./regions/app_permission');
var Base = require('./base');
var BatteryPanel = require('./regions/battery');
var BluetoothPanel = require('./regions/bluetooth');
var BrowsingPrivacyPanel = require('./regions/browsing_privacy');
var DateTimePanel = require('./regions/date_time');
var DeveloperPanel = require('./regions/developer');
var DeviceInfoPanel = require('./regions/device_info');
var DisplayPanel = require('./regions/display');
var DoNotTrackPanel = require('./regions/do_not_track');
var FeedbackPanel = require('./regions/feedback');
var HotspotPanel = require('./regions/hotspot');
var HotspotSettingsPanel = require('./regions/hotspot_settings');
var ImprovePanel = require('./regions/improve');
var KeyboardPanel = require('./regions/keyboard');
var LanguagePanel = require('./regions/language');
var MediaStoragePanel = require('./regions/media_storage');
var MessagePanel = require('./regions/message');
var NotificationsPanel = require('./regions/notifications');
var RootPanel = require('./regions/root');
var ScreenLockPanel = require('./regions/screen_lock');
var SoundPanel = require('./regions/sound');
var SupportPanel = require('./regions/support');
var UsbStoragePanel = require('./regions/usb_storage');
/**
* Abstraction around settings app
* @constructor
* @param {Marionette.Client} client for operations.
*/
function Settings(client) {
this.client = client;
// Call the Base constructor to initiate base class.
Base.call(this, this.client, Settings.ORIGIN, Settings.Selectors);
}
// origin of the settings app
Settings.ORIGIN = 'app://settings.gaiamobile.org';
module.exports = Settings;
Settings.Selectors = {
'menuItemsSection': '#root',
'appPermissionMenuItem': '#menuItem-appPermissions',
'appStorageMenuItem': '.menuItem-applicationStorage',
'batteryMenuItem': '.menuItem-battery',
'bluetoothMenuItem': '#menuItem-bluetooth',
'browsingPrivacyMenuItem': '#menuItem-browsingPrivacy',
'dateTimeMenuItem': '#menuItem-dateAndTime',
'developerMenuItem': '#menuItem-developer',
'deviceInfoMenuItem': '#menuItem-deviceInfo',
'displayMenuItem': '#menuItem-display',
'doNotTrackMenuItem': '#menuItem-doNotTrack',
'feedbackMenuItem': 'a[href="#improveBrowserOS-chooseFeedback"]',
'hotspotMenuItem': '#menuItem-internetSharing',
'hotspotPanel': '#hotspot',
'hotspotSettingsTrigger': '#hotspot-settings-section button',
'improveMenuItem': '#menuItem-improveBrowserOS',
'improveSection': '#improveBrowserOS',
'keyboardMenuItem': '#menuItem-keyboard',
'languageMenuItem': '.menuItem-languageAndRegion',
'mediaStorageMenuItem': '.menuItem-mediaStorage',
'messageMenuItem': '#menuItem-messagingSettings',
'notificationsMenuItem': '#menuItem-notifications',
'screenLockMenuItem': '#menuItem-screenLock',
'soundMenuItem': '#menuItem-sound',
'supportMenuItem': '#menuItem-help',
'usbStorageMenuItem': '.menuItem-enableStorage'
};
Settings.prototype = {
__proto__: Base.prototype,
get rootPanel() {
this._rootPanel = this._rootPanel ||
new RootPanel(this.client);
return this._rootPanel;
},
get bluetoothPanel() {
this.openPanel('bluetoothMenuItem');
this._bluetoothPanel = this._bluetoothPanel ||
new BluetoothPanel(this.client);
return this._bluetoothPanel;
},
get doNotTrackPanel() {
this.openPanel('doNotTrackMenuItem');
this._doNotTrackPanel = this._doNotTrackPanel ||
new DoNotTrackPanel(this.client);
return this._doNotTrackPanel;
},
get browsingPrivacyPanel() {
this.openPanel('browsingPrivacyMenuItem');
this._browsingPrivacyPanel = this._browsingPrivacyPanel ||
new BrowsingPrivacyPanel(this.client);
return this._browsingPrivacyPanel;
},
get hotspotPanel() {
this.openPanel('hotspotMenuItem');
this._hotspotPanel = this._hotspotPanel ||
new HotspotPanel(this.client);
return this._hotspotPanel;
},
get hotspotSettingsPanel() {
this.openPanel('hotspotSettingsTrigger', 'hotspotPanel');
this._hotspotSettingsPanel = this._hotspotSettingsPanel ||
new HotspotSettingsPanel(this.client);
return this._hotspotSettingsPanel;
},
get supportPanel() {
this.openPanel('supportMenuItem');
this._supportPanel = this._supportPanel ||
new SupportPanel(this.client);
return this._supportPanel;
},
get batteryPanel() {
this.openPanel('batteryMenuItem');
this._batteryPanel = this._batteryPanel ||
new BatteryPanel(this.client);
return this._batteryPanel;
},
get dateTimePanel() {
this.openPanel('dateTimeMenuItem');
this._dateTimePanel = this._dateTimePanel ||
new DateTimePanel(this.client);
return this._dateTimePanel;
},
get notificationsPanel() {
this.openPanel('notificationsMenuItem');
this._notificationsPanel = this._notificationsPanel ||
new NotificationsPanel(this.client);
return this._notificationsPanel;
},
get soundPanel() {
this.openPanel('soundMenuItem');
this._soundPanel = this._soundPanel ||
new SoundPanel(this.client);
return this._soundPanel;
},
get languagePanel() {
this.openPanel('languageMenuItem');
this._languagePanel = this._languagePanel ||
new LanguagePanel(this.client);
return this._languagePanel;
},
get screenLockPanel() {
this.openPanel('screenLockMenuItem');
this._screenLockPanel = this._screenLockPanel ||
new ScreenLockPanel(this.client);
return this._screenLockPanel;
},
get displayPanel() {
this.openPanel.call(this, 'displayMenuItem');
this._displayPanel = this._displayPanel ||
new DisplayPanel(this.client);
return this._displayPanel;
},
get improvePanel() {
this.openPanel.call(this, 'improveMenuItem');
this._improvePanel = this._improvePanel ||
new ImprovePanel(this.client);
return this._improvePanel;
},
get feedbackPanel() {
this.openPanel.call(this, 'feedbackMenuItem', 'improveSection');
this._feedbackPanel =
this._feedbackPanel || new FeedbackPanel(this.client);
return this._feedbackPanel;
},
get appPermissionPanel() {
this.openPanel.call(this, 'appPermissionMenuItem');
this._appPermissionPanel =
this._appPermissionPanel || new AppPermissionPanel(this.client);
return this._appPermissionPanel;
},
get appStoragePanel() {
this.openPanel.call(this, 'appStorageMenuItem');
this._appStoragePanel =
this._appStoragePanel || new AppStoragePanel(this.client);
return this._appStoragePanel;
},
get mediaStoragePanel() {
this.openPanel('mediaStorageMenuItem');
this._mediaStoragePanel = this._mediaStoragePanel ||
new MediaStoragePanel(this.client);
return this._mediaStoragePanel;
},
get keyboardPanel() {
this.openPanel('keyboardMenuItem');
this._keyboardPanel = this._keyboardPanel || new KeyboardPanel(this.client);
return this._keyboardPanel;
},
get messagePanel() {
this.openPanel('messageMenuItem');
this._messagePanel = this._messagePanel || new MessagePanel(this.client);
return this._messagePanel;
},
get aboutPanel() {
this.openPanel('deviceInfoMenuItem');
this._aboutPanel = this._aboutPanel ||
new DeviceInfoPanel(this.client);
return this._aboutPanel;
},
get developerPanel() {
this.openPanel('developerMenuItem');
this._developerPanel = this._developerPanel ||
new DeveloperPanel(this.client);
return this._developerPanel;
},
get usbStoragePanel() {
this.openPanel('usbStorageMenuItem');
this._usbStoragePanel = this._usbStoragePanel ||
new UsbStoragePanel(this.client);
return this._usbStoragePanel;
},
set currentLanguage(value) {
// open the language panel
var languagePanel = this.languagePanel;
languagePanel.currentLanguage = value;
languagePanel.back();
},
/**
* @private
*/
openPanel: function app_openPanel(selector, parentSelector) {
var localParentSelector = parentSelector || 'menuItemsSection';
var menuItem = this.waitForElement(selector);
var parentSection = this.waitForElement(localParentSelector);
// make sure it is enabled first
this.client.waitFor(function() {
return this.findElement('messageMenuItem').enabled();
}.bind(this));
menuItem.scriptWith(function(el) {
el.scrollIntoView(false);
});
menuItem.tap();
this.client.waitFor(function() {
var loc = parentSection.location();
var size = parentSection.size();
return Math.abs(loc.x) === size.width;
});
}
};

View file

@ -0,0 +1,89 @@
'use strict';
/**
* Base app object to provide common methods to app objects
* @constructor
* @param {Marionette.Client} client for operations.
*/
function Base(client, origin, selectors) {
this.client = client.scope({ searchTimeout: 20000 });
this.origin = origin;
this.selectors = selectors;
}
module.exports = Base;
Base.prototype = {
/**
* Launches settings app, switches to frame, and waits for it to be loaded.
*/
launch: function() {
this.client.apps.launch(this.origin);
this.client.apps.switchToApp(this.origin);
this.client.helper.waitForElement('body[data-ready="true"]');
},
/**
* Switches back to the current app frame.
* Useful when switching to system frame during test and needs to switch back.
*/
switchTo: function() {
this.client.switchToFrame();
this.client.apps.switchToApp(this.origin);
},
/**
* Close settings app.
*/
close: function() {
this.client.apps.close(this.origin);
},
/**
* @protected
* @param {String} name of selector [its a key in Settings.Selectors].
*/
findElement: function(name) {
return this.client.findElement(this.selectors[name]);
},
/**
* @protected
* @param {String} name of selector [its a key in Settings.Selectors].
*/
findElements: function(name) {
return this.client.findElements(this.selectors[name]);
},
/**
* @protected
* @param {String} name of selector [its a key in Settings.Selectors].
*/
waitForElement: function(name) {
var element = this.client.helper.waitForElement(this.selectors[name]);
this.client.waitFor(function() {
return element.scriptWith(function(el) {
var style = window.getComputedStyle(el);
return style.visibility === 'visible';
});
}.bind(this));
return element;
},
/**
* Use to select an options as currently we are not able to tap on a select
* element. Please refer to bug 977522 for details.
*
* @protected
* @param {String} name of selector [its a key in Settings.Selectors].
* @param {String} text content of an option
*/
tapSelectOption: function(name, optionText) {
this.client.helper.tapSelectOption(this.selectors[name], optionText);
},
tapConfirmButton: function() {
this.client.helper.waitForElement(
'#settings-confirm-dialog button[type="submit"]').tap();
}
};

View file

@ -0,0 +1,83 @@
'use strict';
var Base = require('./base');
/**
* Abstraction around keyboard app
* @constructor
* @param {Marionette.Client} client for operations.
*/
function KeyboardApp(client) {
Base.call(this, client, null, KeyboardApp.Selectors);
}
module.exports = KeyboardApp;
KeyboardApp.Selectors = {
'settingsHeader': '#general-header',
'vibrationCheckbox': '#cb-vibration'
};
KeyboardApp.SETTINGS_LAUNCH_PATH = 'app://keyboard.gaiamobile.org/' +
'settings.html';
KeyboardApp.prototype = {
__proto__: Base.prototype,
get vibrationFromMozSettings() {
return this.client.settings.get('keyboard.vibration');
},
switchToSettings: function() {
this.client.switchToFrame();
var settingsFrame = this.client.findElement(
'iframe[src*="' + KeyboardApp.SETTINGS_LAUNCH_PATH + '"]');
/**
* XXX: Workaround to wait for the frame is ready after switching to the
* keyboard app's settings page. We should use
* this.client.apps.switchToApp(KeyboardApp.SETTINGS_LAUNCH_PATH)
* instead of the logic below after Bug 1027994 is fixed.
*
* Add swithToApp waiting logic here, see Bug 1003788 for a similar
* technique we implemented in marionette-apps plugin.
*/
// Wait for the iframe is rendered.
this.client.waitFor(function() {
var frameClass = settingsFrame.scriptWith(function(el) {
return el.parentNode.getAttribute('class');
});
if (frameClass !== null) {
return frameClass.indexOf('render') !== -1;
} else {
return true;
}
});
// Wait for the iframe is displayed on screen.
this.client.waitFor(function() {
var transitionState = settingsFrame.scriptWith(function(el) {
return el.parentNode.getAttribute('transition-state');
});
if (transitionState !== null) {
return transitionState === 'opened';
} else {
return settingsFrame.displayed();
}
});
this.client.switchToFrame(settingsFrame);
},
clickVibrationOption: function() {
this.waitForElement('vibrationCheckbox').click();
},
goBackToSettingsApp: function() {
var header = this.waitForElement('settingsHeader');
header.tap(25, 25);
}
};

View file

@ -0,0 +1,55 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings app permission panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function AppPermissionPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, AppPermissionPanel.Selectors);
}
module.exports = AppPermissionPanel;
AppPermissionPanel.Selectors = {
'appListItem': '.app-list a',
'geolocationSelect': 'select[data-perm="geolocation"]',
'uninstallButton': '.uninstall-app > button'
};
AppPermissionPanel.prototype = {
__proto__: Base.prototype,
permissionTable: {
'Grant': 'allow'
},
get georlocationSelectValue() {
return this.findElement('geolocationSelect').getAttribute('value');
},
get appList() {
return this.findElements('appListItem');
},
get uninstallButton() {
return this.waitForElement('uninstallButton');
},
tapGeolocationSelect: function(value) {
this.tapSelectOption('geolocationSelect', value);
},
enterPermissionDetail: function() {
var entry = this.waitForElement('appListItem');
entry.tap();
this.client.waitFor(function() {
return this.findElement('geolocationSelect');
}.bind(this));
}
};

View file

@ -0,0 +1,44 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings app storage panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function AppStoragePanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, AppStoragePanel.Selectors);
}
function hasNumbers(t) {
return /\d/.test(t);
}
module.exports = AppStoragePanel;
AppStoragePanel.Selectors = {
'appTotalSpace': '.apps-total-space',
'appUsedSpace': '.apps-used-space',
'appFreeSpace': '.apps-free-space'
};
AppStoragePanel.prototype = {
__proto__: Base.prototype,
get containNumberInAppTotalSpace() {
return hasNumbers(this.waitForElement('appTotalSpace').text());
},
get containNumberInAppUsedSpace() {
return hasNumbers(this.waitForElement('appUsedSpace').text());
},
get containNumberInAppFreeSpace() {
return hasNumbers(this.waitForElement('appFreeSpace').text());
}
};

View file

@ -0,0 +1,61 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings battery panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function BatteryPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, BatteryPanel.Selectors);
}
module.exports = BatteryPanel;
BatteryPanel.Selectors = {
'powerSaveModeEnabledCheckbox': '#battery gaia-switch',
'threshold': 'select[name="powersave.threshold"]',
'option': 'option'
};
BatteryPanel.prototype = {
__proto__: Base.prototype,
get isPowerSavingEnabled() {
return this.findElement('powerSaveModeEnabledCheckbox')
.scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
get isLastOptionSelected() {
var options = this.findElements('option');
return options[options.length - 1].getAttribute('checked');
},
changeTurnOnPeriod: function() {
this.waitForElement('threshold').tap();
this.client.waitFor(function() {
return this.isLastOptionSelected;
}.bind(this));
},
enablePowerSaveMode: function() {
this.waitForElement('powerSaveModeEnabledCheckbox').click();
this.client.waitFor(function() {
return this.isPowerSavingEnabled;
}.bind(this));
},
disablePowerSaveMode: function() {
this.waitForElement('powerSaveModeEnabledCheckbox').click();
this.client.waitFor(function() {
return !this.isPowerSavingEnabled;
}.bind(this));
}
};

View file

@ -0,0 +1,47 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings bluetooth panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function BluetoothPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, BluetoothPanel.Selectors);
}
module.exports = BluetoothPanel;
BluetoothPanel.Selectors = {
'bluetoothEnabledCheckbox': '.bluetooth-status gaia-switch'
};
BluetoothPanel.prototype = {
__proto__: Base.prototype,
get isBluetoothEnabled() {
return this.findElement('bluetoothEnabledCheckbox')
.scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
enableBluetooth: function() {
this.waitForElement('bluetoothEnabledCheckbox').tap();
this.client.waitFor(function() {
return this.isBluetoothEnabled;
}.bind(this));
},
disableBluetooth: function() {
this.waitForElement('bluetoothEnabledCheckbox').tap();
this.client.waitFor(function() {
return !this.isBluetoothEnabled;
}.bind(this));
}
};

View file

@ -0,0 +1,115 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings browsing privacy panel.
* @constructor
* @param {Marionette.Client} client for operations.
*/
function BrowsingPrivacyPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, BrowsingPrivacyPanel.Selectors);
}
module.exports = BrowsingPrivacyPanel;
BrowsingPrivacyPanel.Selectors = {
'privateBrowsingSwitch':
'#browsingPrivacy gaia-switch[name="browser.private.default"]',
'trackingProtectionEnabledSwitch':
'#browsingPrivacy gaia-switch[name="privacy.trackingprotection.enabled"]',
'clearHistoryButton':
'#browsingPrivacy .clear-history-button',
'clearPrivateDataButton':
'#browsingPrivacy .clear-private-data-button',
'confirmDialog':
'#settings-confirm-dialog',
'confirmDialogCancel':
'#settings-confirm-dialog button[type="reset"]',
'confirmDialogSubmit':
'#settings-confirm-dialog button[type="submit"]'
};
BrowsingPrivacyPanel.prototype = {
__proto__: Base.prototype,
get isPrivateBrowsingEnabled() {
return this.findElement('privateBrowsingSwitch')
.scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
get isTrackingProtectionEnabled() {
return this.findElement('trackingProtectionEnabledSwitch')
.scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
get confirmDialogShown() {
return this.findElement('confirmDialog').displayed();
},
enablePrivateBrowsing: function() {
if (this.isPrivateBrowsingEnabled) {
return;
}
this.waitForElement('privateBrowsingSwitch').click();
this.client.waitFor(function() {
return this.isPrivateBrowsingEnabled;
}.bind(this));
},
enableTrackingProtection: function() {
if (this.isTrackingProtectionEnabled) {
return;
}
this.waitForElement('trackingProtectionEnabledSwitch').click();
this.client.waitFor(function() {
return this.isTrackingProtectionEnabled;
}.bind(this));
},
disableTrackingProtection: function() {
if (!this.isTrackingProtectionEnabled) {
return;
}
this.waitForElement('trackingProtectionEnabledSwitch').click();
this.client.waitFor(function() {
return !this.isTrackingProtectionEnabled;
}.bind(this));
},
clickClearHistoryButton: function() {
this.waitForElement('clearHistoryButton').click();
this.client.waitFor(function() {
return this.confirmDialogShown;
}.bind(this));
},
clickClearPrivateDataButton: function() {
this.waitForElement('clearPrivateDataButton').click();
this.client.waitFor(function() {
return this.confirmDialogShown;
}.bind(this));
},
clickConfirmDialogCancel: function() {
this.waitForElement('confirmDialogCancel').click();
this.client.waitFor(function() {
return !this.confirmDialogShown;
}.bind(this));
},
clickConfirmDialogSubmit: function() {
this.waitForElement('confirmDialogSubmit').click();
this.client.waitFor(function() {
return !this.confirmDialogShown;
}.bind(this));
}
};

View file

@ -0,0 +1,40 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings date time panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function DateTimePanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, DateTimePanel.Selectors);
}
module.exports = DateTimePanel;
DateTimePanel.Selectors = {
'timezoneRegion': '#dateTime .timezone-region',
'timezoneInfoText': '#dateTime .timezone-info-text',
'timeFormatSelect': '#dateTime .time-format-time'
};
DateTimePanel.prototype = {
__proto__: Base.prototype,
selectRegion: function(value) {
this.tapSelectOption('timezoneRegion', value);
},
selectTimeFormat: function(value) {
this.tapSelectOption('timeFormatSelect', value);
},
get timezoneInfoText() {
return this.waitForElement('timezoneInfoText').text();
}
};

View file

@ -0,0 +1,29 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings developer panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function DeveloperPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, DeveloperPanel.Selectors);
}
module.exports = DeveloperPanel;
DeveloperPanel.Selectors = {
'DeveloperPanel': '#developer'
};
DeveloperPanel.prototype = {
__proto__: Base.prototype,
get isDeveloperMenuItemVisible() {
return this.findElement('developerMenuItem').displayed();
}
};

View file

@ -0,0 +1,112 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings media storage panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function DeviceInfoPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, DeviceInfoPanel.Selectors);
}
module.exports = DeviceInfoPanel;
DeviceInfoPanel.Selectors = {
'moreInfoBtn': '#about a[href="#about-moreInfo"]',
'yourRightsBtn': '#about a[href="#about-yourRights"]',
'yourPrivacyBtn': '#about a[href="#about-yourPrivacy"]',
'legalInfoBtn': '#about a[href="#about-legal"]',
'resetPhoneBtn': '#about button.reset-phone',
'resetPhoneDialog': '.reset-phone-dialog',
'cancelResetPhoneBtn': '.cancel-reset-phone',
'developerMenuCheckbox': 'gaia-switch[name="developer.menu.enabled"]',
'openSourceNoticesLink': 'a[href="#about-licensing"]',
'obtainingSourceCodeLink': 'a[href="#about-source-code"]',
'privacyLink': 'a.privacy-browserOS',
'developerMenuItem': 'li > #menuItem-developer',
'aboutPanel': '#about',
'rootPanel': '#root',
'deviceInfoBackBtn': '#about gaia-header',
'moreInfoBackBtn': '#about-moreInfo gaia-header',
'openSourceNoticesBackBtn': '#about-licensing gaia-header'
};
DeviceInfoPanel.prototype = {
__proto__: Base.prototype,
tapOnResetPhoneButton: function() {
this.waitForElement('resetPhoneBtn').tap();
},
tapOnCancelResetPhoneButton: function() {
this.waitForElement('cancelResetPhoneBtn').tap();
},
get isResetPhoneDialogVisible() {
return this.findElement('resetPhoneDialog').displayed();
},
tapOnMoreInfoButton: function() {
this.waitForElement('moreInfoBtn').tap();
},
tapOnYourRightsButton: function() {
this.waitForElement('yourRightsBtn').tap();
},
tapOnYourPrivacyButton: function() {
this.waitForElement('yourPrivacyBtn').tap();
},
tapOnPrivacyBrowserButton: function() {
this.waitForElement('privacyLink').tap();
},
tapOnLegalInfoButton: function() {
this.waitForElement('legalInfoBtn').tap();
},
tapOnOpenSourceNoticesButton: function() {
this.waitForElement('openSourceNoticesLink').tap();
},
tapOnObtainingSourceCodeButton: function() {
this.waitForElement('obtainingSourceCodeLink').tap();
},
triggerDevelopMenu: function() {
this.waitForElement('developerMenuCheckbox').click();
this.client.waitFor(function() {
return this.isDevelopMenuEnabled;
}.bind(this));
},
get isDevelopMenuEnabled() {
return this.findElement('developerMenuCheckbox')
.scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
get isDeveloperMenuItemVisible() {
return this.findElement('developerMenuItem').displayed();
},
tapDeviceInfoBackBtn: function() {
this.client.helper.wait(300);
this.waitForElement('deviceInfoBackBtn').tap(25, 25);
},
tapMoreInfoBackBtn: function() {
this.client.helper.wait(300);
this.waitForElement('moreInfoBackBtn').tap(25, 25);
},
tapOpenSourceNoticesBackBtn: function() {
this.waitForElement('openSourceNoticesBackBtn').tap(25, 25);
}
};

View file

@ -0,0 +1,85 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings display panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function DisplayPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, DisplayPanel.Selectors);
}
module.exports = DisplayPanel;
DisplayPanel.Selectors = {
'lockOrientationCheckbox':
'#display gaia-switch[name="screen.orientation.lock"]',
'autoBrightnessItem': '.brightness-auto',
'autoBrightnessCheckbox':
'#display gaia-checkbox[name="screen.automatic-brightness"]',
'manualBrightnessItem': '.brightness-manual',
'screenTimeoutSelectorItem': '#screen-timeout',
'screenTimeoutSelector': '#screen-timeout select'
};
DisplayPanel.prototype = {
__proto__: Base.prototype,
get isLockOrientationChecked() {
// Marionette has trouble returning custom properties on shadow roots.
// For now query the shadowRoot for checked status.
return this.findElement('lockOrientationCheckbox')
.scriptWith(function(el) {
return el.shadowRoot.querySelector('input[type="checkbox"]').checked;
});
},
get isAutoBrightnessChecked() {
return !!this.findElement('autoBrightnessCheckbox')
.scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
get isAutoBrightnessItemVisible() {
return this.findElement('autoBrightnessItem').displayed();
},
get isBrightnessManualItemVisible() {
return this.findElement('manualBrightnessItem').displayed();
},
get autoBrightnessSetting() {
return this.client.settings.get('screen.automatic-brightness');
},
get screenOrientationSetting() {
return this.client.settings.get('screen.orientation.lock');
},
get screenTimeoutSetting() {
return this.client.settings.get('screen.timeout');
},
tapLockOrientationCheckbox: function() {
this.waitForElement('lockOrientationCheckbox').tap();
},
tapAutoBrightnessCheckbox: function() {
this.waitForElement('autoBrightnessCheckbox').tap();
},
tapScreenTimeoutSelector: function() {
this.waitForElement('screenTimeoutSelectorItem').tap();
},
tapScreenTimeoutSelectOption: function(optionText) {
this.tapSelectOption('screenTimeoutSelector', optionText);
}
};

View file

@ -0,0 +1,47 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings do not track panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function DoNotTrackPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, DoNotTrackPanel.Selectors);
}
module.exports = DoNotTrackPanel;
DoNotTrackPanel.Selectors = {
'doNotTrackEnabledCheckbox': '#doNotTrack gaia-radio'
};
DoNotTrackPanel.prototype = {
__proto__: Base.prototype,
get isDoNotTrackEnabled() {
return this.findElement('doNotTrackEnabledCheckbox')
.scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
enableDoNotTrack: function() {
this.waitForElement('doNotTrackEnabledCheckbox').click();
this.client.waitFor(function() {
return this.isDoNotTrackEnabled;
}.bind(this));
},
disableDoNotTrack: function() {
this.waitForElement('doNotTrackEnabledCheckbox').click();
this.client.waitFor(function() {
return !this.isDoNotTrackEnabled;
}.bind(this));
}
};

View file

@ -0,0 +1,98 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings improve panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function FeedbackPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, FeedbackPanel.Selectors);
}
module.exports = FeedbackPanel;
FeedbackPanel.Selectors = {
'feedbackPanel': '#improveBrowserOS-chooseFeedback',
'feedbackHappy': '#feedback-happy',
'feedbackSad': '#feedback-sad',
'sendFeedbackPanel': '#improveBrowserOS-sendFeedback',
'chooseFeedbackPanel': '#improveBrowserOS-chooseFeedback',
'feedbackDiscription': '#feedback-description',
'feedbackEmailEnable': '#feedback-contactyou',
'emailEnable': 'span[data-l10n-id="feedback-contactyou"]',
'feedbackEmail': '#feedback-email',
'feedbackEmailBar': '#feedback-emailbar',
'sendFeedbackButton': '#feedback-send-btn',
'alertDialogMsg': '#settings-alert-dialog.current .settings-dialog-message',
'feedbackBackButton': '#feedback-back-button'
};
FeedbackPanel.prototype = {
__proto__: Base.prototype,
get alertMsg() {
return this.waitForElement('alertDialogMsg').text();
},
get discription() {
return this.waitForElement('feedbackDiscription')
.getAttribute('value');
},
isRendered: function() {
this.client.waitFor(function() {
return this.waitForElement('feedbackPanel')
.getAttribute('data-rendered') === 'true';
}.bind(this));
},
tapFeedbackBack: function() {
this.waitForElement('feedbackBackButton').tap();
this.client.waitFor(function() {
return this.waitForElement('feedbackHappy').displayed();
}.bind(this));
},
enterWithHappy: function() {
this.waitForElement('feedbackHappy').tap();
this.sendFeedbackPanelDisplay();
},
enterWithSad: function() {
this.waitForElement('feedbackSad').tap();
this.sendFeedbackPanelDisplay();
},
sendFeedbackPanelDisplay: function() {
var chooseFeedbackPanel =
this.waitForElement('chooseFeedbackPanel');
this.client.waitFor(function() {
return chooseFeedbackPanel.location().x +
chooseFeedbackPanel.size().width === 0;
});
},
sendFeedback: function() {
this.waitForElement('sendFeedbackButton').tap();
},
openEmailCol: function() {
this.findElement('feedbackEmailEnable').click();
this.client.waitFor(function() {
var value = this.findElement('feedbackEmailBar').
getAttribute('hidden');
return value === 'false';
}.bind(this));
},
inputMsgToDialog: function(text) {
var ele = this.waitForElement('feedbackDiscription');
ele.sendKeys(text);
}
};

View file

@ -0,0 +1,25 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings hotspot panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function HotspotPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, HotspotPanel.Selectors);
}
module.exports = HotspotPanel;
HotspotPanel.Selectors = {
};
HotspotPanel.prototype = {
__proto__: Base.prototype
};

View file

@ -0,0 +1,50 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around hotspot settings panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function HotspotSettingsPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, HotspotSettingsPanel.Selectors);
}
module.exports = HotspotSettingsPanel;
HotspotSettingsPanel.Selectors = {
'body': 'body',
'hotspotSettingsPanel': '#hotspot-wifiSettings',
'hotspotSettingsNetworkName': 'input[data-setting="tethering.wifi.ssid"]',
'hotspotSettingsBack': '#hotspot-wifiSettings button[type="reset"]'
};
HotspotSettingsPanel.prototype = {
__proto__: Base.prototype,
get ssid() {
return this.findElement('hotspotSettingsNetworkName')
.getAttribute('value');
},
set ssid(value) {
return this.findElement('hotspotSettingsNetworkName')
.sendKeys(value);
},
back: function() {
var parentSection = this.waitForElement('hotspotSettingsPanel');
this.findElement('hotspotSettingsBack').tap();
var bodyWidth = this.findElement('body').size().width;
this.client.waitFor(function() {
var loc = parentSection.location();
return loc.x >= bodyWidth;
});
}
};

View file

@ -0,0 +1,70 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings improve panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function ImprovePanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, ImprovePanel.Selectors);
}
module.exports = ImprovePanel;
ImprovePanel.Selectors = {
'feedbackEntryButton':
'#improveBrowserOS-chooseFeedback',
'alwaysSendReport':
'#menuItem-alwaysSendReport gaia-radio',
'neverSendReport':
'#menuItem-neverSendReport gaia-radio',
'askEachTime':
'#menuItem-askToSendReport2 gaia-radio',
'reportCrashes':
'gaia-radio[name="app.reportCrashes"]'
};
ImprovePanel.prototype = {
__proto__: Base.prototype,
selectedReport: function(type) {
this.client.waitFor(function() {
var eles = this.findElements('reportCrashes');
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
if (ele.getAttribute('checked') &&
(ele.getAttribute('value') === type)) {
return true;
}
}
}.bind(this));
},
enableNeverSendReport: function() {
this.waitForElement('neverSendReport').tap();
this.selectedReport('never');
},
enableAskEachTime: function() {
this.waitForElement('askEachTime').tap();
this.selectedReport('ask');
},
enableAlwaysSendReport: function() {
this.waitForElement('alwaysSendReport').tap();
this.selectedReport('always');
},
enterFeedbackPanel: function() {
this.waitForElement('feedbackEntryButton').tap();
}
};

View file

@ -0,0 +1,62 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings keyboard panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function KeyboardPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, KeyboardPanel.Selectors);
}
module.exports = KeyboardPanel;
KeyboardPanel.Selectors = {
keyboardList: '.allKeyboardList li',
header: '#keyboard gaia-header',
panel: '#keyboard',
selectKeyboards: '#keyboard a[href="#keyboard-selection-addMore"]',
builtinKeyboardList: '#keyboard-selection-addMore .keyboardAppContainer ul',
backButton: '#keyboard-selection-addMore gaia-header'
};
KeyboardPanel.prototype = {
__proto__: Base.prototype,
get header() {
return this.findElement('header');
},
tapBuiltInKeyboardItem: function() {
this.waitForElement('keyboardList').tap();
},
tapSelectKeyboards: function() {
this.waitForElement('selectKeyboards').tap();
},
selectLayout: function(layoutLabel) {
var builtinKeyboardList = this.waitForElement('builtinKeyboardList');
var layout = builtinKeyboardList.scriptWith(function(list, layoutLabel) {
var langs = list.querySelectorAll('bdi');
return [].filter.call(langs, function(lang) {
return (lang.innerHTML === layoutLabel);
})[0];
}, [layoutLabel]);
layout.tap();
},
tapBackButton: function() {
var header = this.waitForElement('backButton');
header.tap(25, 25);
},
isDialog: function() {
var dialogAttribute =
this.findElement('panel').getAttribute('data-dialog');
return dialogAttribute === 'true';
}
};

View file

@ -0,0 +1,134 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings do not track panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function LanguagePanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, LanguagePanel.Selectors);
}
module.exports = LanguagePanel;
LanguagePanel.Selectors = {
'languagePanel': '#languages',
'body': 'body',
'header': 'gaia-header',
'languageChangeSelect': '#languages select[name="language.current"]',
'languageLabel': 'p[data-l10n-id="language"]',
'languageRegionDateLabel': '#region-date'
};
LanguagePanel.prototype = {
__proto__: Base.prototype,
// The \u202a, \u202b and \u202c are special Unicode formatting codes which
// force the direction of the text between them. They are added by
// LanguageList.wrapBidi to ensure proper display of all language names.
_languageMap: {
english: {
label: 'Language',
desc: '\u202aEnglish (US)\u202c',
dayRules: /Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday/
},
accented: {
label: 'Ŀȧȧƞɠŭŭȧȧɠḗḗ',
desc: '\u202aƤȧȧƈķȧȧɠḗḗḓ Ȧȧƈƈḗḗƞŧḗḗḓ\u202c',
dayRules: new RegExp(
'lundi|' +
'mardi|' +
'mercredi|' +
'jeudi|' +
'vendredi|' +
'samedi|' +
'dimanche')
},
bidi: {
label: '\u202e˥ɐuƃnɐƃǝ\u202c',
desc: '\u202b\u202eԀɐɔʞɐƃǝp\u202c \u202eԐıpı\u202c\u202c',
dayRules: new RegExp(
'الاثنين|' +
'الثلاثاء|' +
'الأربعاء|' +
'الخميس|' +
'الجمعة|' +
'السبت|' +
'الأحد')
}
},
get regionDateLabel() {
return this.findElement('languageRegionDateLabel').text();
},
get currentLanguageFromMozSettings() {
return this.client.settings.get('language.current');
},
get currentLanguageLabel() {
return this.findElement('languageLabel').text();
},
get currentLanguage() {
var languageLabel = this.currentLanguageLabel;
var realLanguage;
for (var languageKey in this._languageMap) {
if (this._languageMap[languageKey].label === languageLabel) {
realLanguage = languageKey;
break;
}
}
return realLanguage;
},
set currentLanguage(value) {
if (this._languageMap[value]) {
var oldLanguage = this.currentLanguage;
this.tapSelectOption('languageChangeSelect',
this._languageMap[value].desc);
this.client.waitFor(function() {
var newLanguage = this.currentLanguage;
return oldLanguage !== newLanguage;
}.bind(this));
}
},
setupDefaultLanguage: function() {
if (this.currentLanguage !== 'english') {
this.currentLanguage = 'english';
}
},
isSampleFormatTranslated: function(languageKey) {
if (this._languageMap[languageKey]) {
var rule = this._languageMap[languageKey].dayRules;
if (this.regionDateLabel.match(rule)) {
return true;
}
}
return false;
},
back: function() {
var parentSection = this.waitForElement('languagePanel');
var bodyWidth = this.findElement('body').size().width;
this.client.switchToShadowRoot(this.findElement('header'));
this.client.findElement('[action="back"] button').tap();
this.client.switchToShadowRoot();
this.client.waitFor(function() {
var loc = parentSection.location();
return Math.abs(loc.x) >= bodyWidth;
});
}
};

View file

@ -0,0 +1,73 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings media storage panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function MediaStoragePanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, MediaStoragePanel.Selectors);
}
function hasNumbers(t) {
return /\d/.test(t);
}
module.exports = MediaStoragePanel;
MediaStoragePanel.Selectors = {
'formatSdcardButton':
'#mediaStorage button[data-l10n-id="format-sdcard-external-0"]',
'formatSdcardDialog': '#format-sdcard-dialog',
'mediaLocationSelector':
'#mediaStorage select[name="device.storage.writable.name"]',
'musicSpace': 'a[data-l10n-id="music-space"]>span',
'pictureSpace': 'a[data-l10n-id="pictures-space"]>span',
'videoSpace': 'a[data-l10n-id="videos-space"]>span',
'mediaFreeSpace': 'a[data-l10n-id="free-space"]>span',
'mediaTotalSpace': 'a[data-l10n-id="total-space"]>span'
};
MediaStoragePanel.prototype = {
__proto__: Base.prototype,
tapOnFormatSdcardButton: function() {
this.waitForElement('formatSdcardButton').tap();
},
get isFormatSdcardDialogShowed() {
return this.findElement('formatSdcardDialog')
.getAttribute('hidden');
},
get isMediaLocationSelectorEnabled() {
return !this.findElement('mediaLocationSelector')
.getAttribute('disabled');
},
get containNumberInMusicSpace() {
return hasNumbers(this.waitForElement('musicSpace').text());
},
get containNumberInPictureSpace() {
return hasNumbers(this.waitForElement('pictureSpace').text());
},
get containNumberInVideoSpace() {
return hasNumbers(this.waitForElement('videoSpace').text());
},
get containNumberInFreeSpace() {
return hasNumbers(this.waitForElement('mediaFreeSpace').text());
},
get containNumberInTotalSpace() {
return hasNumbers(this.waitForElement('mediaTotalSpace').text());
}
};

View file

@ -0,0 +1,166 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings do not track panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function MessagePanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, MessagePanel.Selectors);
}
module.exports = MessagePanel;
MessagePanel.Selectors = {
'deliveryReportMenuItem': '#menuItem-deliveryReport span',
'deliveryReportCheckbox': '#menuItem-deliveryReport input[type="checkbox"]',
'readReportMenuItem': '#menuItem-readReport span',
'readReportCheckbox': '#menuItem-readReport input[type="checkbox"]',
'wapPushMenuItem': '#menuItem-wapPush',
'wapPushCheckbox': '#menuItem-wapPush input[type="checkbox"]',
'cellBroadcastMenuItem': '#menuItem-cellBroadcast',
'cellBroadcastCheckbox': '#menuItem-cellBroadcast gaia-checkbox',
'emergencyAlertMenuItem': '#menuItem-emergencyAlert',
'emergencyAlertCheckbox': '#menuItem-emergencyAlert gaia-checkbox',
'retrieveSelect': 'select[name="ril.mms.retrieval_mode"]',
'messageContentDiv': '#messaging > div'
};
MessagePanel.prototype = {
__proto__: Base.prototype,
settingsKeys: [
'ril.sms.requestStatusReport.enabled',
'ril.mms.requestReadReport.enabled',
'wap.push.enabled',
'ril.cellbroadcast.disabled',
'cmas.enabled'
],
checkboxes: [
'deliveryReportCheckbox',
'readReportCheckbox',
'wapPushCheckbox',
'cellBroadcastCheckbox',
'emergencyAlertCheckbox'
],
menuItems: [
'deliveryReportMenuItem',
'readReportMenuItem',
'wapPushMenuItem',
'cellBroadcastMenuItem',
'emergencyAlertMenuItem'
],
get deliveryReportMenuItem() {
return this.findElement('deliveryReportMenuItem');
},
get deliveryReportCheckbox() {
return this.findElement('deliveryReportCheckbox');
},
get readReportMenuItem() {
return this.findElement('readReportMenuItem');
},
get readReportCheckbox() {
return this.findElement('readReportCheckbox');
},
get wapPushMenuItem() {
return this.findElement('wapPushMenuItem');
},
get wapPushCheckbox() {
return this.findElement('wapPushCheckbox');
},
get cellBroadcastMenuItem() {
return this.findElement('cellBroadcastMenuItem');
},
get cellBroadcastCheckbox() {
return this.findElement('cellBroadcastCheckbox');
},
get emergencyAlertMenuItem() {
return this.findElement('emergencyAlertMenuItem');
},
get emergencyAlertCheckbox() {
return this.findElement('emergencyAlertCheckbox');
},
get isEmergencyAlertCheckboxEnabled() {
return !this.findElement('emergencyAlertCheckbox')
.getAttribute('disabled');
},
get messageContentDiv() {
return this.findElement('messageContentDiv');
},
chooseRetrieveMethod: function(optionText) {
this.tapSelectOption('retrieveSelect', optionText);
},
getSelectedRetrieveMethod: function() {
return this.client.settings.get('ril.mms.retrieval_mode');
},
initialMessagingSettings: function() {
this._resetCheckboxes();
this._resetSelect();
this._scrollMessageContentToTop();
},
toggleMenuItem: function(menuItemName, value) {
var checked = !!this[menuItemName + 'Checkbox'].getAttribute('checked');
if (checked !== value) {
this[menuItemName + 'MenuItem'].tap();
}
},
isChecked: function(elementName) {
return !!this.findElement(elementName).getAttribute('checked');
},
/**
* Returns the checked status of a web component.
* We need to execute script because the custom attribute does not
* work in marionette.
*/
isComponentChecked: function(elementName) {
return !!this.findElement(elementName).scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
_resetSelect: function() {
this.chooseRetrieveMethod('Off');
},
_resetCheckboxes: function() {
var self = this;
this._scrollMessageContentToTop();
this.checkboxes.forEach(function(checkbox, index) {
var checked = !!self[checkbox].getAttribute('checked');
if (checked) {
var menuItemKey = self.menuItems[index];
self[menuItemKey].tap();
}
});
},
_scrollMessageContentToTop: function() {
// it seems that the screen will scroll to bottom sometimes
this.messageContentDiv.scriptWith(function(el) {
el.scrollTop = 0;
});
}
};

View file

@ -0,0 +1,36 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings notification panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function NotificationsPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, NotificationsPanel.Selectors);
}
module.exports = NotificationsPanel;
NotificationsPanel.Selectors = {
'showOnLockScreenCheckbox': '#notifications gaia-switch'
};
NotificationsPanel.prototype = {
__proto__: Base.prototype,
get isShowOnLockScreenEnabled() {
return this.findElement('showOnLockScreenCheckbox')
.getAttribute('checked') &&
this.client.settings.get('lockscreen.notifications-preview.enabled');
},
tapOnShowOnLockScreen: function() {
this.waitForElement('showOnLockScreenCheckbox').click();
}
};

View file

@ -0,0 +1,174 @@
'use strict';
var Base = require('../base');
var LanguagePanel = require('./language');
/**
* Abstraction around settings root panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function RootPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, RootPanel.Selectors);
}
module.exports = RootPanel;
RootPanel.Selectors = {
'airplaneModeCheckbox': '.airplaneMode-input',
'airplaneModeMenuItem': '#menuItem-airplaneMode',
'applicationStorageDesc': '.application-storage-desc',
'batteryDesc': '.battery-desc',
'bluetoothDesc': '.bluetooth-desc',
'firefoxAccountDesc': '#fxa-desc',
'geolocationCheckbox': 'gaia-switch[name="geolocation.enabled"]',
'languageDesc': '.language-desc',
'mediaStorageDesc': '.media-storage-desc',
'simManagerItem': '#simCardManager-settings',
'simSecurityItem': '#simSecurity-settings',
'screenLockDesc': '.screenLock-desc',
'wifiDesc': '#wifi-desc',
'nfcCheckbox': '#nfc-input'
};
RootPanel.prototype = {
__proto__: Base.prototype,
// application storage
get applicationStorageDesc() {
return this.waitForElement('applicationStorageDesc').text();
},
// airplane mode
airplaneMode: function(enabled) {
var self = this;
this.client.waitFor(function() {
return self.airplaneModeCheckboxEnabled;
});
if (enabled !== this.airplaneModeCheckboxChecked) {
this.waitForElement('airplaneModeCheckbox').click();
this.client.waitFor(function() {
return enabled === self.airplaneModeCheckboxChecked;
});
}
// make sure we would wait for two more status here
if (enabled === true) {
this.client.waitFor(function() {
return self.WiFiDesc === 'Disabled';
});
this.client.waitFor(function() {
return self.bluetoothDesc === 'Turned off';
});
}
},
get airplaneModeCheckboxChecked() {
return !!this.findElement('airplaneModeCheckbox').scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
get airplaneModeCheckboxEnabled() {
return this.findElement('airplaneModeCheckbox').scriptWith(function(el) {
return !el.wrappedJSObject.hasAttribute('disabled');
});
},
// battery
get batteryDesc() {
return this.waitForElement('batteryDesc').text();
},
// bluetooth
get bluetoothDesc() {
return this.waitForElement('bluetoothDesc').text();
},
// firefox account
get firefoxAccountDesc() {
return this.waitForElement('firefoxAccountDesc').text();
},
// geolocation
geolocation: function(enabled) {
if (enabled !== this.geolocationCheckboxChecked) {
this.waitForElement('geolocationCheckbox').tap();
this.client.waitFor(function() {
return enabled === this.geolocationCheckboxChecked;
}.bind(this));
}
},
get geolocationCheckboxChecked() {
return !!this.findElement('geolocationCheckbox').scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
get geolocationEnabledSetting() {
return this.client.settings.get('geolocation.enabled');
},
get wifiEnabledSetting() {
return this.client.settings.get('wifi.enabled');
},
get bluetoothEnabledSetting() {
return this.client.settings.get('bluetooth.enabled');
},
get nfcCheckboxChecked() {
return !!this.findElement('nfcCheckbox').scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
// language
isLanguageDescTranslated: function(languageKey) {
if (!LanguagePanel.prototype._languageMap[languageKey]) {
return false;
}
var expected;
this.client.waitFor(function() {
expected = LanguagePanel.prototype._languageMap[languageKey].desc;
return this.languageDesc === expected;
}.bind(this));
return true;
},
get languageDesc() {
return this.findElement('languageDesc').text();
},
// media storage
get mediaStorageDesc() {
return this.waitForElement('mediaStorageDesc').text();
},
// screen lock
get screenLockDesc() {
return this.waitForElement('screenLockDesc').text();
},
// wifi
get WiFiDesc() {
return this.waitForElement('wifiDesc').text();
},
// sim manager
get isSimManagerItemVisible() {
return this.findElement('simManagerItem').displayed();
},
get isSimSecurityItemVisible() {
return this.findElement('simSecurityItem').displayed();
}
};

View file

@ -0,0 +1,150 @@
/* global require, module */
'use strict';
var Base = require('../base');
/**
* Abstraction around settings screenLock panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function ScreenLockPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, ScreenLockPanel.Selectors);
}
module.exports = ScreenLockPanel;
ScreenLockPanel.Selectors = {
'screenLockLabel': 'label[data-l10n-id="lockScreen"]',
'screenLockCheckbox': '.lockscreen-enable',
'header': 'gaia-header',
'passcodeLockLabel': 'label[data-l10n-id="passcode-lock"]',
'passcodeInput': '.passcode-input',
'passcodeCheckbox': '.passcode-enable',
'passcodeIsNotMatchedLabel': 'div[data-l10n-id="passcode-doesnt-match"]',
'passcodeIncorrectLabel': 'div[data-l10n-id="incorrect-passcode"]',
'passcodeCreateButton': 'button[type="submit"]',
'passcodeEditButton': '.passcode-edit',
'passcodeChangeButton': 'button[type="submit"]',
'passcodePanel': '#screenLock-passcode',
'screenLockHeaderLabel': 'h1[data-l10n-id="screenLock-header"]'
};
ScreenLockPanel.prototype = {
__proto__: Base.prototype,
isScreenLockEnabled: function() {
return this.client.settings.get('lockscreen.enabled');
},
isScreenLockChecked: function() {
return !!this.findElement('screenLockCheckbox').scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
isPasscodeLockEnabled: function() {
return this.client.settings.get('lockscreen.passcode-lock.enabled');
},
isPasscodeChecked: function() {
return !!this.findElement('passcodeCheckbox').scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
isPasscodeNotMatched: function() {
return this.findElement('passcodeIsNotMatchedLabel').displayed();
},
isPasscodeIncorrect: function() {
return this.findElement('passcodeIncorrectLabel').displayed();
},
isPasscodePanelVisible: function() {
return this.findElement('passcodePanel').displayed();
},
isScreenLockHeaderLabelVisible: function() {
return this.findElement('screenLockHeaderLabel').displayed();
},
enableScreenLock: function() {
this.waitForElement('screenLockLabel').tap();
this.client.waitFor(function() {
return this.isScreenLockEnabled();
}.bind(this));
},
setupScreenLock: function() {
// make sure we are at the root panel at first
if (this.isPasscodePanelVisible()) {
this.tapBackButton();
}
// we have to make sure screenLock is disabled by default
if (!this.isScreenLockEnabled()) {
return;
}
// if we have passcode by default, then there is a popup
// when disabling screenLock, in this way, we have to
// type the correct code to disable passcodeLock at first
if (this.isPasscodeLockEnabled()) {
var code = this.getPasscode();
this.togglePasscodeLock();
this.typePasscode(code);
}
// then we can disable screenLock
this.toggleScreenLock();
},
toggleScreenLock: function() {
this.waitForElement('screenLockLabel').tap();
},
togglePasscodeLock: function() {
this.waitForElement('passcodeLockLabel').tap();
},
_typePasscode: function(keys) {
this.waitForElement('passcodeInput').sendKeys(keys);
},
typePasscode: function(key1, key2) {
if (key1) {
this._typePasscode(key1);
if (key2) {
this._typePasscode(key2);
}
}
},
tapBackButton: function() {
this.waitForElement('header').tap(25, 25);
},
tapCreatePasscode: function() {
this.waitForElement('passcodeCreateButton').tap();
// we have to make sure transition is done
this.client.waitFor(function() {
return this.isScreenLockHeaderLabelVisible();
}.bind(this));
},
tapEditPasscode: function(keys) {
this.waitForElement('passcodeEditButton').tap();
if (keys) {
this._typePasscode(keys);
}
},
tapChangePasscode: function() {
this.waitForElement('passcodeChangeButton').tap();
}
};

View file

@ -0,0 +1,145 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings sound panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function SoundPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, SoundPanel.Selectors);
}
module.exports = SoundPanel;
SoundPanel.Selectors = {
'vibrateCheckbox': '#sound gaia-switch[name="vibration.enabled"]',
'mediaSlider': '#sound .media input',
'ringerSlider': '#sound .notification input',
'alarmSlider': '#sound .alarm input',
'keypadCheckbox': '#sound [name="phone.ring.keypad"]',
'cameraCheckbox': '#sound [name="camera.sound.enabled"]',
'sentMessageCheckbox':
'#sound [name="message.sent-sound.enabled"]',
'unlockScreenCheckbox':
'#sound [name="lockscreen.unlock-sound.enabled"]',
'alerttoneButton': '.alert-tone-selection',
'alerttoneButtonDesc': '.alert-tone-selection .desc',
'ringtoneButton': '.ring-tone-selection',
'ringtoneButtonDesc': '.ring-tone-selection .desc',
'manageTonesButton': '.manage-tones-button'
};
SoundPanel.prototype = {
__proto__: Base.prototype,
isGaiaCheckboxChecked: function(selector) {
return this.findElement(selector).scriptWith(function(el) {
return el.wrappedJSObject.checked;
});
},
get isVibrateEnabled() {
return this.findElement('vibrateCheckbox')
.getAttribute('checked') &&
this.client.settings.get('vibration.enabled');
},
tapOnVibration: function() {
this.waitForElement('vibrateCheckbox').tap();
},
/* Volume */
get contentValue() {
return this.client.settings.get('audio.volume.content');
},
tapOnMediaSlider: function() {
this.waitForElement('mediaSlider').tap();
},
get ringerValue() {
return this.client.settings.get('audio.volume.notification');
},
tapOnRingerSlider: function() {
this.waitForElement('ringerSlider').tap();
},
get alarmValue() {
return this.client.settings.get('audio.volume.alarm');
},
tapOnAlarmSlider: function() {
this.waitForElement('alarmSlider').tap();
},
/* Other sounds */
get isKeypadChecked() {
return this.isGaiaCheckboxChecked('keypadCheckbox') &&
this.client.settings.get('phone.ring.keypad');
},
tapOnKeypad: function() {
this.waitForElement('keypadCheckbox').tap();
},
get isCameraChecked() {
return this.isGaiaCheckboxChecked('cameraCheckbox') &&
this.client.settings.get('camera.sound.enabled');
},
tapOnCamera: function() {
this.waitForElement('cameraCheckbox').tap();
},
get isSentMessageChecked() {
return this.isGaiaCheckboxChecked('sentMessageCheckbox') &&
this.client.settings.get('message.sent-sound.enabled');
},
tapOnSentMessage: function() {
this.waitForElement('sentMessageCheckbox').tap();
},
get isUnlockScreenChecked() {
return this.isGaiaCheckboxChecked('unlockScreenCheckbox') &&
this.client.settings.get('message.sent-sound.enabled');
},
tapOnUnlockScreen: function() {
this.waitForElement('unlockScreenCheckbox').tap();
},
clickRingToneSelect: function() {
this.waitForElement('ringtoneButton').tap();
},
clickAlertToneSelect: function() {
this.waitForElement('alerttoneButton').tap();
},
clickManageTones: function() {
this.waitForElement('manageTonesButton').tap();
},
get selectedRingtone() {
return this.waitForElement('ringtoneButtonDesc').text();
},
get selectedAlertTone() {
return this.waitForElement('alerttoneButtonDesc').text();
},
getSelectedTone: function(type) {
if (type === 'ringtone') {
return this.selectedRingtone;
} else if (type === 'alerttone') {
return this.selectedAlertTone;
}
}
};

View file

@ -0,0 +1,50 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings support panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function SupportPanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, SupportPanel.Selectors);
}
module.exports = SupportPanel;
SupportPanel.Selectors = {
'onlineSupport': '#online-support-text [href]',
'callSupports': '#call-support-numbers [href]'
};
SupportPanel.prototype = {
__proto__: Base.prototype,
get isOnlineSupportEnabled() {
var retval = false;
try {
this.onlineSupport;
retval = true;
} catch (ex) {
retval = false;
}
return retval;
},
get isCallSupportEnabled() {
return this.callSupports.length > 0;
},
get onlineSupport() {
return this.findElement('onlineSupport');
},
get callSupports() {
return this.findElements('callSupports');
}
};

View file

@ -0,0 +1,42 @@
'use strict';
var Base = require('../base');
/**
* Abstraction around settings bluetooth panel
* @constructor
* @param {Marionette.Client} client for operations.
*/
function UsbStoragePanel(client) {
// Call the Base constructor to initiate base class.
Base.call(this, client, null, UsbStoragePanel.Selectors);
}
module.exports = UsbStoragePanel;
UsbStoragePanel.Selectors = {
'usbEnabledCheckbox': '.ums-switch',
'confirmButton': '#settings-confirm-dialog button[type="submit"]'
};
UsbStoragePanel.prototype = {
__proto__: Base.prototype,
get isUsbEnabledSwitchChecked() {
// Marionette has trouble returning custom properties on shadow roots.
// For now query the shadowRoot for checked status.
return this.findElement('usbEnabledCheckbox')
.scriptWith(function(el) {
return el.shadowRoot.querySelector('input[type="checkbox"]').checked;
});
},
get isUmsEnabled() {
return this.client.settings.get('ums.enabled');
},
tapUsbEnabledSwitch: function() {
this.waitForElement('usbEnabledCheckbox').tap();
}
};

View file

@ -0,0 +1,57 @@
'use strict';
var Base = require('./base');
// origin of the settings app
var ORIGIN = 'app://settings.gaiamobile.org';
/**
* Abstraction around system app
* @constructor
* @param {Marionette.Client} client for operations.
*/
function SystemApp(client) {
Base.call(this, client, ORIGIN, SystemApp.Selectors);
}
module.exports = SystemApp;
SystemApp.Selectors = {
'actionMenu': 'form[data-z-index-level="action-menu"]',
'valueSelector': '.value-selector',
'confirmOkButton': '.appWindow.active .modal-dialog-confirm-ok'
};
SystemApp.prototype = {
__proto__: Base.prototype,
isActionMenuVisible: function() {
var actionMenu = null,
displayed = false;
this.client.switchToFrame();
actionMenu = this.waitForElement('actionMenu');
displayed = actionMenu && actionMenu.displayed();
// Go back to settings app.
this.launch();
return displayed;
},
isValueSelectorVisible: function() {
var valueSelector = null,
displayed = false;
this.client.switchToFrame();
valueSelector = this.waitForElement('valueSelector');
displayed = valueSelector && valueSelector.displayed();
// Go back to settings app.
this.launch();
return displayed;
},
/*
/* Click the ok button on window.confirm dialog.
*/
confirmOk: function() {
this.client.switchToFrame();
var confirmButton = this.waitForElement('confirmOkButton');
confirmButton.click();
}
};