Skip to content

Commit

Permalink
Initial Checkin.
Browse files Browse the repository at this point in the history
  • Loading branch information
cuff-links committed May 6, 2016
1 parent c1d21b0 commit d0c3365
Show file tree
Hide file tree
Showing 37 changed files with 775 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .gitignore
@@ -0,0 +1,15 @@
*.sw[op]
_temp/
venv/
*.pyc
*.egg-info/
*.egg
dist/
.tox/
.DS_Store

# pyenv
.python-version

#IDE
.idea
3 changes: 3 additions & 0 deletions __init__.py
@@ -0,0 +1,3 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
3 changes: 3 additions & 0 deletions apps/__init__.py
@@ -0,0 +1,3 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
1 change: 1 addition & 0 deletions apps/activitystream/__init__.py
@@ -0,0 +1 @@
__author__ = 'jdorlus'
30 changes: 30 additions & 0 deletions apps/activitystream/app.py
@@ -0,0 +1,30 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from apps.base import Base

from firefox_puppeteer.testcases import BaseFirefoxTestCase

from marionette_driver import By


class ActivityStream(Base, BaseFirefoxTestCase):

_activitystream_top_sites_header = (By.XPATH, '//h3[text()="Top Sites"]')

def __init__(self, puppeteer):
super(ActivityStream, self).__init__(puppeteer.marionette)

self.set_context(self.CHROME)
self.browser = self.windows.current

self.browser.focus()
self.browser.tabbar.open_tab()
self.set_context(self.CONTENT)
self.wait_for_element_displayed(*self._activitystream_top_sites_header)

@property
def top_sites(self):
pass

96 changes: 96 additions & 0 deletions apps/base.py
@@ -0,0 +1,96 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from marionette_driver import expected, Wait, Actions
from marionette_driver.errors import NoSuchElementException

import re


class Base(object):

def __init__(self, marionette):
self.marionette = marionette
self.CHROME = 'chrome'
self.CONTENT = 'content'
self.set_context(self.CONTENT)
self.action = Actions(marionette)

def launch(self, url):
if url is not None:
regex = re.compile(
r'^(?:http|ftp)s?://'
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)'
r'+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'
r'localhost|'
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
r'(?::\d+)?'
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
if regex.match(url):
self.marionette.navigate(url)
else:
raise ValueError('Url is malformed.')
else:
raise ValueError("Url must contain a value.")

def is_element_present(self, by, locator):
try:
self.marionette.find_element(by, locator)
return True
except NoSuchElementException:
return False

def is_element_displayed(self, by, locator):
try:
return self.marionette.find_element(by, locator).is_displayed()
except NoSuchElementException:
return False

def wait_for_element_displayed(self, by, locator):
return Wait(self.marionette).until(expected.element_displayed(
Wait(self.marionette).until(expected.element_present(by, locator))))

def wait_for_element_present(self, by, locator):
Wait(self.marionette).until(expected.element_present(by, locator))

def wait_for_element_enabled(self, by, locator):
Wait(self.marionette).until(
expected.element_enabled(lambda m: m.find_element(by, locator)))

def wait_for_element_not_displayed(self, by, locator):
Wait(self.marionette).until(expected.element_not_displayed(
Wait(self.marionette).until(expected.element_present(by, locator))))

def wait_for_element_not_present(self, by, locator):
Wait(self.marionette).until(expected.element_not_present(by, locator))

def wait_for_element_not_enabled(self, by, locator):
Wait(self.marionette).until(
expected.element_not_enabled(lambda m: m.find_element(by, locator)))

def set_context(self, context):
if context != self.CHROME and context != self.CONTENT:
raise AttributeError(
'{} is not a context that you can switch to'.format(context))
else:
self.marionette.set_context(context)

def click_element(self, by, locator):
self.marionette.find_element(by, locator).click()

def send_keys_to_element(self, by, locator, string):
self.marionette.find_element(by, locator).send_keys(string)

def wait(self, time):
self.action.wait(time).perform()

def get_element_text(self, by, locator):
return self.marionette.find_element(by, locator).text


class PageRegion(Base):

def __init__(self, marionette, element):
self.root_element = element
Base.__init__(self, marionette)
3 changes: 3 additions & 0 deletions apps/pocket/__init__.py
@@ -0,0 +1,3 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
75 changes: 75 additions & 0 deletions apps/pocket/app.py
@@ -0,0 +1,75 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.


from marionette_driver import By


from apps.base import Base, PageRegion


class Pocket(Base):
_login_url = 'https://www.getpocket.com/login'
_pocket_chrome_button = (By.ID, "#pocket-button")
_login_with_firefox_button_locator = (
By.CSS_SELECTOR, 'a.btn.login-btn-firefox')
_pocket_start_saving_button_locator = (
By.XPATH, '//a[text()="Start Saving"]')
_pocket_logo_header_locator = (By.CSS_SELECTOR, 'h1.pocket_logo')
_pocket_username_nav_locator = (By.CSS_SELECTOR, 'span.nav-username')
_pocket_all_pocket_items_locator = (By.CSS_SELECTOR, '#queue li.item')

def __init__(self, marionette):
super(Pocket, self).__init__(marionette)
self.wait_for_element_displayed(*self._pocket_logo_header_locator)
self.wait_for_element_displayed(*self._pocket_all_pocket_items_locator)

def click_pocket_chrome_button(self):
with self.marionette.using_context(self.CHROME):
self.wait_for_element_displayed(
*self._pocket_chrome_button).click()

@property
def username(self):
return self.get_element_text(*self._pocket_username_nav_locator)

@property
def queue_items(self):
return [self.QueueItem(self.marionette, queue_item) for queue_item in
self.marionette.find_elements(*self._pocket_all_pocket_items_locator)]

class QueueItem(PageRegion):
# TODO: Create methods for all of these different properties and functions.

@property
def header(self):
pass

@property
def body(self):
pass

@property
def url(self):
pass

@property
def tags(self):
pass

def toggle_favorite(self):
pass

def delete(self):
pass

def archive(self):
pass

def add_tag(self):
pass

def delete_tag(self):
pass

3 changes: 3 additions & 0 deletions apps/testpilot/__init__.py
@@ -0,0 +1,3 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
33 changes: 33 additions & 0 deletions apps/testpilot/app.py
@@ -0,0 +1,33 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from marionette_driver import By

from firefox_puppeteer.ui.browser.notifications import (
AddOnInstallBlockedNotification,
AddOnInstallConfirmationNotification,
AddOnInstallCompleteNotification)

from apps.base import Base


class TestPilot(Base):
_login_with_firefox_button_locator = (
By.CSS_SELECTOR, 'div.cta-layout a.fxa-alternate')
_testpilot_install_addon_button_locator = (By.CSS_SELECTOR, '[data-l10n-id="landingInstallButton"]')

def __init__(self, puppeteer, firefox, url):
super(TestPilot, self).__init__(puppeteer.marionette)
self.wait_for_element_displayed(*self._testpilot_install_addon_button_locator)
self.click_element(*self._testpilot_install_addon_button_locator)
with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
if 'dev' in url:
firefox.wait_for_notification(AddOnInstallBlockedNotification)
print self.marionette.find_element(By.ID, 'notification-popup')
firefox.notification.allow()
firefox.wait_for_notification(AddOnInstallConfirmationNotification)
firefox.notification.install()
firefox.wait_for_notification(AddOnInstallCompleteNotification)
firefox.notification.close()

3 changes: 3 additions & 0 deletions helpers/__init__.py
@@ -0,0 +1,3 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
30 changes: 30 additions & 0 deletions helpers/utils.py
@@ -0,0 +1,30 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import json
import time
import urllib2

_rest__email_client = 'http://restmail.net/mail/'


def generate_random_email_address(domain=None):
domain = 'restmail.net' if domain is None else str(domain)
return 'test' + str(time.time()) + '@' + domain


def check_generated_email(email_address):
try:
data = pull_email_messages(email_address)
activation_link = data['headers']['x-link']
return activation_link
except IndexError:
check_generated_email(email_address)


def pull_email_messages(email_address):
response = urllib2.urlopen(
_rest__email_client + email_address.split('@')[0])
data = json.load(response)[0]
time.sleep(.5)
return data
39 changes: 39 additions & 0 deletions setup.py
@@ -0,0 +1,39 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

from setuptools import setup, find_packages

PACKAGE_VERSION = '0.0.2'

deps = [
'marionette-client == 2.0.0',
'marionette-driver == 1.1.1',
'mozfile == 1.2',
'mozinfo == 0.8',
'mozinstall == 1.12',
'mozlog == 3.0',
'firefox-puppeteer == 4.0.0'
]

setup(name='firefox-services-tests',
version=PACKAGE_VERSION,
description='A collection of Mozillas Cloud Services tests run with Marionette',
long_description='See https://github.com/mozilla-services/services-test/tree/dev/services-marionette',
classifiers=['Environment :: Console',
'Intended Audience :: Developers',
'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
'Natural Language :: English',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Topic :: Software Development :: Libraries :: Python Modules',
],
keywords='mozilla services',
author='Mozilla Cloud Services QA Team',
author_email='cloud-services-qa@mozilla.com',
url='https://github.com/mozilla-services/services-test',
license='MPL 2.0',
packages=find_packages(),
include_package_data=True,
zip_safe=False,
install_requires=deps)
3 changes: 3 additions & 0 deletions tests/__init__.py
@@ -0,0 +1,3 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
Binary file added tests/activity_stream.xpi
Binary file not shown.
3 changes: 3 additions & 0 deletions tests/functional/__init__.py
@@ -0,0 +1,3 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
Binary file added tests/functional/activity_stream.xpi
Binary file not shown.
1 change: 1 addition & 0 deletions tests/functional/activitystream/__init__.py
@@ -0,0 +1 @@
__author__ = 'jdorlus'
Binary file not shown.

0 comments on commit d0c3365

Please sign in to comment.