From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by yocto-www.yoctoproject.org (Postfix, from userid 118) id 470C6E00D82; Mon, 4 Jul 2016 13:56:49 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on yocto-www.yoctoproject.org X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-HAM-Report: * -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low * trust * [209.85.192.176 listed in list.dnswl.org] * -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% * [score: 0.0000] * 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily * valid * -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature Received: from mail-pf0-f176.google.com (mail-pf0-f176.google.com [209.85.192.176]) by yocto-www.yoctoproject.org (Postfix) with ESMTP id 00C1BE00D6C for ; Mon, 4 Jul 2016 13:56:46 -0700 (PDT) Received: by mail-pf0-f176.google.com with SMTP id t190so63797634pfb.3 for ; Mon, 04 Jul 2016 13:56:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=intel-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=e6tmA/lOzNG4oF+CkwB7tHXGtnqEYWe6tXyt/vBJBN0=; b=w1CbXi/avvqiG4bXkoHn9iooI/nJTqnv8AZZ7wEnD9OObvNAXU0tL/nwmFI49MiK91 h3unSxyovCiGMS24M9K50YeePeZS3HhdrFs6QATrUAFdYazQMFcKJudtvdtyE4ZV7vfp NBO836PJoLU2O68tuJyLpCCDrNE3bRczlvLkemDWWEsiQiT2zG6iuBNk7C7Aq15lqM6H wuVdt+Fzqq8WSkGCfXx+RhdqwTVSznEjDduoXvhzwaflNEM4tS6LC82qfxdQuYpqEV3c BaKdp3lPX1G0ZhMh4rwrBj+/3y5pqvlanBLqgtiThdArVoDHDIFWM0qZ5noMi2BLUSDO hjEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=e6tmA/lOzNG4oF+CkwB7tHXGtnqEYWe6tXyt/vBJBN0=; b=h31+0hrXr2ibvAt+tZ4BOE3mqU3anQHEQAPe+sJ6iIBulG1fm3LF1ccVuKM8/iIctA dCaIHq10hZKv53C2ipsnqEodHL0JsDlyEundV1Jz8bDMwXRoH0CdxxmeQhI1522xCmhp A8OS5mUYzxvM5UwppqZ0SFwJz22kct2RGitmQMWPDIxPYprRpp4mm06568CgbmbtkU/u ilwb3Rv+Dh0HwLm10LK6o6y3sYwdmwV404/YcfX3UkmsVti2RRzKHYM8kX3v4hWoUcCt nQ/9xwdr8VOkTCsZyZKQ+Yby31TMHxEvmo+0WsPBvW3gOu8bzTQ7V1Z0reQOHxqV2fvb D4fg== X-Gm-Message-State: ALyK8tLEfvuXJT65K04ir+kjB86D7YQnPpWa/7CVfTD8qKtUTHtp+ls3OA/MF+MEGoOe+nJM X-Received: by 10.98.152.76 with SMTP id q73mr26214105pfd.38.1467665806090; Mon, 04 Jul 2016 13:56:46 -0700 (PDT) Received: from orion.ger.corp.intel.com (fmdmzpr04-ext.fm.intel.com. [192.55.55.39]) by smtp.gmail.com with ESMTPSA id b71sm7213602pfc.51.2016.07.04.13.56.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 04 Jul 2016 13:56:45 -0700 (PDT) From: Michael Wood To: toaster@yoctoproject.org Date: Mon, 4 Jul 2016 21:56:25 +0100 Message-Id: <1467665785-13108-5-git-send-email-michael.g.wood@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1467665785-13108-1-git-send-email-michael.g.wood@intel.com> References: <1467665785-13108-1-git-send-email-michael.g.wood@intel.com> Subject: [PATCH 4/4] toaster: tests Add selenium test for layerdetails page X-BeenThere: toaster@yoctoproject.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Web based interface for BitBake List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 04 Jul 2016 20:56:49 -0000 This tests: - Adding remove layer from project - Deleting layer - Editing layer fields Signed-off-by: Michael Wood --- .../tests/browser/test_layerdetails_page.py | 190 +++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 bitbake/lib/toaster/tests/browser/test_layerdetails_page.py diff --git a/bitbake/lib/toaster/tests/browser/test_layerdetails_page.py b/bitbake/lib/toaster/tests/browser/test_layerdetails_page.py new file mode 100644 index 0000000..fb1007f --- /dev/null +++ b/bitbake/lib/toaster/tests/browser/test_layerdetails_page.py @@ -0,0 +1,190 @@ +#! /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 tests.browser.selenium_helpers import SeleniumTestCase + +from orm.models import Layer, Layer_Version, Project, LayerSource, Release +from orm.models import BitbakeVersion + +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.common.by import By + + +class TestLayerDetailsPage(SeleniumTestCase): + """ Test layerdetails page works correctly """ + + def __init__(self, *args, **kwargs): + super(TestLayerDetailsPage, self).__init__(*args, **kwargs) + + self.initial_values = None + self.url = None + self.imported_layer_version = None + + def setUp(self): + release = Release.objects.create( + name='baz', + bitbake_version=BitbakeVersion.objects.create(name='v1') + ) + + # project to add new custom images to + self.project = Project.objects.create(name='foo', release=release) + + layer_source = LayerSource.objects.create( + sourcetype=LayerSource.TYPE_IMPORTED) + + name = "meta-imported" + vcs_url = "git://example.com/meta-imported" + subdir = "/layer" + gitrev = "d33d" + summary = "A imported layer" + description = "This was imported" + + imported_layer = Layer.objects.create(name=name, + vcs_url=vcs_url, + summary=summary, + description=description) + + self.imported_layer_version = Layer_Version.objects.create( + layer=imported_layer, + layer_source=layer_source, + branch=gitrev, + commit=gitrev, + dirpath=subdir, + project=self.project) + + self.initial_values = [name, vcs_url, subdir, gitrev, summary, + description] + self.url = reverse('layerdetails', + args=(self.project.pk, + self.imported_layer_version.pk)) + + def test_edit_layerdetails(self): + """ Edit all the editable fields for the layer refresh the page and + check that the new values exist""" + + self.get(self.url) + + self.click("#add-remove-layer-btn") + + # Open every edit box + for btn in self.find_all("dd .glyphicon-edit"): + btn.click() + + self.wait_until_visible("dd input") + + # Edit each value + for inputs in self.find_all("dd input[type=text]") + \ + self.find_all("dd textarea"): + # ignore the tt inputs (twitter typeahead input) + if "tt-" in inputs.get_attribute("class"): + continue + + value = inputs.get_attribute("value") + + self.assertTrue(value in self.initial_values, + "Expecting any of \"%s\"but got \"%s\"" % + (self.initial_values, value)) + + inputs.send_keys("-edited") + + for save_btn in self.find_all(".change-btn"): + save_btn.click() + + # Refresh the page to see if the new values are returned + self.get(self.url) + + new_values = ["%s-edited" % old_val + for old_val in self.initial_values] + + for inputs in self.find_all("dd input[type=text]") + \ + self.find_all("dd textarea"): + # ignore the tt inputs (twitter typeahead input) + if "tt-" in inputs.get_attribute("class"): + continue + + value = inputs.get_attribute("value") + + self.assertTrue(value in new_values, + "Expecting any of \"%s\"but got \"%s\"" % + (self.initial_values, value)) + + def test_delete_layer(self): + """ Delete the layer """ + + self.get(self.url) + + # Wait for the tables to load to avoid a race condition where the + # toaster tables have made an async request. If the layer is deleted + # before the request finishes it will cause an exception and fail this + # test. + wait = WebDriverWait(self.driver, 30) + + wait.until(EC.text_to_be_present_in_element( + (By.CLASS_NAME, + "table-count-recipestable"), "0")) + + wait.until(EC.text_to_be_present_in_element( + (By.CLASS_NAME, + "table-count-machinestable"), "0")) + + self.click('a[data-target="#delete-layer-modal"]') + self.wait_until_visible("#delete-layer-modal") + self.click("#layer-delete-confirmed") + + notification = self.wait_until_visible("#change-notification-msg") + expected_text = "You have deleted 1 layer from your project: %s" % \ + self.imported_layer_version.layer.name + + self.assertTrue(expected_text in notification.text, + "Expected notification text \"%s\" not found instead" + "it was \"%s\"" % + (expected_text, notification.text)) + + def test_addrm_to_project(self): + self.get(self.url) + + # Add the layer + self.click("#add-remove-layer-btn") + + notification = self.wait_until_visible("#change-notification-msg") + + expected_text = "You have added 1 layer to your project: %s" % \ + self.imported_layer_version.layer.name + + self.assertTrue(expected_text in notification.text, + "Expected notification text %s not found was " + " \"%s\" instead" % + (expected_text, notification.text)) + + # Remove the layer + self.click("#add-remove-layer-btn") + + notification = self.wait_until_visible("#change-notification-msg") + + expected_text = "You have removed 1 layer from your project: %s" % \ + self.imported_layer_version.layer.name + + self.assertTrue(expected_text in notification.text, + "Expected notification text %s not found was " + " \"%s\" instead" % + (expected_text, notification.text)) -- 2.7.4