All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] Migrate Toaster tests to Selenium
@ 2016-03-16 13:10 Elliot Smith
  2016-03-16 13:10 ` [PATCH 1/5] toaster-tests: migrate to Selenium for UI tests Elliot Smith
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Elliot Smith @ 2016-03-16 13:10 UTC (permalink / raw)
  To: toaster

As discussed in the Toaster public meeting, migrate the Django UI tests to
Selenium.

(Note that the build dashboard tests have not been migrated, as this is covered
in another branch I have which is pending submission.)

Also add a sample testcase to use as a template for future tests
(test_sample.py).

See bitbake/lib/toaster/tests_browser/README for instructions on running the
tests.

Changes since d6887a7 (toaster-next) are in
git://git.yoctoproject.org/poky-contrib, elliot/toaster/migrate_tests_to_selenium
http://git.yoctoproject.org/cgit.cgi/poky-contrib/log/?h=elliot/toaster/migrate_tests_to_selenium

Elliot Smith (5):
  toaster-tests: migrate to Selenium for UI tests
  toaster-tests: migrate all builds page and project page tests to
    Selenium
  toaster-tests: migrate project builds page tests to Selenium
  toaster-tests: migrate all projects page tests to Selenium
  toaster-tests: migrate landing page tests to Selenium

 bitbake/lib/toaster/tests_browser/README           |  41 ++
 bitbake/lib/toaster/tests_browser/__init__.py      |   0
 .../lib/toaster/tests_browser/selenium_helpers.py  | 200 ++++++++
 .../toaster/tests_browser/test_all_builds_page.py  | 143 ++++++
 .../tests_browser/test_all_projects_page.py        | 214 ++++++++
 .../lib/toaster/tests_browser/test_landing_page.py | 108 ++++
 .../tests_browser/test_project_builds_page.py      | 168 +++++++
 .../lib/toaster/tests_browser/test_project_page.py |  59 +++
 bitbake/lib/toaster/tests_browser/test_sample.py   |  41 ++
 bitbake/lib/toaster/toastergui/tests.py            | 544 ---------------------
 bitbake/toaster-requirements.txt                   |   1 +
 11 files changed, 975 insertions(+), 544 deletions(-)
 create mode 100644 bitbake/lib/toaster/tests_browser/README
 create mode 100644 bitbake/lib/toaster/tests_browser/__init__.py
 create mode 100644 bitbake/lib/toaster/tests_browser/selenium_helpers.py
 create mode 100644 bitbake/lib/toaster/tests_browser/test_all_builds_page.py
 create mode 100644 bitbake/lib/toaster/tests_browser/test_all_projects_page.py
 create mode 100644 bitbake/lib/toaster/tests_browser/test_landing_page.py
 create mode 100644 bitbake/lib/toaster/tests_browser/test_project_builds_page.py
 create mode 100644 bitbake/lib/toaster/tests_browser/test_project_page.py
 create mode 100644 bitbake/lib/toaster/tests_browser/test_sample.py

--
Elliot Smith
Software Engineer
Intel OTC

---------------------------------------------------------------------
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/5] toaster-tests: migrate to Selenium for UI tests
  2016-03-16 13:10 [PATCH 0/5] Migrate Toaster tests to Selenium Elliot Smith
@ 2016-03-16 13:10 ` Elliot Smith
  2016-03-16 13:10 ` [PATCH 2/5] toaster-tests: migrate all builds page and project page tests to Selenium Elliot Smith
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Elliot Smith @ 2016-03-16 13:10 UTC (permalink / raw)
  To: toaster

Create a new folder for Selenium tests.

Add a new base Selenium testcase class and a helper which
instantiates a webdriver for a given browser.

Add a sample Selenium test case which can be used as a template
for creating new tests.

Amend the pip requirements file to include Selenium.

Signed-off-by: Elliot Smith <elliot.smith@intel.com>
---
 bitbake/lib/toaster/tests_browser/README           |  41 +++++
 bitbake/lib/toaster/tests_browser/__init__.py      |   0
 .../lib/toaster/tests_browser/selenium_helpers.py  | 200 +++++++++++++++++++++
 bitbake/lib/toaster/tests_browser/test_sample.py   |  41 +++++
 bitbake/toaster-requirements.txt                   |   1 +
 5 files changed, 283 insertions(+)
 create mode 100644 bitbake/lib/toaster/tests_browser/README
 create mode 100644 bitbake/lib/toaster/tests_browser/__init__.py
 create mode 100644 bitbake/lib/toaster/tests_browser/selenium_helpers.py
 create mode 100644 bitbake/lib/toaster/tests_browser/test_sample.py

diff --git a/bitbake/lib/toaster/tests_browser/README b/bitbake/lib/toaster/tests_browser/README
new file mode 100644
index 0000000..f399280
--- /dev/null
+++ b/bitbake/lib/toaster/tests_browser/README
@@ -0,0 +1,41 @@
+# Running Toaster's browser-based test suite
+
+These tests require Selenium to be installed in your Python environment.
+
+The simplest way to install this is via pip:
+
+  pip install selenium
+
+Alternatively, if you used pip to install the libraries required by Toaster,
+selenium will already be installed.
+
+To run tests against Chrome:
+
+* Download chromedriver for your host OS from
+  https://code.google.com/p/chromedriver/downloads/list
+* On *nix systems, put chromedriver on PATH
+* On Windows, put chromedriver.exe in the same directory as chrome.exe
+
+To run tests against PhantomJS (headless);
+
+* Download and install PhantomJS:
+  http://phantomjs.org/download.html
+* On *nix systems, put phantomjs on PATH
+* Not tested on Windows
+
+Firefox should work without requiring additional software to be installed.
+
+The test case will instantiate a Selenium driver set by the
+TOASTER_TESTS_BROWSER environment variable, or Chrome if this is not specified.
+
+Available drivers:
+
+* chrome (default)
+* firefox
+* ie
+* phantomjs
+
+e.g. to run the test suite with phantomjs where you have phantomjs installed
+in /home/me/apps/phantomjs:
+
+PATH=/home/me/apps/phantomjs/bin:$PATH TOASTER_TESTS_BROWSER=phantomjs manage.py test tests_browser
diff --git a/bitbake/lib/toaster/tests_browser/__init__.py b/bitbake/lib/toaster/tests_browser/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/bitbake/lib/toaster/tests_browser/selenium_helpers.py b/bitbake/lib/toaster/tests_browser/selenium_helpers.py
new file mode 100644
index 0000000..93c7968
--- /dev/null
+++ b/bitbake/lib/toaster/tests_browser/selenium_helpers.py
@@ -0,0 +1,200 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The Wait class and some of SeleniumDriverHelper and SeleniumTestCase are
+# modified from Patchwork, released under the same licence terms as Toaster:
+# https://github.com/dlespiau/patchwork/blob/master/patchwork/tests/browser.py
+
+"""
+Helper methods for creating Toaster Selenium tests which run within
+the context of Django unit tests.
+"""
+
+import os
+import time
+
+from django.contrib.staticfiles.testing import StaticLiveServerTestCase
+from selenium import webdriver
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.common.exceptions import NoSuchElementException, \
+        StaleElementReferenceException, TimeoutException
+
+def create_selenium_driver(browser='chrome'):
+    # set default browser string based on env (if available)
+    env_browser = os.environ.get('TOASTER_TESTS_BROWSER')
+    if env_browser:
+        browser = env_browser
+
+    if browser == 'chrome':
+        return webdriver.Chrome(
+            service_args=["--verbose", "--log-path=selenium.log"]
+        )
+    elif browser == 'firefox':
+        return webdriver.Firefox()
+    elif browser == 'ie':
+        return webdriver.Ie()
+    elif browser == 'phantomjs':
+        return webdriver.PhantomJS()
+    else:
+        msg = 'Selenium driver for browser %s is not available' % browser
+        raise RuntimeError(msg)
+
+class Wait(WebDriverWait):
+    """
+    Subclass of WebDriverWait with predetermined timeout and poll
+    frequency. Also deals with a wider variety of exceptions.
+    """
+    _TIMEOUT = 10
+    _POLL_FREQUENCY = 0.5
+
+    def __init__(self, driver):
+        super(Wait, self).__init__(driver, self._TIMEOUT, self._POLL_FREQUENCY)
+
+    def until(self, method, message=''):
+        """
+        Calls the method provided with the driver as an argument until the
+        return value is not False.
+        """
+
+        end_time = time.time() + self._timeout
+        while True:
+            try:
+                value = method(self._driver)
+                if value:
+                    return value
+            except NoSuchElementException:
+                pass
+            except StaleElementReferenceException:
+                pass
+
+            time.sleep(self._poll)
+            if time.time() > end_time:
+                break
+
+        raise TimeoutException(message)
+
+    def until_not(self, method, message=''):
+        """
+        Calls the method provided with the driver as an argument until the
+        return value is False.
+        """
+
+        end_time = time.time() + self._timeout
+        while True:
+            try:
+                value = method(self._driver)
+                if not value:
+                    return value
+            except NoSuchElementException:
+                return True
+            except StaleElementReferenceException:
+                pass
+
+            time.sleep(self._poll)
+            if time.time() > end_time:
+                break
+
+        raise TimeoutException(message)
+
+class SeleniumTestCase(StaticLiveServerTestCase):
+    """
+    NB StaticLiveServerTestCase is used as the base test case so that
+    static files are served correctly in a Selenium test run context; see
+    https://docs.djangoproject.com/en/1.9/ref/contrib/staticfiles/#specialized-test-case-to-support-live-testing
+    """
+
+    @classmethod
+    def setUpClass(cls):
+        """ Create a webdriver driver at the class level """
+
+        super(SeleniumTestCase, cls).setUpClass()
+
+        # instantiate the Selenium webdriver once for all the test methods
+        # in this test case
+        cls.driver = create_selenium_driver()
+
+    @classmethod
+    def tearDownClass(cls):
+        """ Clean up webdriver driver """
+
+        cls.driver.quit()
+        super(SeleniumTestCase, cls).tearDownClass()
+
+    def get(self, url):
+        """
+        Selenium requires absolute URLs, so convert Django URLs returned
+        by resolve() or similar to absolute ones and get using the
+        webdriver instance.
+
+        url: a relative URL
+        """
+        abs_url = '%s%s' % (self.live_server_url, url)
+        self.driver.get(abs_url)
+
+    def find(self, selector):
+        """ Find single element by CSS selector """
+        return self.driver.find_element_by_css_selector(selector)
+
+    def find_all(self, selector):
+        """ Find all elements matching CSS selector """
+        return self.driver.find_elements_by_css_selector(selector)
+
+    def focused_element(self):
+        """ Return the element which currently has focus on the page """
+        return self.driver.switch_to.active_element
+
+    def wait_until_present(self, selector):
+        """ Wait until element matching CSS selector is on the page """
+        is_present = lambda driver: self.find(selector)
+        msg = 'An element matching "%s" should be on the page' % selector
+        element = Wait(self.driver).until(is_present, msg)
+        return element
+
+    def wait_until_visible(self, selector):
+        """ Wait until element matching CSS selector is visible on the page """
+        is_visible = lambda driver: self.find(selector).is_displayed()
+        msg = 'An element matching "%s" should be visible' % selector
+        Wait(self.driver).until(is_visible, msg)
+        return self.find(selector)
+
+    def wait_until_focused(self, selector):
+        """ Wait until element matching CSS selector has focus """
+        is_focused = \
+            lambda driver: self.find(selector) == self.focused_element()
+        msg = 'An element matching "%s" should be focused' % selector
+        Wait(self.driver).until(is_focused, msg)
+        return self.find(selector)
+
+    def enter_text(self, selector, value):
+        """ Insert text into element matching selector """
+        field = self.wait_until_present(selector)
+        field.send_keys(value)
+        return field
+
+    def click(self, selector):
+        """ Click on element which matches CSS selector """
+        element = self.wait_until_visible(selector)
+        element.click()
+        return element
+
+    def get_page_source(self):
+        """ Get raw HTML for the current page """
+        return self.driver.page_source
diff --git a/bitbake/lib/toaster/tests_browser/test_sample.py b/bitbake/lib/toaster/tests_browser/test_sample.py
new file mode 100644
index 0000000..143ea3c
--- /dev/null
+++ b/bitbake/lib/toaster/tests_browser/test_sample.py
@@ -0,0 +1,41 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+"""
+A small example test demonstrating the basics of writing a test with
+Toaster's SeleniumTestCase; this just fetches the Toaster home page
+and checks it has the word "Toaster" in the brand link
+
+New test files should follow this structure, should be named "test_*.py",
+and should be in the same directory as this sample.
+"""
+
+from django.core.urlresolvers import reverse
+from toaster.tests_browser.selenium_helpers import SeleniumTestCase
+
+class TestSample(SeleniumTestCase):
+    """ Test landing page shows the Toaster brand """
+
+    def test_landing_page_has_brand(self):
+        url = reverse('landing')
+        self.get(url)
+        brand_link = self.find('span.brand a')
+        self.assertEqual(brand_link.text.strip(), 'Toaster')
diff --git a/bitbake/toaster-requirements.txt b/bitbake/toaster-requirements.txt
index 0e8c742..5c3c633 100644
--- a/bitbake/toaster-requirements.txt
+++ b/bitbake/toaster-requirements.txt
@@ -2,3 +2,4 @@ Django>1.8,<1.9
 argparse==1.2.1
 wsgiref==0.1.2
 beautifulsoup4>=4.4.0
+selenium==2.49.2
-- 
Elliot Smith
Software Engineer
Intel OTC

---------------------------------------------------------------------
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/5] toaster-tests: migrate all builds page and project page tests to Selenium
  2016-03-16 13:10 [PATCH 0/5] Migrate Toaster tests to Selenium Elliot Smith
  2016-03-16 13:10 ` [PATCH 1/5] toaster-tests: migrate to Selenium for UI tests Elliot Smith
@ 2016-03-16 13:10 ` Elliot Smith
  2016-03-16 13:10 ` [PATCH 3/5] toaster-tests: migrate project builds " Elliot Smith
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Elliot Smith @ 2016-03-16 13:10 UTC (permalink / raw)
  To: toaster

Signed-off-by: Elliot Smith <elliot.smith@intel.com>
---
 .../toaster/tests_browser/test_all_builds_page.py  | 143 +++++++++++++++++++++
 .../lib/toaster/tests_browser/test_project_page.py |  59 +++++++++
 bitbake/lib/toaster/toastergui/tests.py            | 140 --------------------
 3 files changed, 202 insertions(+), 140 deletions(-)
 create mode 100644 bitbake/lib/toaster/tests_browser/test_all_builds_page.py
 create mode 100644 bitbake/lib/toaster/tests_browser/test_project_page.py

diff --git a/bitbake/lib/toaster/tests_browser/test_all_builds_page.py b/bitbake/lib/toaster/tests_browser/test_all_builds_page.py
new file mode 100644
index 0000000..24ca436
--- /dev/null
+++ b/bitbake/lib/toaster/tests_browser/test_all_builds_page.py
@@ -0,0 +1,143 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import re
+
+from django.core.urlresolvers import reverse
+from django.utils import timezone
+from toaster.tests_browser.selenium_helpers import SeleniumTestCase
+
+from orm.models import BitbakeVersion, Release, Project, Build, Target
+
+class TestAllBuildsPage(SeleniumTestCase):
+    """ Tests for all builds page /builds/ """
+
+    PROJECT_NAME = 'test project'
+    CLI_BUILDS_PROJECT_NAME = 'command line builds'
+
+    def setUp(self):
+        bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/',
+                                            branch='master', dirpath='')
+        release = Release.objects.create(name='release1',
+                                         bitbake_version=bbv)
+        self.project1 = Project.objects.create_project(name=self.PROJECT_NAME,
+                                                       release=release)
+        self.default_project = Project.objects.create_project(
+            name=self.CLI_BUILDS_PROJECT_NAME,
+            release=release
+        )
+        self.default_project.is_default = True
+        self.default_project.save()
+
+        # parameters for builds to associate with the projects
+        now = timezone.now()
+
+        self.project1_build_success = {
+            'project': self.project1,
+            'started_on': now,
+            'completed_on': now,
+            'outcome': Build.SUCCEEDED
+        }
+
+        self.default_project_build_success = {
+            'project': self.default_project,
+            'started_on': now,
+            'completed_on': now,
+            'outcome': Build.SUCCEEDED
+        }
+
+    def test_show_tasks_with_suffix(self):
+        """ Task should be shown as suffix on build name """
+        build = Build.objects.create(**self.project1_build_success)
+        target = 'bash'
+        task = 'clean'
+        Target.objects.create(build=build, target=target, task=task)
+
+        url = reverse('all-builds')
+        self.get(url)
+        self.wait_until_present('td[class="target"]')
+
+        cell = self.find('td[class="target"]')
+        content = cell.get_attribute('innerHTML')
+        expected_text = '%s:%s' % (target, task)
+
+        self.assertTrue(re.search(expected_text, content),
+                        '"target" cell should contain text %s' % expected_text)
+
+    def test_rebuild_buttons(self):
+        """
+        Test 'Rebuild' buttons in recent builds section
+
+        'Rebuild' button should not be shown for command-line builds,
+        but should be shown for other builds
+        """
+        build1 = Build.objects.create(**self.project1_build_success)
+        default_build = Build.objects.create(**self.default_project_build_success)
+
+        url = reverse('all-builds')
+        self.get(url)
+
+        # shouldn't see a run again button for command-line builds
+        selector = 'div[data-latest-build-result="%s"] button' % default_build.id
+        run_again_button = self.find_all(selector)
+        self.assertEqual(len(run_again_button), 0,
+                         'should not see a run again button for cli builds')
+
+        # should see a run again button for non-command-line builds
+        selector = 'div[data-latest-build-result="%s"] button' % build1.id
+        run_again_button = self.find_all(selector)
+        self.assertEqual(len(run_again_button), 1,
+                         'should see a run again button for non-cli builds')
+
+    def test_tooltips_on_project_name(self):
+        """
+        Test tooltips shown next to project name in the main table
+
+        A tooltip should be present next to the command line
+        builds project name in the all builds page, but not for
+        other projects
+        """
+        Build.objects.create(**self.project1_build_success)
+        Build.objects.create(**self.default_project_build_success)
+
+        url = reverse('all-builds')
+        self.get(url)
+
+        # get the project name cells from the table
+        cells = self.find_all('#allbuildstable td[class="project"]')
+
+        selector = 'i.get-help'
+
+        for cell in cells:
+            content = cell.get_attribute('innerHTML')
+            help_icons = cell.find_elements_by_css_selector(selector)
+
+            if re.search(self.PROJECT_NAME, content):
+                # no help icon next to non-cli project name
+                msg = 'should not be a help icon for non-cli builds name'
+                self.assertEqual(len(help_icons), 0, msg)
+            elif re.search(self.CLI_BUILDS_PROJECT_NAME, content):
+                # help icon next to cli project name
+                msg = 'should be a help icon for cli builds name'
+                self.assertEqual(len(help_icons), 1, msg)
+            else:
+                msg = 'found unexpected project name cell in all builds table'
+                self.fail(msg)
diff --git a/bitbake/lib/toaster/tests_browser/test_project_page.py b/bitbake/lib/toaster/tests_browser/test_project_page.py
new file mode 100644
index 0000000..acd334b
--- /dev/null
+++ b/bitbake/lib/toaster/tests_browser/test_project_page.py
@@ -0,0 +1,59 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from django.core.urlresolvers import reverse
+from django.utils import timezone
+from toaster.tests_browser.selenium_helpers import SeleniumTestCase
+
+from orm.models import Build, Project
+
+class TestProjectPage(SeleniumTestCase):
+    """ Test project data at /project/X/ is displayed correctly """
+
+    CLI_BUILDS_PROJECT_NAME = 'Command line builds'
+
+    def test_cli_builds_in_progress(self):
+        """
+        In progress builds should not cause an error to be thrown
+        when navigating to "command line builds" project page;
+        see https://bugzilla.yoctoproject.org/show_bug.cgi?id=8277
+        """
+
+        # add the "command line builds" default project; this mirrors what
+        # we do with get_or_create_default_project()
+        default_project = Project.objects.create_project(self.CLI_BUILDS_PROJECT_NAME, None)
+        default_project.is_default = True
+        default_project.save()
+
+        # add an "in progress" build for the default project
+        now = timezone.now()
+        Build.objects.create(project=default_project,
+                             started_on=now,
+                             completed_on=now,
+                             outcome=Build.IN_PROGRESS)
+
+        # navigate to the project page for the default project
+        url = reverse("project", args=(default_project.id,))
+        self.get(url)
+
+        # check that we get a project page with the correct heading
+        project_name = self.find('#project-name').text.strip()
+        self.assertEqual(project_name, self.CLI_BUILDS_PROJECT_NAME)
diff --git a/bitbake/lib/toaster/toastergui/tests.py b/bitbake/lib/toaster/toastergui/tests.py
index 6b05916..78b7c04 100644
--- a/bitbake/lib/toaster/toastergui/tests.py
+++ b/bitbake/lib/toaster/toastergui/tests.py
@@ -897,146 +897,6 @@ class ProjectBuildsPageTests(TestCase):
         self.assertEqual(len(tabs), 1,
                          'should be a top bar shown for non-command-line builds')
 
-class AllBuildsPageTests(TestCase):
-    """ Tests for all builds page /builds/ """
-
-    def setUp(self):
-        bbv = BitbakeVersion.objects.create(name="bbv1", giturl="/tmp/",
-                                            branch="master", dirpath="")
-        release = Release.objects.create(name="release1",
-                                         bitbake_version=bbv)
-        self.project1 = Project.objects.create_project(name=PROJECT_NAME,
-                                                       release=release)
-        self.default_project = Project.objects.create_project(
-            name=CLI_BUILDS_PROJECT_NAME,
-            release=release
-        )
-        self.default_project.is_default = True
-        self.default_project.save()
-
-        # parameters for builds to associate with the projects
-        now = timezone.now()
-
-        self.project1_build_success = {
-            "project": self.project1,
-            "started_on": now,
-            "completed_on": now,
-            "outcome": Build.SUCCEEDED
-        }
-
-        self.default_project_build_success = {
-            "project": self.default_project,
-            "started_on": now,
-            "completed_on": now,
-            "outcome": Build.SUCCEEDED
-        }
-
-    def _get_row_for_build(self, data, build_id):
-        """ Get the object representing the table data for a project """
-        return [row for row in data['rows']
-                    if row['id'] == build_id][0]
-
-    def test_show_tasks_in_allbuilds(self):
-        """ Task should be shown as suffix on build name """
-        build = Build.objects.create(**self.project1_build_success)
-        Target.objects.create(build=build, target='bash', task='clean')
-
-        url = reverse('all-builds')
-        response = self.client.get(url, {'format': 'json'}, follow=True)
-        data = json.loads(response.content)
-        cell = data['rows'][0]['static:target']
-
-        result = re.findall('bash:clean', cell, re.MULTILINE)
-        self.assertEqual(len(result), 1)
-
-    def test_run_again(self):
-        """
-        "Rebuild" button should not be shown for command-line builds,
-        but should be shown for other builds
-        """
-        build1 = Build.objects.create(**self.project1_build_success)
-        default_build = Build.objects.create(**self.default_project_build_success)
-        url = reverse('all-builds')
-        response = self.client.get(url, follow=True)
-        soup = BeautifulSoup(response.content)
-
-        # shouldn't see a run again button for command-line builds
-        attrs = {'data-latest-build-result': default_build.id}
-        result = soup.find('div', attrs=attrs)
-        run_again_button = result.select('button')
-        self.assertEqual(len(run_again_button), 0)
-
-        # should see a run again button for non-command-line builds
-        attrs = {'data-latest-build-result': build1.id}
-        result = soup.find('div', attrs=attrs)
-        run_again_button = result.select('button')
-        self.assertEqual(len(run_again_button), 1)
-
-    def test_tooltips_on_project_name(self):
-        """
-        A tooltip should be present next to the command line
-        builds project name in the all builds page, but not for
-        other projects
-        """
-        build1 = Build.objects.create(**self.project1_build_success)
-        default_build = Build.objects.create(**self.default_project_build_success)
-
-        url = reverse('all-builds')
-        response = self.client.get(url, {'format': 'json'}, follow=True)
-        data = json.loads(response.content)
-
-        # get the data row for the non-command-line builds project
-        other_project_row = self._get_row_for_build(data, build1.id)
-
-        # make sure there is some HTML
-        soup = BeautifulSoup(other_project_row['static:project'])
-        self.assertEqual(len(soup.select('a')), 1,
-                         'should be a project name link')
-
-        # no help icon on non-default project name
-        icons = soup.select('i.get-help')
-        self.assertEqual(len(icons), 0,
-                         'should not be a help icon for non-cli builds name')
-
-        # get the data row for the command-line builds project
-        default_project_row = self._get_row_for_build(data, default_build.id)
-
-        # help icon on default project name
-        soup = BeautifulSoup(default_project_row['static:project'])
-        icons = soup.select('i.get-help')
-        self.assertEqual(len(icons), 1,
-                         'should be a help icon for cli builds name')
-
-class ProjectPageTests(TestCase):
-    """ Test project data at /project/X/ is displayed correctly """
-    CLI_BUILDS_PROJECT_NAME = 'Command line builds'
-
-    def test_command_line_builds_in_progress(self):
-        """
-        In progress builds should not cause an error to be thrown
-        when navigating to "command line builds" project page;
-        see https://bugzilla.yoctoproject.org/show_bug.cgi?id=8277
-        """
-
-        # add the "command line builds" default project; this mirrors what
-        # we do in migration 0026_set_default_project.py
-        default_project = Project.objects.create_project(self.CLI_BUILDS_PROJECT_NAME, None)
-        default_project.is_default = True
-        default_project.save()
-
-        # add an "in progress" build for the default project
-        now = timezone.now()
-        build = Build.objects.create(project=default_project,
-                                     started_on=now,
-                                     completed_on=now,
-                                     outcome=Build.IN_PROGRESS)
-
-        # navigate to the project page for the default project
-        url = reverse("project", args=(default_project.id,))
-        response = self.client.get(url, follow=True)
-
-        self.assertEqual(response.status_code, 200)
-
 class BuildDashboardTests(TestCase):
     """ Tests for the build dashboard /build/X """
 
-- 
Elliot Smith
Software Engineer
Intel OTC

---------------------------------------------------------------------
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/5] toaster-tests: migrate project builds page tests to Selenium
  2016-03-16 13:10 [PATCH 0/5] Migrate Toaster tests to Selenium Elliot Smith
  2016-03-16 13:10 ` [PATCH 1/5] toaster-tests: migrate to Selenium for UI tests Elliot Smith
  2016-03-16 13:10 ` [PATCH 2/5] toaster-tests: migrate all builds page and project page tests to Selenium Elliot Smith
@ 2016-03-16 13:10 ` Elliot Smith
  2016-03-16 13:10 ` [PATCH 4/5] toaster-tests: migrate all projects " Elliot Smith
  2016-03-16 13:10 ` [PATCH 5/5] toaster-tests: migrate landing " Elliot Smith
  4 siblings, 0 replies; 10+ messages in thread
From: Elliot Smith @ 2016-03-16 13:10 UTC (permalink / raw)
  To: toaster

Signed-off-by: Elliot Smith <elliot.smith@intel.com>
---
 .../tests_browser/test_project_builds_page.py      | 168 +++++++++++++++++++++
 bitbake/lib/toaster/toastergui/tests.py            | 133 ----------------
 2 files changed, 168 insertions(+), 133 deletions(-)
 create mode 100644 bitbake/lib/toaster/tests_browser/test_project_builds_page.py

diff --git a/bitbake/lib/toaster/tests_browser/test_project_builds_page.py b/bitbake/lib/toaster/tests_browser/test_project_builds_page.py
new file mode 100644
index 0000000..eb74560
--- /dev/null
+++ b/bitbake/lib/toaster/tests_browser/test_project_builds_page.py
@@ -0,0 +1,168 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import re
+
+from django.core.urlresolvers import reverse
+from django.utils import timezone
+from toaster.tests_browser.selenium_helpers import SeleniumTestCase
+
+from orm.models import BitbakeVersion, Release, Project, Build, Target
+
+class TestProjectBuildsPage(SeleniumTestCase):
+    """ Test data at /project/X/builds is displayed correctly """
+
+    PROJECT_NAME = 'test project'
+    CLI_BUILDS_PROJECT_NAME = 'command line builds'
+
+    def setUp(self):
+        bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/',
+                                            branch='master', dirpath='')
+        release = Release.objects.create(name='release1',
+                                         bitbake_version=bbv)
+        self.project1 = Project.objects.create_project(name=self.PROJECT_NAME,
+                                                       release=release)
+        self.project1.save()
+
+        self.project2 = Project.objects.create_project(name=self.PROJECT_NAME,
+                                                       release=release)
+        self.project2.save()
+
+        self.default_project = Project.objects.create_project(
+            name=self.CLI_BUILDS_PROJECT_NAME,
+            release=release
+        )
+        self.default_project.is_default = True
+        self.default_project.save()
+
+        # parameters for builds to associate with the projects
+        now = timezone.now()
+
+        self.project1_build_success = {
+            'project': self.project1,
+            'started_on': now,
+            'completed_on': now,
+            'outcome': Build.SUCCEEDED
+        }
+
+        self.project1_build_in_progress = {
+            'project': self.project1,
+            'started_on': now,
+            'completed_on': now,
+            'outcome': Build.IN_PROGRESS
+        }
+
+        self.project2_build_success = {
+            'project': self.project2,
+            'started_on': now,
+            'completed_on': now,
+            'outcome': Build.SUCCEEDED
+        }
+
+        self.project2_build_in_progress = {
+            'project': self.project2,
+            'started_on': now,
+            'completed_on': now,
+            'outcome': Build.IN_PROGRESS
+        }
+
+    def _get_rows_for_project(self, project_id):
+        """
+        Helper to retrieve HTML rows for a project's builds,
+        as shown in the main table of the page
+        """
+        url = reverse('projectbuilds', args=(project_id,))
+        self.get(url)
+        self.wait_until_present('#projectbuildstable tbody tr')
+        return self.find_all('#projectbuildstable tbody tr')
+
+    def test_show_builds_for_project(self):
+        """ Builds for a project should be displayed in the main table """
+        Build.objects.create(**self.project1_build_success)
+        Build.objects.create(**self.project1_build_success)
+        build_rows = self._get_rows_for_project(self.project1.id)
+        self.assertEqual(len(build_rows), 2)
+
+    def test_show_builds_project_only(self):
+        """ Builds for other projects should be excluded """
+        Build.objects.create(**self.project1_build_success)
+        Build.objects.create(**self.project1_build_success)
+        Build.objects.create(**self.project1_build_success)
+
+        # shouldn't see these two
+        Build.objects.create(**self.project2_build_success)
+        Build.objects.create(**self.project2_build_in_progress)
+
+        build_rows = self._get_rows_for_project(self.project1.id)
+        self.assertEqual(len(build_rows), 3)
+
+    def test_builds_exclude_in_progress(self):
+        """ "in progress" builds should not be shown in main table """
+        Build.objects.create(**self.project1_build_success)
+        Build.objects.create(**self.project1_build_success)
+
+        # shouldn't see this one
+        Build.objects.create(**self.project1_build_in_progress)
+
+        # shouldn't see these two either, as they belong to a different project
+        Build.objects.create(**self.project2_build_success)
+        Build.objects.create(**self.project2_build_in_progress)
+
+        build_rows = self._get_rows_for_project(self.project1.id)
+        self.assertEqual(len(build_rows), 2)
+
+    def test_show_tasks_with_suffix(self):
+        """ Task should be shown as suffixes on build names """
+        build = Build.objects.create(**self.project1_build_success)
+        target = 'bash'
+        task = 'clean'
+        Target.objects.create(build=build, target=target, task=task)
+
+        url = reverse('projectbuilds', args=(self.project1.id,))
+        self.get(url)
+        self.wait_until_present('td[class="target"]')
+
+        cell = self.find('td[class="target"]')
+        content = cell.get_attribute('innerHTML')
+        expected_text = '%s:%s' % (target, task)
+
+        self.assertTrue(re.search(expected_text, content),
+                        '"target" cell should contain text %s' % expected_text)
+
+    def test_cli_builds_hides_tabs(self):
+        """
+        Display for command line builds should hide tabs
+        """
+        url = reverse('projectbuilds', args=(self.default_project.id,))
+        self.get(url)
+        tabs = self.find_all('#project-topbar')
+        self.assertEqual(len(tabs), 0,
+                         'should be no top bar shown for command line builds')
+
+    def test_non_cli_builds_has_tabs(self):
+        """
+        Non-command-line builds projects should show the tabs
+        """
+        url = reverse('projectbuilds', args=(self.project1.id,))
+        self.get(url)
+        tabs = self.find_all('#project-topbar')
+        self.assertEqual(len(tabs), 1,
+                         'should be a top bar shown for non-command-line builds')
diff --git a/bitbake/lib/toaster/toastergui/tests.py b/bitbake/lib/toaster/toastergui/tests.py
index 78b7c04..7192947 100644
--- a/bitbake/lib/toaster/toastergui/tests.py
+++ b/bitbake/lib/toaster/toastergui/tests.py
@@ -764,139 +764,6 @@ class AllProjectsPageTests(TestCase):
         self.assertEqual(soup.find('a')['href'], expected_url,
                          'link on project name should point to configuration')
 
-class ProjectBuildsPageTests(TestCase):
-    """ Test data at /project/X/builds is displayed correctly """
-
-    def setUp(self):
-        bbv = BitbakeVersion.objects.create(name="bbv1", giturl="/tmp/",
-                                            branch="master", dirpath="")
-        release = Release.objects.create(name="release1",
-                                         bitbake_version=bbv)
-        self.project1 = Project.objects.create_project(name=PROJECT_NAME,
-                                                       release=release)
-        self.project1.save()
-
-        self.project2 = Project.objects.create_project(name=PROJECT_NAME,
-                                                       release=release)
-        self.project2.save()
-
-        self.default_project = Project.objects.create_project(
-            name=CLI_BUILDS_PROJECT_NAME,
-            release=release
-        )
-        self.default_project.is_default = True
-        self.default_project.save()
-
-        # parameters for builds to associate with the projects
-        now = timezone.now()
-
-        self.project1_build_success = {
-            "project": self.project1,
-            "started_on": now,
-            "completed_on": now,
-            "outcome": Build.SUCCEEDED
-        }
-
-        self.project1_build_in_progress = {
-            "project": self.project1,
-            "started_on": now,
-            "completed_on": now,
-            "outcome": Build.IN_PROGRESS
-        }
-
-        self.project2_build_success = {
-            "project": self.project2,
-            "started_on": now,
-            "completed_on": now,
-            "outcome": Build.SUCCEEDED
-        }
-
-        self.project2_build_in_progress = {
-            "project": self.project2,
-            "started_on": now,
-            "completed_on": now,
-            "outcome": Build.IN_PROGRESS
-        }
-
-    def _get_rows_for_project(self, project_id):
-        """ Helper to retrieve HTML rows for a project """
-        url = reverse("projectbuilds", args=(project_id,))
-        response = self.client.get(url, {'format': 'json'}, follow=True)
-        data = json.loads(response.content)
-        return data['rows']
-
-    def test_show_builds_for_project(self):
-        """ Builds for a project should be displayed """
-        Build.objects.create(**self.project1_build_success)
-        Build.objects.create(**self.project1_build_success)
-        build_rows = self._get_rows_for_project(self.project1.id)
-        self.assertEqual(len(build_rows), 2)
-
-    def test_show_builds_project_only(self):
-        """ Builds for other projects should be excluded """
-        Build.objects.create(**self.project1_build_success)
-        Build.objects.create(**self.project1_build_success)
-        Build.objects.create(**self.project1_build_success)
-
-        # shouldn't see these two
-        Build.objects.create(**self.project2_build_success)
-        Build.objects.create(**self.project2_build_in_progress)
-
-        build_rows = self._get_rows_for_project(self.project1.id)
-        self.assertEqual(len(build_rows), 3)
-
-    def test_builds_exclude_in_progress(self):
-        """ "in progress" builds should not be shown """
-        Build.objects.create(**self.project1_build_success)
-        Build.objects.create(**self.project1_build_success)
-
-        # shouldn't see this one
-        Build.objects.create(**self.project1_build_in_progress)
-
-        # shouldn't see these two either, as they belong to a different project
-        Build.objects.create(**self.project2_build_success)
-        Build.objects.create(**self.project2_build_in_progress)
-
-        build_rows = self._get_rows_for_project(self.project1.id)
-        self.assertEqual(len(build_rows), 2)
-
-    def test_tasks_in_projectbuilds(self):
-        """ Task should be shown as suffix on build name """
-        build = Build.objects.create(**self.project1_build_success)
-        Target.objects.create(build=build, target='bash', task='clean')
-
-        url = reverse('projectbuilds', args=(self.project1.id,))
-        response = self.client.get(url, {'format': 'json'}, follow=True)
-        data = json.loads(response.content)
-        cell = data['rows'][0]['static:target']
-
-        result = re.findall('^ +bash:clean', cell, re.MULTILINE)
-        self.assertEqual(len(result), 1)
-
-    def test_cli_builds_hides_tabs(self):
-        """
-        Display for command line builds should hide tabs;
-        note that the latest builds section is already tested in
-        AllBuildsPageTests, as the template is the same
-        """
-        url = reverse("projectbuilds", args=(self.default_project.id,))
-        response = self.client.get(url, follow=True)
-        soup = BeautifulSoup(response.content)
-        tabs = soup.select('#project-topbar')
-        self.assertEqual(len(tabs), 0,
-                         'should be no top bar shown for command line builds')
-
-    def test_non_cli_builds_has_tabs(self):
-        """
-        Non-command-line builds projects should show the tabs
-        """
-        url = reverse("projectbuilds", args=(self.project1.id,))
-        response = self.client.get(url, follow=True)
-        soup = BeautifulSoup(response.content)
-        tabs = soup.select('#project-topbar')
-        self.assertEqual(len(tabs), 1,
-                         'should be a top bar shown for non-command-line builds')
-
 class BuildDashboardTests(TestCase):
     """ Tests for the build dashboard /build/X """
 
-- 
Elliot Smith
Software Engineer
Intel OTC

---------------------------------------------------------------------
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/5] toaster-tests: migrate all projects page tests to Selenium
  2016-03-16 13:10 [PATCH 0/5] Migrate Toaster tests to Selenium Elliot Smith
                   ` (2 preceding siblings ...)
  2016-03-16 13:10 ` [PATCH 3/5] toaster-tests: migrate project builds " Elliot Smith
@ 2016-03-16 13:10 ` Elliot Smith
  2016-03-16 13:10 ` [PATCH 5/5] toaster-tests: migrate landing " Elliot Smith
  4 siblings, 0 replies; 10+ messages in thread
From: Elliot Smith @ 2016-03-16 13:10 UTC (permalink / raw)
  To: toaster

Signed-off-by: Elliot Smith <elliot.smith@intel.com>
---
 .../tests_browser/test_all_projects_page.py        | 214 +++++++++++++++++++++
 bitbake/lib/toaster/toastergui/tests.py            | 197 -------------------
 2 files changed, 214 insertions(+), 197 deletions(-)
 create mode 100644 bitbake/lib/toaster/tests_browser/test_all_projects_page.py

diff --git a/bitbake/lib/toaster/tests_browser/test_all_projects_page.py b/bitbake/lib/toaster/tests_browser/test_all_projects_page.py
new file mode 100644
index 0000000..9b1cc2e
--- /dev/null
+++ b/bitbake/lib/toaster/tests_browser/test_all_projects_page.py
@@ -0,0 +1,214 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import re
+
+from django.core.urlresolvers import reverse
+from django.utils import timezone
+from toaster.tests_browser.selenium_helpers import SeleniumTestCase
+
+from orm.models import BitbakeVersion, Release, Project, Build
+from orm.models import ProjectVariable
+
+class TestAllProjectsPage(SeleniumTestCase):
+    """ Browser tests for projects page /projects/ """
+
+    PROJECT_NAME = 'test project'
+    CLI_BUILDS_PROJECT_NAME = 'command line builds'
+    MACHINE_NAME = 'delorean'
+
+    def setUp(self):
+        """ Add default project manually """
+        project = Project.objects.create_project(self.CLI_BUILDS_PROJECT_NAME, None)
+        self.default_project = project
+        self.default_project.is_default = True
+        self.default_project.save()
+
+        # this project is only set for some of the tests
+        self.project = None
+
+        self.release = None
+
+    def _add_build_to_default_project(self):
+        """ Add a build to the default project (not used in all tests) """
+        now = timezone.now()
+        build = Build.objects.create(project=self.default_project,
+                                     started_on=now,
+                                     completed_on=now)
+        build.save()
+
+    def _add_non_default_project(self):
+        """ Add another project """
+        bbv = BitbakeVersion.objects.create(name='test bbv', giturl='/tmp/',
+                                            branch='master', dirpath='')
+        self.release = Release.objects.create(name='test release',
+                                              branch_name='master',
+                                              bitbake_version=bbv)
+        self.project = Project.objects.create_project(self.PROJECT_NAME, self.release)
+        self.project.is_default = False
+        self.project.save()
+
+        # fake the MACHINE variable
+        project_var = ProjectVariable.objects.create(project=self.project,
+                                                     name='MACHINE',
+                                                     value=self.MACHINE_NAME)
+        project_var.save()
+
+    def _get_row_for_project(self, project_name):
+        """ Get the HTML row for a project, or None if not found """
+        self.wait_until_present('#projectstable tbody tr')
+        rows = self.find_all('#projectstable tbody tr')
+
+        # find the row with a project name matching the one supplied
+        found_row = None
+        for row in rows:
+            if re.search(project_name, row.get_attribute('innerHTML')):
+                found_row = row
+                break
+
+        return found_row
+
+    def test_default_project_hidden(self):
+        """
+        The default project should be hidden if it has no builds
+        and we should see the "no results" area
+        """
+        url = reverse('all-projects')
+        self.get(url)
+        self.wait_until_visible('#no-results-projectstable')
+
+        rows = self.find_all('#projectstable tbody tr')
+        self.assertEqual(len(rows), 0, 'should be no projects displayed')
+
+    def test_default_project_has_build(self):
+        """ The default project should be shown if it has builds """
+        self._add_build_to_default_project()
+
+        url = reverse('all-projects')
+        self.get(url)
+
+        default_project_row = self._get_row_for_project(self.default_project.name)
+
+        self.assertNotEqual(default_project_row, None,
+                            'default project "cli builds" should be in page')
+
+    def test_default_project_release(self):
+        """
+        The release for the default project should display as
+        'Not applicable'
+        """
+        # need a build, otherwise project doesn't display at all
+        self._add_build_to_default_project()
+
+        # another project to test, which should show release
+        self._add_non_default_project()
+
+        self.get(reverse('all-projects'))
+
+        # find the row for the default project
+        default_project_row = self._get_row_for_project(self.default_project.name)
+
+        # check the release text for the default project
+        selector = 'span[data-project-field="release"] span.muted'
+        element = default_project_row.find_element_by_css_selector(selector)
+        text = element.text.strip()
+        self.assertEqual(text, 'Not applicable',
+                         'release should be "not applicable" for default project')
+
+        # find the row for the default project
+        other_project_row = self._get_row_for_project(self.project.name)
+
+        # check the link in the release cell for the other project
+        selector = 'span[data-project-field="release"] a'
+        element = other_project_row.find_element_by_css_selector(selector)
+        text = element.text.strip()
+        self.assertEqual(text, self.release.name,
+                         'release name should be shown for non-default project')
+
+    def test_default_project_machine(self):
+        """
+        The machine for the default project should display as
+        'Not applicable'
+        """
+        # need a build, otherwise project doesn't display at all
+        self._add_build_to_default_project()
+
+        # another project to test, which should show machine
+        self._add_non_default_project()
+
+        self.get(reverse('all-projects'))
+
+        # find the row for the default project
+        default_project_row = self._get_row_for_project(self.default_project.name)
+
+        # check the machine cell for the default project
+        selector = 'span[data-project-field="machine"] span.muted'
+        element = default_project_row.find_element_by_css_selector(selector)
+        text = element.text.strip()
+        self.assertEqual(text, 'Not applicable',
+                         'machine should be not applicable for default project')
+
+        # find the row for the default project
+        other_project_row = self._get_row_for_project(self.project.name)
+
+        # check the link in the machine cell for the other project
+        selector = 'span[data-project-field="machine"] a'
+        element = other_project_row.find_element_by_css_selector(selector)
+        text = element.text.strip()
+        self.assertEqual(text, self.MACHINE_NAME,
+                         'machine name should be shown for non-default project')
+
+    def test_project_page_links(self):
+        """
+        Test that links for the default project point to the builds
+        page /projects/X/builds for that project, and that links for
+        other projects point to their configuration pages /projects/X/
+        """
+
+        # need a build, otherwise project doesn't display at all
+        self._add_build_to_default_project()
+
+        # another project to test
+        self._add_non_default_project()
+
+        self.get(reverse('all-projects'))
+
+        # find the row for the default project
+        default_project_row = self._get_row_for_project(self.default_project.name)
+
+        # check the link on the name field
+        selector = 'span[data-project-field="name"] a'
+        element = default_project_row.find_element_by_css_selector(selector)
+        link_url = element.get_attribute('href').strip()
+        expected_url = reverse('projectbuilds', args=(self.default_project.id,))
+        msg = 'link on default project name should point to builds but was %s' % link_url
+        self.assertTrue(link_url.endswith(expected_url), msg)
+
+        # find the row for the other project
+        other_project_row = self._get_row_for_project(self.project.name)
+
+        # check the link for the other project
+        selector = 'span[data-project-field="name"] a'
+        element = other_project_row.find_element_by_css_selector(selector)
+        link_url = element.get_attribute('href').strip()
+        expected_url = reverse('project', args=(self.project.id,))
+        msg = 'link on project name should point to configuration but was %s' % link_url
+        self.assertTrue(link_url.endswith(expected_url), msg)
diff --git a/bitbake/lib/toaster/toastergui/tests.py b/bitbake/lib/toaster/toastergui/tests.py
index 7192947..6975ac1 100644
--- a/bitbake/lib/toaster/toastergui/tests.py
+++ b/bitbake/lib/toaster/toastergui/tests.py
@@ -493,7 +493,6 @@ class ViewTests(TestCase):
                                 "Changed page on table %s but first row is the "
                                 "same as the previous page" % name)
 
-
 class LandingPageTests(TestCase):
     """ Tests for redirects on the landing page """
     # disable bogus pylint message error:
@@ -568,202 +567,6 @@ class LandingPageTests(TestCase):
         self.assertTrue('/builds' in response.url,
                         'should redirect to builds')
 
-class AllProjectsPageTests(TestCase):
-    """ Tests for projects page /projects/ """
-
-    MACHINE_NAME = 'delorean'
-
-    def setUp(self):
-        """ Add default project manually """
-        project = Project.objects.create_project(CLI_BUILDS_PROJECT_NAME, None)
-        self.default_project = project
-        self.default_project.is_default = True
-        self.default_project.save()
-
-        # this project is only set for some of the tests
-        self.project = None
-
-        self.release = None
-
-    def _add_build_to_default_project(self):
-        """ Add a build to the default project (not used in all tests) """
-        now = timezone.now()
-        build = Build.objects.create(project=self.default_project,
-                                     started_on=now,
-                                     completed_on=now)
-        build.save()
-
-    def _add_non_default_project(self):
-        """ Add another project """
-        bbv = BitbakeVersion.objects.create(name="test bbv", giturl="/tmp/",
-                                            branch="master", dirpath="")
-        self.release = Release.objects.create(name="test release",
-                                              branch_name="master",
-                                              bitbake_version=bbv)
-        self.project = Project.objects.create_project(PROJECT_NAME, self.release)
-        self.project.is_default = False
-        self.project.save()
-
-        # fake the MACHINE variable
-        project_var = ProjectVariable.objects.create(project=self.project,
-                                                     name='MACHINE',
-                                                     value=self.MACHINE_NAME)
-        project_var.save()
-
-    def _get_row_for_project(self, data, project_id):
-        """ Get the object representing the table data for a project """
-        return [row for row in data['rows'] if row['id'] == project_id][0]
-
-    def test_default_project_hidden(self):
-        """ The default project should be hidden if it has no builds """
-        params = {"count": 10, "orderby": "updated:-", "page": 1}
-        response = self.client.get(reverse('all-projects'), params)
-
-        self.assertTrue(not('tr class="data"' in response.content),
-                        'should be no project rows in the page')
-        self.assertTrue(not(CLI_BUILDS_PROJECT_NAME in response.content),
-                        'default project "cli builds" should not be in page')
-
-    def test_default_project_has_build(self):
-        """ The default project should be shown if it has builds """
-        self._add_build_to_default_project()
-
-        params = {"count": 10, "orderby": "updated:-", "page": 1}
-
-        response = self.client.get(
-            reverse('all-projects'),
-            {'format': 'json'},
-            params
-        )
-
-        data = json.loads(response.content)
-
-        # find the row for the default project
-        default_project_row = self._get_row_for_project(data, self.default_project.id)
-
-        # check its name template has the correct text
-        self.assertEqual(default_project_row['name'], CLI_BUILDS_PROJECT_NAME,
-                        'default project "cli builds" should be in page')
-
-    def test_default_project_release(self):
-        """
-        The release for the default project should display as
-        'Not applicable'
-        """
-        # need a build, otherwise project doesn't display at all
-        self._add_build_to_default_project()
-
-        # another project to test, which should show release
-        self._add_non_default_project()
-
-        response = self.client.get(
-            reverse('all-projects'),
-            {'format': 'json'},
-            follow=True
-        )
-
-        data = json.loads(response.content)
-
-        # used to find the correct span in the template output
-        attrs = {'data-project-field': 'release'}
-
-        # find the row for the default project
-        default_project_row = self._get_row_for_project(data, self.default_project.id)
-
-        # check the release text for the default project
-        soup = BeautifulSoup(default_project_row['static:release'])
-        text = soup.find('span', attrs=attrs).select('span.muted')[0].text
-        self.assertEqual(text, 'Not applicable',
-                         'release should be not applicable for default project')
-
-        # find the row for the default project
-        other_project_row = self._get_row_for_project(data, self.project.id)
-
-        # check the link in the release cell for the other project
-        soup = BeautifulSoup(other_project_row['static:release'])
-        text = soup.find('span', attrs=attrs).select('a')[0].text.strip()
-        self.assertEqual(text, self.release.name,
-                         'release name should be shown for non-default project')
-
-    def test_default_project_machine(self):
-        """
-        The machine for the default project should display as
-        'Not applicable'
-        """
-        # need a build, otherwise project doesn't display at all
-        self._add_build_to_default_project()
-
-        # another project to test, which should show machine
-        self._add_non_default_project()
-
-        response = self.client.get(
-            reverse('all-projects'),
-            {'format': 'json'},
-            follow=True
-        )
-
-        data = json.loads(response.content)
-
-        # used to find the correct span in the template output
-        attrs = {'data-project-field': 'machine'}
-
-        # find the row for the default project
-        default_project_row = self._get_row_for_project(data, self.default_project.id)
-
-        # check the machine cell for the default project
-        soup = BeautifulSoup(default_project_row['static:machine'])
-        text = soup.find('span', attrs=attrs).select('span.muted')[0].text.strip()
-        self.assertEqual(text, 'Not applicable',
-            'machine should be not applicable for default project')
-
-        # find the row for the default project
-        other_project_row = self._get_row_for_project(data, self.project.id)
-
-        # check the link in the machine cell for the other project
-        soup = BeautifulSoup(other_project_row['static:machine'])
-        text = soup.find('span', attrs=attrs).find('a').text.strip()
-        self.assertEqual(text, self.MACHINE_NAME,
-                         'machine name should be shown for non-default project')
-
-    def test_project_page_links(self):
-        """
-        Test that links for the default project point to the builds
-        page /projects/X/builds for that project, and that links for
-        other projects point to their configuration pages /projects/X/
-        """
-
-        # need a build, otherwise project doesn't display at all
-        self._add_build_to_default_project()
-
-        # another project to test
-        self._add_non_default_project()
-
-        response = self.client.get(
-            reverse('all-projects'),
-            {'format': 'json'},
-            follow=True
-        )
-
-        data = json.loads(response.content)
-
-        # find the row for the default project
-        default_project_row = self._get_row_for_project(data, self.default_project.id)
-
-        # check the link on the name field
-        soup = BeautifulSoup(default_project_row['static:name'])
-        expected_url = reverse('projectbuilds', args=(self.default_project.id,))
-        self.assertEqual(soup.find('a')['href'], expected_url,
-                         'link on default project name should point to builds')
-
-        # find the row for the other project
-        other_project_row = self._get_row_for_project(data, self.project.id)
-
-        # check the link for the other project
-        soup = BeautifulSoup(other_project_row['static:name'])
-        expected_url = reverse('project', args=(self.project.id,))
-        self.assertEqual(soup.find('a')['href'], expected_url,
-                         'link on project name should point to configuration')
-
 class BuildDashboardTests(TestCase):
     """ Tests for the build dashboard /build/X """
 
-- 
Elliot Smith
Software Engineer
Intel OTC

---------------------------------------------------------------------
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 5/5] toaster-tests: migrate landing page tests to Selenium
  2016-03-16 13:10 [PATCH 0/5] Migrate Toaster tests to Selenium Elliot Smith
                   ` (3 preceding siblings ...)
  2016-03-16 13:10 ` [PATCH 4/5] toaster-tests: migrate all projects " Elliot Smith
@ 2016-03-16 13:10 ` Elliot Smith
  2016-03-31 14:41   ` Michael Wood
  4 siblings, 1 reply; 10+ messages in thread
From: Elliot Smith @ 2016-03-16 13:10 UTC (permalink / raw)
  To: toaster

Signed-off-by: Elliot Smith <elliot.smith@intel.com>
---
 .../lib/toaster/tests_browser/test_landing_page.py | 108 +++++++++++++++++++++
 bitbake/lib/toaster/toastergui/tests.py            |  74 --------------
 2 files changed, 108 insertions(+), 74 deletions(-)
 create mode 100644 bitbake/lib/toaster/tests_browser/test_landing_page.py

diff --git a/bitbake/lib/toaster/tests_browser/test_landing_page.py b/bitbake/lib/toaster/tests_browser/test_landing_page.py
new file mode 100644
index 0000000..8343630
--- /dev/null
+++ b/bitbake/lib/toaster/tests_browser/test_landing_page.py
@@ -0,0 +1,108 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from django.core.urlresolvers import reverse
+from django.utils import timezone
+from toaster.tests_browser.selenium_helpers import SeleniumTestCase
+
+from orm.models import Project, Build
+
+class TestLandingPage(SeleniumTestCase):
+    """ Tests for redirects on the landing page """
+
+    PROJECT_NAME = 'test project'
+    LANDING_PAGE_TITLE = 'This is Toaster'
+    CLI_BUILDS_PROJECT_NAME = 'command line builds'
+
+    def setUp(self):
+        """ Add default project manually """
+        self.project = Project.objects.create_project(
+            self.CLI_BUILDS_PROJECT_NAME,
+            None
+        )
+        self.project.is_default = True
+        self.project.save()
+
+    def test_only_default_project(self):
+        """
+        No projects except default
+        => should see the landing page
+        """
+        self.get(reverse('landing'))
+        self.assertTrue(self.LANDING_PAGE_TITLE in self.get_page_source())
+
+    def test_default_project_has_build(self):
+        """
+        Default project has a build, no other projects
+        => should see the builds page
+        """
+        now = timezone.now()
+        build = Build.objects.create(project=self.project,
+                                     started_on=now,
+                                     completed_on=now)
+        build.save()
+
+        self.get(reverse('landing'))
+
+        elements = self.find_all('#allbuildstable')
+        self.assertEqual(len(elements), 1, 'should redirect to builds')
+        content = self.get_page_source()
+        self.assertFalse(self.PROJECT_NAME in content,
+                         'should not show builds for project %s' % self.PROJECT_NAME)
+        self.assertTrue(self.CLI_BUILDS_PROJECT_NAME in content,
+                        'should show builds for cli project')
+
+    def test_user_project_exists(self):
+        """
+        User has added a project (without builds)
+        => should see the projects page
+        """
+        user_project = Project.objects.create_project('foo', None)
+        user_project.save()
+
+        self.get(reverse('landing'))
+
+        elements = self.find_all('#projectstable')
+        self.assertEqual(len(elements), 1, 'should redirect to projects')
+
+    def test_user_project_has_build(self):
+        """
+        User has added a project (with builds), command line builds doesn't
+        => should see the builds page
+        """
+        user_project = Project.objects.create_project(self.PROJECT_NAME, None)
+        user_project.save()
+
+        now = timezone.now()
+        build = Build.objects.create(project=user_project,
+                                     started_on=now,
+                                     completed_on=now)
+        build.save()
+
+        self.get(reverse('landing'))
+
+        elements = self.find_all('#allbuildstable')
+        self.assertEqual(len(elements), 1, 'should redirect to builds')
+        content = self.get_page_source()
+        self.assertTrue(self.PROJECT_NAME in content,
+                        'should show builds for project %s' % self.PROJECT_NAME)
+        self.assertFalse(self.CLI_BUILDS_PROJECT_NAME in content,
+                         'should not show builds for cli project')
diff --git a/bitbake/lib/toaster/toastergui/tests.py b/bitbake/lib/toaster/toastergui/tests.py
index 6975ac1..eebd1b7 100644
--- a/bitbake/lib/toaster/toastergui/tests.py
+++ b/bitbake/lib/toaster/toastergui/tests.py
@@ -493,80 +493,6 @@ class ViewTests(TestCase):
                                 "Changed page on table %s but first row is the "
                                 "same as the previous page" % name)
 
-class LandingPageTests(TestCase):
-    """ Tests for redirects on the landing page """
-    # disable bogus pylint message error:
-    # "Instance of 'WSGIRequest' has no 'url' member (no-member)"
-    # (see https://github.com/landscapeio/pylint-django/issues/42)
-    # pylint: disable=E1103
-
-    LANDING_PAGE_TITLE = 'This is Toaster'
-
-    def setUp(self):
-        """ Add default project manually """
-        self.project = Project.objects.create_project('foo', None)
-        self.project.is_default = True
-        self.project.save()
-
-    def test_only_default_project(self):
-        """
-        No projects except default
-        => get the landing page
-        """
-        response = self.client.get(reverse('landing'))
-        self.assertTrue(self.LANDING_PAGE_TITLE in response.content)
-
-    def test_default_project_has_build(self):
-        """
-        Default project has a build, no other projects
-        => get the builds page
-        """
-        now = timezone.now()
-        build = Build.objects.create(project=self.project,
-                                     started_on=now,
-                                     completed_on=now)
-        build.save()
-
-        response = self.client.get(reverse('landing'))
-        self.assertEqual(response.status_code, 302,
-                         'response should be a redirect')
-        self.assertTrue('/builds' in response.url,
-                        'should redirect to builds')
-
-    def test_user_project_exists(self):
-        """
-        User has added a project (without builds)
-        => get the projects page
-        """
-        user_project = Project.objects.create_project('foo', None)
-        user_project.save()
-
-        response = self.client.get(reverse('landing'))
-        self.assertEqual(response.status_code, 302,
-                         'response should be a redirect')
-        self.assertTrue('/projects' in response.url,
-                        'should redirect to projects')
-
-    def test_user_project_has_build(self):
-        """
-        User has added a project (with builds)
-        => get the builds page
-        """
-        user_project = Project.objects.create_project('foo', None)
-        user_project.save()
-
-        now = timezone.now()
-        build = Build.objects.create(project=user_project,
-                                     started_on=now,
-                                     completed_on=now)
-        build.save()
-
-        response = self.client.get(reverse('landing'))
-        self.assertEqual(response.status_code, 302,
-                         'response should be a redirect')
-        self.assertTrue('/builds' in response.url,
-                        'should redirect to builds')
-
 class BuildDashboardTests(TestCase):
     """ Tests for the build dashboard /build/X """
 
-- 
Elliot Smith
Software Engineer
Intel OTC

---------------------------------------------------------------------
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 5/5] toaster-tests: migrate landing page tests to Selenium
  2016-03-16 13:10 ` [PATCH 5/5] toaster-tests: migrate landing " Elliot Smith
@ 2016-03-31 14:41   ` Michael Wood
  2016-03-31 15:06     ` Smith, Elliot
  0 siblings, 1 reply; 10+ messages in thread
From: Michael Wood @ 2016-03-31 14:41 UTC (permalink / raw)
  To: toaster

Hijacking this with a bit of an RFC, but as I'm looking at tests at the 
moment, shall we start consolidating the tests in a single directory?

I was thinking:

├──bitbake/lib/toaster/tests
│   ├── browser
│   ├── views
│   ├── build
│   ├── api
│   ├── static
...etc

usage ./manage.py test tests [or tests.views etc]

Michael

On 16/03/16 13:10, Elliot Smith wrote:
> Signed-off-by: Elliot Smith <elliot.smith@intel.com>
> ---
>   .../lib/toaster/tests_browser/test_landing_page.py | 108 +++++++++++++++++++++
>   bitbake/lib/toaster/toastergui/tests.py            |  74 --------------
>   2 files changed, 108 insertions(+), 74 deletions(-)
>   create mode 100644 bitbake/lib/toaster/tests_browser/test_landing_page.py
>
> diff --git a/bitbake/lib/toaster/tests_browser/test_landing_page.py b/bitbake/lib/toaster/tests_browser/test_landing_page.py
> new file mode 100644
> index 0000000..8343630
> --- /dev/null
> +++ b/bitbake/lib/toaster/tests_browser/test_landing_page.py
> @@ -0,0 +1,108 @@
> +#! /usr/bin/env python
> +# ex:ts=4:sw=4:sts=4:et
> +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
> +#
> +# BitBake Toaster Implementation
> +#
> +# Copyright (C) 2013-2016 Intel Corporation
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License version 2 as
> +# published by the Free Software Foundation.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License along
> +# with this program; if not, write to the Free Software Foundation, Inc.,
> +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> +
> +from django.core.urlresolvers import reverse
> +from django.utils import timezone
> +from toaster.tests_browser.selenium_helpers import SeleniumTestCase
> +
> +from orm.models import Project, Build
> +
> +class TestLandingPage(SeleniumTestCase):
> +    """ Tests for redirects on the landing page """
> +
> +    PROJECT_NAME = 'test project'
> +    LANDING_PAGE_TITLE = 'This is Toaster'
> +    CLI_BUILDS_PROJECT_NAME = 'command line builds'
> +
> +    def setUp(self):
> +        """ Add default project manually """
> +        self.project = Project.objects.create_project(
> +            self.CLI_BUILDS_PROJECT_NAME,
> +            None
> +        )
> +        self.project.is_default = True
> +        self.project.save()
> +
> +    def test_only_default_project(self):
> +        """
> +        No projects except default
> +        => should see the landing page
> +        """
> +        self.get(reverse('landing'))
> +        self.assertTrue(self.LANDING_PAGE_TITLE in self.get_page_source())
> +
> +    def test_default_project_has_build(self):
> +        """
> +        Default project has a build, no other projects
> +        => should see the builds page
> +        """
> +        now = timezone.now()
> +        build = Build.objects.create(project=self.project,
> +                                     started_on=now,
> +                                     completed_on=now)
> +        build.save()
> +
> +        self.get(reverse('landing'))
> +
> +        elements = self.find_all('#allbuildstable')
> +        self.assertEqual(len(elements), 1, 'should redirect to builds')
> +        content = self.get_page_source()
> +        self.assertFalse(self.PROJECT_NAME in content,
> +                         'should not show builds for project %s' % self.PROJECT_NAME)
> +        self.assertTrue(self.CLI_BUILDS_PROJECT_NAME in content,
> +                        'should show builds for cli project')
> +
> +    def test_user_project_exists(self):
> +        """
> +        User has added a project (without builds)
> +        => should see the projects page
> +        """
> +        user_project = Project.objects.create_project('foo', None)
> +        user_project.save()
> +
> +        self.get(reverse('landing'))
> +
> +        elements = self.find_all('#projectstable')
> +        self.assertEqual(len(elements), 1, 'should redirect to projects')
> +
> +    def test_user_project_has_build(self):
> +        """
> +        User has added a project (with builds), command line builds doesn't
> +        => should see the builds page
> +        """
> +        user_project = Project.objects.create_project(self.PROJECT_NAME, None)
> +        user_project.save()
> +
> +        now = timezone.now()
> +        build = Build.objects.create(project=user_project,
> +                                     started_on=now,
> +                                     completed_on=now)
> +        build.save()
> +
> +        self.get(reverse('landing'))
> +
> +        elements = self.find_all('#allbuildstable')
> +        self.assertEqual(len(elements), 1, 'should redirect to builds')
> +        content = self.get_page_source()
> +        self.assertTrue(self.PROJECT_NAME in content,
> +                        'should show builds for project %s' % self.PROJECT_NAME)
> +        self.assertFalse(self.CLI_BUILDS_PROJECT_NAME in content,
> +                         'should not show builds for cli project')
> diff --git a/bitbake/lib/toaster/toastergui/tests.py b/bitbake/lib/toaster/toastergui/tests.py
> index 6975ac1..eebd1b7 100644
> --- a/bitbake/lib/toaster/toastergui/tests.py
> +++ b/bitbake/lib/toaster/toastergui/tests.py
> @@ -493,80 +493,6 @@ class ViewTests(TestCase):
>                                   "Changed page on table %s but first row is the "
>                                   "same as the previous page" % name)
>   
> -class LandingPageTests(TestCase):
> -    """ Tests for redirects on the landing page """
> -    # disable bogus pylint message error:
> -    # "Instance of 'WSGIRequest' has no 'url' member (no-member)"
> -    # (see https://github.com/landscapeio/pylint-django/issues/42)
> -    # pylint: disable=E1103
> -
> -    LANDING_PAGE_TITLE = 'This is Toaster'
> -
> -    def setUp(self):
> -        """ Add default project manually """
> -        self.project = Project.objects.create_project('foo', None)
> -        self.project.is_default = True
> -        self.project.save()
> -
> -    def test_only_default_project(self):
> -        """
> -        No projects except default
> -        => get the landing page
> -        """
> -        response = self.client.get(reverse('landing'))
> -        self.assertTrue(self.LANDING_PAGE_TITLE in response.content)
> -
> -    def test_default_project_has_build(self):
> -        """
> -        Default project has a build, no other projects
> -        => get the builds page
> -        """
> -        now = timezone.now()
> -        build = Build.objects.create(project=self.project,
> -                                     started_on=now,
> -                                     completed_on=now)
> -        build.save()
> -
> -        response = self.client.get(reverse('landing'))
> -        self.assertEqual(response.status_code, 302,
> -                         'response should be a redirect')
> -        self.assertTrue('/builds' in response.url,
> -                        'should redirect to builds')
> -
> -    def test_user_project_exists(self):
> -        """
> -        User has added a project (without builds)
> -        => get the projects page
> -        """
> -        user_project = Project.objects.create_project('foo', None)
> -        user_project.save()
> -
> -        response = self.client.get(reverse('landing'))
> -        self.assertEqual(response.status_code, 302,
> -                         'response should be a redirect')
> -        self.assertTrue('/projects' in response.url,
> -                        'should redirect to projects')
> -
> -    def test_user_project_has_build(self):
> -        """
> -        User has added a project (with builds)
> -        => get the builds page
> -        """
> -        user_project = Project.objects.create_project('foo', None)
> -        user_project.save()
> -
> -        now = timezone.now()
> -        build = Build.objects.create(project=user_project,
> -                                     started_on=now,
> -                                     completed_on=now)
> -        build.save()
> -
> -        response = self.client.get(reverse('landing'))
> -        self.assertEqual(response.status_code, 302,
> -                         'response should be a redirect')
> -        self.assertTrue('/builds' in response.url,
> -                        'should redirect to builds')
> -
>   class BuildDashboardTests(TestCase):
>       """ Tests for the build dashboard /build/X """
>   



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 5/5] toaster-tests: migrate landing page tests to Selenium
  2016-03-31 14:41   ` Michael Wood
@ 2016-03-31 15:06     ` Smith, Elliot
  2016-03-31 15:12       ` Michael Wood
  0 siblings, 1 reply; 10+ messages in thread
From: Smith, Elliot @ 2016-03-31 15:06 UTC (permalink / raw)
  To: Michael Wood; +Cc: toaster

[-- Attachment #1: Type: text/plain, Size: 9744 bytes --]

Sounds like a good idea to me. Do you want me to amend my branch to start
the ball rolling?

Elliot

On 31 March 2016 at 15:41, Michael Wood <michael.g.wood@intel.com> wrote:

> Hijacking this with a bit of an RFC, but as I'm looking at tests at the
> moment, shall we start consolidating the tests in a single directory?
>
> I was thinking:
>
> ├──bitbake/lib/toaster/tests
> │   ├── browser
> │   ├── views
> │   ├── build
> │   ├── api
> │   ├── static
> ...etc
>
> usage ./manage.py test tests [or tests.views etc]
>
> Michael
>
>
> On 16/03/16 13:10, Elliot Smith wrote:
>
>> Signed-off-by: Elliot Smith <elliot.smith@intel.com>
>> ---
>>   .../lib/toaster/tests_browser/test_landing_page.py | 108
>> +++++++++++++++++++++
>>   bitbake/lib/toaster/toastergui/tests.py            |  74 --------------
>>   2 files changed, 108 insertions(+), 74 deletions(-)
>>   create mode 100644
>> bitbake/lib/toaster/tests_browser/test_landing_page.py
>>
>> diff --git a/bitbake/lib/toaster/tests_browser/test_landing_page.py
>> b/bitbake/lib/toaster/tests_browser/test_landing_page.py
>> new file mode 100644
>> index 0000000..8343630
>> --- /dev/null
>> +++ b/bitbake/lib/toaster/tests_browser/test_landing_page.py
>> @@ -0,0 +1,108 @@
>> +#! /usr/bin/env python
>> +# ex:ts=4:sw=4:sts=4:et
>> +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
>> +#
>> +# BitBake Toaster Implementation
>> +#
>> +# Copyright (C) 2013-2016 Intel Corporation
>> +#
>> +# This program is free software; you can redistribute it and/or modify
>> +# it under the terms of the GNU General Public License version 2 as
>> +# published by the Free Software Foundation.
>> +#
>> +# This program is distributed in the hope that it will be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +# GNU General Public License for more details.
>> +#
>> +# You should have received a copy of the GNU General Public License along
>> +# with this program; if not, write to the Free Software Foundation, Inc.,
>> +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
>> +
>> +from django.core.urlresolvers import reverse
>> +from django.utils import timezone
>> +from toaster.tests_browser.selenium_helpers import SeleniumTestCase
>> +
>> +from orm.models import Project, Build
>> +
>> +class TestLandingPage(SeleniumTestCase):
>> +    """ Tests for redirects on the landing page """
>> +
>> +    PROJECT_NAME = 'test project'
>> +    LANDING_PAGE_TITLE = 'This is Toaster'
>> +    CLI_BUILDS_PROJECT_NAME = 'command line builds'
>> +
>> +    def setUp(self):
>> +        """ Add default project manually """
>> +        self.project = Project.objects.create_project(
>> +            self.CLI_BUILDS_PROJECT_NAME,
>> +            None
>> +        )
>> +        self.project.is_default = True
>> +        self.project.save()
>> +
>> +    def test_only_default_project(self):
>> +        """
>> +        No projects except default
>> +        => should see the landing page
>> +        """
>> +        self.get(reverse('landing'))
>> +        self.assertTrue(self.LANDING_PAGE_TITLE in
>> self.get_page_source())
>> +
>> +    def test_default_project_has_build(self):
>> +        """
>> +        Default project has a build, no other projects
>> +        => should see the builds page
>> +        """
>> +        now = timezone.now()
>> +        build = Build.objects.create(project=self.project,
>> +                                     started_on=now,
>> +                                     completed_on=now)
>> +        build.save()
>> +
>> +        self.get(reverse('landing'))
>> +
>> +        elements = self.find_all('#allbuildstable')
>> +        self.assertEqual(len(elements), 1, 'should redirect to builds')
>> +        content = self.get_page_source()
>> +        self.assertFalse(self.PROJECT_NAME in content,
>> +                         'should not show builds for project %s' %
>> self.PROJECT_NAME)
>> +        self.assertTrue(self.CLI_BUILDS_PROJECT_NAME in content,
>> +                        'should show builds for cli project')
>> +
>> +    def test_user_project_exists(self):
>> +        """
>> +        User has added a project (without builds)
>> +        => should see the projects page
>> +        """
>> +        user_project = Project.objects.create_project('foo', None)
>> +        user_project.save()
>> +
>> +        self.get(reverse('landing'))
>> +
>> +        elements = self.find_all('#projectstable')
>> +        self.assertEqual(len(elements), 1, 'should redirect to projects')
>> +
>> +    def test_user_project_has_build(self):
>> +        """
>> +        User has added a project (with builds), command line builds
>> doesn't
>> +        => should see the builds page
>> +        """
>> +        user_project = Project.objects.create_project(self.PROJECT_NAME,
>> None)
>> +        user_project.save()
>> +
>> +        now = timezone.now()
>> +        build = Build.objects.create(project=user_project,
>> +                                     started_on=now,
>> +                                     completed_on=now)
>> +        build.save()
>> +
>> +        self.get(reverse('landing'))
>> +
>> +        elements = self.find_all('#allbuildstable')
>> +        self.assertEqual(len(elements), 1, 'should redirect to builds')
>> +        content = self.get_page_source()
>> +        self.assertTrue(self.PROJECT_NAME in content,
>> +                        'should show builds for project %s' %
>> self.PROJECT_NAME)
>> +        self.assertFalse(self.CLI_BUILDS_PROJECT_NAME in content,
>> +                         'should not show builds for cli project')
>> diff --git a/bitbake/lib/toaster/toastergui/tests.py
>> b/bitbake/lib/toaster/toastergui/tests.py
>> index 6975ac1..eebd1b7 100644
>> --- a/bitbake/lib/toaster/toastergui/tests.py
>> +++ b/bitbake/lib/toaster/toastergui/tests.py
>> @@ -493,80 +493,6 @@ class ViewTests(TestCase):
>>                                   "Changed page on table %s but first row
>> is the "
>>                                   "same as the previous page" % name)
>>   -class LandingPageTests(TestCase):
>> -    """ Tests for redirects on the landing page """
>> -    # disable bogus pylint message error:
>> -    # "Instance of 'WSGIRequest' has no 'url' member (no-member)"
>> -    # (see https://github.com/landscapeio/pylint-django/issues/42)
>> -    # pylint: disable=E1103
>> -
>> -    LANDING_PAGE_TITLE = 'This is Toaster'
>> -
>> -    def setUp(self):
>> -        """ Add default project manually """
>> -        self.project = Project.objects.create_project('foo', None)
>> -        self.project.is_default = True
>> -        self.project.save()
>> -
>> -    def test_only_default_project(self):
>> -        """
>> -        No projects except default
>> -        => get the landing page
>> -        """
>> -        response = self.client.get(reverse('landing'))
>> -        self.assertTrue(self.LANDING_PAGE_TITLE in response.content)
>> -
>> -    def test_default_project_has_build(self):
>> -        """
>> -        Default project has a build, no other projects
>> -        => get the builds page
>> -        """
>> -        now = timezone.now()
>> -        build = Build.objects.create(project=self.project,
>> -                                     started_on=now,
>> -                                     completed_on=now)
>> -        build.save()
>> -
>> -        response = self.client.get(reverse('landing'))
>> -        self.assertEqual(response.status_code, 302,
>> -                         'response should be a redirect')
>> -        self.assertTrue('/builds' in response.url,
>> -                        'should redirect to builds')
>> -
>> -    def test_user_project_exists(self):
>> -        """
>> -        User has added a project (without builds)
>> -        => get the projects page
>> -        """
>> -        user_project = Project.objects.create_project('foo', None)
>> -        user_project.save()
>> -
>> -        response = self.client.get(reverse('landing'))
>> -        self.assertEqual(response.status_code, 302,
>> -                         'response should be a redirect')
>> -        self.assertTrue('/projects' in response.url,
>> -                        'should redirect to projects')
>> -
>> -    def test_user_project_has_build(self):
>> -        """
>> -        User has added a project (with builds)
>> -        => get the builds page
>> -        """
>> -        user_project = Project.objects.create_project('foo', None)
>> -        user_project.save()
>> -
>> -        now = timezone.now()
>> -        build = Build.objects.create(project=user_project,
>> -                                     started_on=now,
>> -                                     completed_on=now)
>> -        build.save()
>> -
>> -        response = self.client.get(reverse('landing'))
>> -        self.assertEqual(response.status_code, 302,
>> -                         'response should be a redirect')
>> -        self.assertTrue('/builds' in response.url,
>> -                        'should redirect to builds')
>> -
>>   class BuildDashboardTests(TestCase):
>>       """ Tests for the build dashboard /build/X """
>>
>>
>
> --
> _______________________________________________
> toaster mailing list
> toaster@yoctoproject.org
> https://lists.yoctoproject.org/listinfo/toaster
>



-- 
Elliot Smith
Software Engineer
Intel Open Source Technology Centre

[-- Attachment #2: Type: text/html, Size: 12336 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 5/5] toaster-tests: migrate landing page tests to Selenium
  2016-03-31 15:06     ` Smith, Elliot
@ 2016-03-31 15:12       ` Michael Wood
  2016-03-31 19:04         ` Michael Wood
  0 siblings, 1 reply; 10+ messages in thread
From: Michael Wood @ 2016-03-31 15:12 UTC (permalink / raw)
  To: Smith, Elliot; +Cc: toaster

Yes that'd be great.

Michael

On 31/03/16 16:06, Smith, Elliot wrote:
> Sounds like a good idea to me. Do you want me to amend my branch to 
> start the ball rolling?
>
> Elliot
>
> On 31 March 2016 at 15:41, Michael Wood <michael.g.wood@intel.com 
> <mailto:michael.g.wood@intel.com>> wrote:
>
>     Hijacking this with a bit of an RFC, but as I'm looking at tests
>     at the moment, shall we start consolidating the tests in a single
>     directory?
>
>     I was thinking:
>
>     ├──bitbake/lib/toaster/tests
>     │   ├── browser
>     │   ├── views
>     │   ├── build
>     │   ├── api
>     │   ├── static
>     ...etc
>
>     usage ./manage.py test tests [or tests.views etc]
>
>     Michael
>
>
>     On 16/03/16 13:10, Elliot Smith wrote:
>
>         Signed-off-by: Elliot Smith <elliot.smith@intel.com
>         <mailto:elliot.smith@intel.com>>
>         ---
>           .../lib/toaster/tests_browser/test_landing_page.py | 108
>         +++++++++++++++++++++
>           bitbake/lib/toaster/toastergui/tests.py |  74 --------------
>           2 files changed, 108 insertions(+), 74 deletions(-)
>           create mode 100644
>         bitbake/lib/toaster/tests_browser/test_landing_page.py
>
>         diff --git
>         a/bitbake/lib/toaster/tests_browser/test_landing_page.py
>         b/bitbake/lib/toaster/tests_browser/test_landing_page.py
>         new file mode 100644
>         index 0000000..8343630
>         --- /dev/null
>         +++ b/bitbake/lib/toaster/tests_browser/test_landing_page.py
>         @@ -0,0 +1,108 @@
>         +#! /usr/bin/env python
>         +# ex:ts=4:sw=4:sts=4:et
>         +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
>         +#
>         +# BitBake Toaster Implementation
>         +#
>         +# Copyright (C) 2013-2016 Intel Corporation
>         +#
>         +# This program is free software; you can redistribute it
>         and/or modify
>         +# it under the terms of the GNU General Public License
>         version 2 as
>         +# published by the Free Software Foundation.
>         +#
>         +# This program is distributed in the hope that it will be useful,
>         +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>         +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>         +# GNU General Public License for more details.
>         +#
>         +# You should have received a copy of the GNU General Public
>         License along
>         +# with this program; if not, write to the Free Software
>         Foundation, Inc.,
>         +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
>         +
>         +from django.core.urlresolvers import reverse
>         +from django.utils import timezone
>         +from toaster.tests_browser.selenium_helpers import
>         SeleniumTestCase
>         +
>         +from orm.models import Project, Build
>         +
>         +class TestLandingPage(SeleniumTestCase):
>         +    """ Tests for redirects on the landing page """
>         +
>         +    PROJECT_NAME = 'test project'
>         +    LANDING_PAGE_TITLE = 'This is Toaster'
>         +    CLI_BUILDS_PROJECT_NAME = 'command line builds'
>         +
>         +    def setUp(self):
>         +        """ Add default project manually """
>         +        self.project = Project.objects.create_project(
>         +            self.CLI_BUILDS_PROJECT_NAME,
>         +            None
>         +        )
>         +        self.project.is_default = True
>         +        self.project.save()
>         +
>         +    def test_only_default_project(self):
>         +        """
>         +        No projects except default
>         +        => should see the landing page
>         +        """
>         +        self.get(reverse('landing'))
>         +        self.assertTrue(self.LANDING_PAGE_TITLE in
>         self.get_page_source())
>         +
>         +    def test_default_project_has_build(self):
>         +        """
>         +        Default project has a build, no other projects
>         +        => should see the builds page
>         +        """
>         +        now = timezone.now()
>         +        build = Build.objects.create(project=self.project,
>         +                                     started_on=now,
>         +  completed_on=now)
>         +        build.save()
>         +
>         +        self.get(reverse('landing'))
>         +
>         +        elements = self.find_all('#allbuildstable')
>         +        self.assertEqual(len(elements), 1, 'should redirect
>         to builds')
>         +        content = self.get_page_source()
>         +        self.assertFalse(self.PROJECT_NAME in content,
>         +                         'should not show builds for project
>         %s' % self.PROJECT_NAME)
>         +        self.assertTrue(self.CLI_BUILDS_PROJECT_NAME in content,
>         +                        'should show builds for cli project')
>         +
>         +    def test_user_project_exists(self):
>         +        """
>         +        User has added a project (without builds)
>         +        => should see the projects page
>         +        """
>         +        user_project = Project.objects.create_project('foo',
>         None)
>         +        user_project.save()
>         +
>         +        self.get(reverse('landing'))
>         +
>         +        elements = self.find_all('#projectstable')
>         +        self.assertEqual(len(elements), 1, 'should redirect
>         to projects')
>         +
>         +    def test_user_project_has_build(self):
>         +        """
>         +        User has added a project (with builds), command line
>         builds doesn't
>         +        => should see the builds page
>         +        """
>         +        user_project =
>         Project.objects.create_project(self.PROJECT_NAME, None)
>         +        user_project.save()
>         +
>         +        now = timezone.now()
>         +        build = Build.objects.create(project=user_project,
>         +                                     started_on=now,
>         +  completed_on=now)
>         +        build.save()
>         +
>         +        self.get(reverse('landing'))
>         +
>         +        elements = self.find_all('#allbuildstable')
>         +        self.assertEqual(len(elements), 1, 'should redirect
>         to builds')
>         +        content = self.get_page_source()
>         +        self.assertTrue(self.PROJECT_NAME in content,
>         +                        'should show builds for project %s' %
>         self.PROJECT_NAME)
>         +        self.assertFalse(self.CLI_BUILDS_PROJECT_NAME in content,
>         +                         'should not show builds for cli
>         project')
>         diff --git a/bitbake/lib/toaster/toastergui/tests.py
>         b/bitbake/lib/toaster/toastergui/tests.py
>         index 6975ac1..eebd1b7 100644
>         --- a/bitbake/lib/toaster/toastergui/tests.py
>         +++ b/bitbake/lib/toaster/toastergui/tests.py
>         @@ -493,80 +493,6 @@ class ViewTests(TestCase):
>                                           "Changed page on table %s
>         but first row is the "
>                                           "same as the previous page"
>         % name)
>           -class LandingPageTests(TestCase):
>         -    """ Tests for redirects on the landing page """
>         -    # disable bogus pylint message error:
>         -    # "Instance of 'WSGIRequest' has no 'url' member (no-member)"
>         -    # (see
>         https://github.com/landscapeio/pylint-django/issues/42)
>         -    # pylint: disable=E1103
>         -
>         -    LANDING_PAGE_TITLE = 'This is Toaster'
>         -
>         -    def setUp(self):
>         -        """ Add default project manually """
>         -        self.project = Project.objects.create_project('foo',
>         None)
>         -        self.project.is_default = True
>         -        self.project.save()
>         -
>         -    def test_only_default_project(self):
>         -        """
>         -        No projects except default
>         -        => get the landing page
>         -        """
>         -        response = self.client.get(reverse('landing'))
>         -        self.assertTrue(self.LANDING_PAGE_TITLE in
>         response.content)
>         -
>         -    def test_default_project_has_build(self):
>         -        """
>         -        Default project has a build, no other projects
>         -        => get the builds page
>         -        """
>         -        now = timezone.now()
>         -        build = Build.objects.create(project=self.project,
>         -                                     started_on=now,
>         -  completed_on=now)
>         -        build.save()
>         -
>         -        response = self.client.get(reverse('landing'))
>         -        self.assertEqual(response.status_code, 302,
>         -                         'response should be a redirect')
>         -        self.assertTrue('/builds' in response.url,
>         -                        'should redirect to builds')
>         -
>         -    def test_user_project_exists(self):
>         -        """
>         -        User has added a project (without builds)
>         -        => get the projects page
>         -        """
>         -        user_project = Project.objects.create_project('foo',
>         None)
>         -        user_project.save()
>         -
>         -        response = self.client.get(reverse('landing'))
>         -        self.assertEqual(response.status_code, 302,
>         -                         'response should be a redirect')
>         -        self.assertTrue('/projects' in response.url,
>         -                        'should redirect to projects')
>         -
>         -    def test_user_project_has_build(self):
>         -        """
>         -        User has added a project (with builds)
>         -        => get the builds page
>         -        """
>         -        user_project = Project.objects.create_project('foo',
>         None)
>         -        user_project.save()
>         -
>         -        now = timezone.now()
>         -        build = Build.objects.create(project=user_project,
>         -                                     started_on=now,
>         -  completed_on=now)
>         -        build.save()
>         -
>         -        response = self.client.get(reverse('landing'))
>         -        self.assertEqual(response.status_code, 302,
>         -                         'response should be a redirect')
>         -        self.assertTrue('/builds' in response.url,
>         -                        'should redirect to builds')
>         -
>           class BuildDashboardTests(TestCase):
>               """ Tests for the build dashboard /build/X """
>
>
>     -- 
>     _______________________________________________
>     toaster mailing list
>     toaster@yoctoproject.org <mailto:toaster@yoctoproject.org>
>     https://lists.yoctoproject.org/listinfo/toaster
>
>
>
>
> -- 
> Elliot Smith
> Software Engineer
> Intel Open Source Technology Centre
>
> ---------------------------------------------------------------------
> Intel Corporation (UK) Limited
> Registered No. 1134945 (England)
> Registered Office: Pipers Way, Swindon SN3 1RJ
> VAT No: 860 2173 47
>
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
>



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 5/5] toaster-tests: migrate landing page tests to Selenium
  2016-03-31 15:12       ` Michael Wood
@ 2016-03-31 19:04         ` Michael Wood
  0 siblings, 0 replies; 10+ messages in thread
From: Michael Wood @ 2016-03-31 19:04 UTC (permalink / raw)
  To: Smith, Elliot; +Cc: toaster

Thanks this is great. Sent upstream and to toaster-next. I did a sed on 
the paths in the patches so that an additional commit to move the files 
into tests was no longer necessary.

For those following along, this makes running these selenium tests very 
easy, here it is for firefox:

(activate virtualenv if using)

$ cd ./bitbake/lib/toaster/
$ pip install -r ./tests/toaster-tests-requirements.txt
$ TOASTER_TESTS_BROWSER=firefox ./manage.py test tests.browser

Michael

On 31/03/16 16:12, Michael Wood wrote:
> Yes that'd be great.
>
> Michael
>
> On 31/03/16 16:06, Smith, Elliot wrote:
>> Sounds like a good idea to me. Do you want me to amend my branch to 
>> start the ball rolling?
>>
>> Elliot
>>
>> On 31 March 2016 at 15:41, Michael Wood <michael.g.wood@intel.com 
>> <mailto:michael.g.wood@intel.com>> wrote:
>>
>>     Hijacking this with a bit of an RFC, but as I'm looking at tests
>>     at the moment, shall we start consolidating the tests in a single
>>     directory?
>>
>>     I was thinking:
>>
>>     ├──bitbake/lib/toaster/tests
>>     │   ├── browser
>>     │   ├── views
>>     │   ├── build
>>     │   ├── api
>>     │   ├── static
>>     ...etc
>>
>>     usage ./manage.py test tests [or tests.views etc]
>>
>>     Michael
>>
>>
>>     On 16/03/16 13:10, Elliot Smith wrote:
>>
>>         Signed-off-by: Elliot Smith <elliot.smith@intel.com
>>         <mailto:elliot.smith@intel.com>>
>>         ---
>>           .../lib/toaster/tests_browser/test_landing_page.py | 108
>>         +++++++++++++++++++++
>>           bitbake/lib/toaster/toastergui/tests.py |  74 --------------
>>           2 files changed, 108 insertions(+), 74 deletions(-)
>>           create mode 100644
>>         bitbake/lib/toaster/tests_browser/test_landing_page.py
>>
>>         diff --git
>>         a/bitbake/lib/toaster/tests_browser/test_landing_page.py
>>         b/bitbake/lib/toaster/tests_browser/test_landing_page.py
>>         new file mode 100644
>>         index 0000000..8343630
>>         --- /dev/null
>>         +++ b/bitbake/lib/toaster/tests_browser/test_landing_page.py
>>         @@ -0,0 +1,108 @@
>>         +#! /usr/bin/env python
>>         +# ex:ts=4:sw=4:sts=4:et
>>         +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil 
>> -*-
>>         +#
>>         +# BitBake Toaster Implementation
>>         +#
>>         +# Copyright (C) 2013-2016 Intel Corporation
>>         +#
>>         +# This program is free software; you can redistribute it
>>         and/or modify
>>         +# it under the terms of the GNU General Public License
>>         version 2 as
>>         +# published by the Free Software Foundation.
>>         +#
>>         +# This program is distributed in the hope that it will be 
>> useful,
>>         +# but WITHOUT ANY WARRANTY; without even the implied 
>> warranty of
>>         +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>         +# GNU General Public License for more details.
>>         +#
>>         +# You should have received a copy of the GNU General Public
>>         License along
>>         +# with this program; if not, write to the Free Software
>>         Foundation, Inc.,
>>         +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
>>         +
>>         +from django.core.urlresolvers import reverse
>>         +from django.utils import timezone
>>         +from toaster.tests_browser.selenium_helpers import
>>         SeleniumTestCase
>>         +
>>         +from orm.models import Project, Build
>>         +
>>         +class TestLandingPage(SeleniumTestCase):
>>         +    """ Tests for redirects on the landing page """
>>         +
>>         +    PROJECT_NAME = 'test project'
>>         +    LANDING_PAGE_TITLE = 'This is Toaster'
>>         +    CLI_BUILDS_PROJECT_NAME = 'command line builds'
>>         +
>>         +    def setUp(self):
>>         +        """ Add default project manually """
>>         +        self.project = Project.objects.create_project(
>>         +            self.CLI_BUILDS_PROJECT_NAME,
>>         +            None
>>         +        )
>>         +        self.project.is_default = True
>>         +        self.project.save()
>>         +
>>         +    def test_only_default_project(self):
>>         +        """
>>         +        No projects except default
>>         +        => should see the landing page
>>         +        """
>>         +        self.get(reverse('landing'))
>>         +        self.assertTrue(self.LANDING_PAGE_TITLE in
>>         self.get_page_source())
>>         +
>>         +    def test_default_project_has_build(self):
>>         +        """
>>         +        Default project has a build, no other projects
>>         +        => should see the builds page
>>         +        """
>>         +        now = timezone.now()
>>         +        build = Build.objects.create(project=self.project,
>>         +                                     started_on=now,
>>         +  completed_on=now)
>>         +        build.save()
>>         +
>>         +        self.get(reverse('landing'))
>>         +
>>         +        elements = self.find_all('#allbuildstable')
>>         +        self.assertEqual(len(elements), 1, 'should redirect
>>         to builds')
>>         +        content = self.get_page_source()
>>         +        self.assertFalse(self.PROJECT_NAME in content,
>>         +                         'should not show builds for project
>>         %s' % self.PROJECT_NAME)
>>         +        self.assertTrue(self.CLI_BUILDS_PROJECT_NAME in 
>> content,
>>         +                        'should show builds for cli project')
>>         +
>>         +    def test_user_project_exists(self):
>>         +        """
>>         +        User has added a project (without builds)
>>         +        => should see the projects page
>>         +        """
>>         +        user_project = Project.objects.create_project('foo',
>>         None)
>>         +        user_project.save()
>>         +
>>         +        self.get(reverse('landing'))
>>         +
>>         +        elements = self.find_all('#projectstable')
>>         +        self.assertEqual(len(elements), 1, 'should redirect
>>         to projects')
>>         +
>>         +    def test_user_project_has_build(self):
>>         +        """
>>         +        User has added a project (with builds), command line
>>         builds doesn't
>>         +        => should see the builds page
>>         +        """
>>         +        user_project =
>>         Project.objects.create_project(self.PROJECT_NAME, None)
>>         +        user_project.save()
>>         +
>>         +        now = timezone.now()
>>         +        build = Build.objects.create(project=user_project,
>>         +                                     started_on=now,
>>         +  completed_on=now)
>>         +        build.save()
>>         +
>>         +        self.get(reverse('landing'))
>>         +
>>         +        elements = self.find_all('#allbuildstable')
>>         +        self.assertEqual(len(elements), 1, 'should redirect
>>         to builds')
>>         +        content = self.get_page_source()
>>         +        self.assertTrue(self.PROJECT_NAME in content,
>>         +                        'should show builds for project %s' %
>>         self.PROJECT_NAME)
>>         +        self.assertFalse(self.CLI_BUILDS_PROJECT_NAME in 
>> content,
>>         +                         'should not show builds for cli
>>         project')
>>         diff --git a/bitbake/lib/toaster/toastergui/tests.py
>>         b/bitbake/lib/toaster/toastergui/tests.py
>>         index 6975ac1..eebd1b7 100644
>>         --- a/bitbake/lib/toaster/toastergui/tests.py
>>         +++ b/bitbake/lib/toaster/toastergui/tests.py
>>         @@ -493,80 +493,6 @@ class ViewTests(TestCase):
>>                                           "Changed page on table %s
>>         but first row is the "
>>                                           "same as the previous page"
>>         % name)
>>           -class LandingPageTests(TestCase):
>>         -    """ Tests for redirects on the landing page """
>>         -    # disable bogus pylint message error:
>>         -    # "Instance of 'WSGIRequest' has no 'url' member 
>> (no-member)"
>>         -    # (see
>>         https://github.com/landscapeio/pylint-django/issues/42)
>>         -    # pylint: disable=E1103
>>         -
>>         -    LANDING_PAGE_TITLE = 'This is Toaster'
>>         -
>>         -    def setUp(self):
>>         -        """ Add default project manually """
>>         -        self.project = Project.objects.create_project('foo',
>>         None)
>>         -        self.project.is_default = True
>>         -        self.project.save()
>>         -
>>         -    def test_only_default_project(self):
>>         -        """
>>         -        No projects except default
>>         -        => get the landing page
>>         -        """
>>         -        response = self.client.get(reverse('landing'))
>>         -        self.assertTrue(self.LANDING_PAGE_TITLE in
>>         response.content)
>>         -
>>         -    def test_default_project_has_build(self):
>>         -        """
>>         -        Default project has a build, no other projects
>>         -        => get the builds page
>>         -        """
>>         -        now = timezone.now()
>>         -        build = Build.objects.create(project=self.project,
>>         -                                     started_on=now,
>>         -  completed_on=now)
>>         -        build.save()
>>         -
>>         -        response = self.client.get(reverse('landing'))
>>         -        self.assertEqual(response.status_code, 302,
>>         -                         'response should be a redirect')
>>         -        self.assertTrue('/builds' in response.url,
>>         -                        'should redirect to builds')
>>         -
>>         -    def test_user_project_exists(self):
>>         -        """
>>         -        User has added a project (without builds)
>>         -        => get the projects page
>>         -        """
>>         -        user_project = Project.objects.create_project('foo',
>>         None)
>>         -        user_project.save()
>>         -
>>         -        response = self.client.get(reverse('landing'))
>>         -        self.assertEqual(response.status_code, 302,
>>         -                         'response should be a redirect')
>>         -        self.assertTrue('/projects' in response.url,
>>         -                        'should redirect to projects')
>>         -
>>         -    def test_user_project_has_build(self):
>>         -        """
>>         -        User has added a project (with builds)
>>         -        => get the builds page
>>         -        """
>>         -        user_project = Project.objects.create_project('foo',
>>         None)
>>         -        user_project.save()
>>         -
>>         -        now = timezone.now()
>>         -        build = Build.objects.create(project=user_project,
>>         -                                     started_on=now,
>>         -  completed_on=now)
>>         -        build.save()
>>         -
>>         -        response = self.client.get(reverse('landing'))
>>         -        self.assertEqual(response.status_code, 302,
>>         -                         'response should be a redirect')
>>         -        self.assertTrue('/builds' in response.url,
>>         -                        'should redirect to builds')
>>         -
>>           class BuildDashboardTests(TestCase):
>>               """ Tests for the build dashboard /build/X """
>>
>>
>>     --     _______________________________________________
>>     toaster mailing list
>>     toaster@yoctoproject.org <mailto:toaster@yoctoproject.org>
>>     https://lists.yoctoproject.org/listinfo/toaster
>>
>>
>>
>>
>> -- 
>> Elliot Smith
>> Software Engineer
>> Intel Open Source Technology Centre
>>
>> ---------------------------------------------------------------------
>> Intel Corporation (UK) Limited
>> Registered No. 1134945 (England)
>> Registered Office: Pipers Way, Swindon SN3 1RJ
>> VAT No: 860 2173 47
>>
>> This e-mail and any attachments may contain confidential material for
>> the sole use of the intended recipient(s). Any review or distribution
>> by others is strictly prohibited. If you are not the intended
>> recipient, please contact the sender and delete all copies.
>>
>



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2016-03-31 19:04 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-16 13:10 [PATCH 0/5] Migrate Toaster tests to Selenium Elliot Smith
2016-03-16 13:10 ` [PATCH 1/5] toaster-tests: migrate to Selenium for UI tests Elliot Smith
2016-03-16 13:10 ` [PATCH 2/5] toaster-tests: migrate all builds page and project page tests to Selenium Elliot Smith
2016-03-16 13:10 ` [PATCH 3/5] toaster-tests: migrate project builds " Elliot Smith
2016-03-16 13:10 ` [PATCH 4/5] toaster-tests: migrate all projects " Elliot Smith
2016-03-16 13:10 ` [PATCH 5/5] toaster-tests: migrate landing " Elliot Smith
2016-03-31 14:41   ` Michael Wood
2016-03-31 15:06     ` Smith, Elliot
2016-03-31 15:12       ` Michael Wood
2016-03-31 19:04         ` Michael Wood

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.