From 2675f0be3aba91db5eab0220dbbc748edc2037da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Sun, 24 Jun 2018 21:28:50 +0200 Subject: [PATCH 01/23] CI: Enable selenium tests on Travis --- .travis.yml | 9 +++++++-- src/ci_scripts/travis.sh | 19 ++++++++++--------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7caa4daf22..5933b0c2fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,11 @@ matrix: addons: firefox: latest-esr env: TEST_SUITE=js_unittests + - addons: + firefox: "60.0.2esr" + env: + - TEST_SUITE=selenium + - DJANGO_VERSION=1.11 install: - . src/ci_scripts/travis_install.sh @@ -34,10 +39,10 @@ before_script: - . src/ci_scripts/travis_before_script.sh script: - - src/ci_scripts/travis.sh sqlite3 django$DJANGO_VERSION unittest + - src/ci_scripts/travis.sh after_success: - - . src/ci_scripts/travis_after_success.sh + - src/ci_scripts/travis_after_success.sh branches: only: diff --git a/src/ci_scripts/travis.sh b/src/ci_scripts/travis.sh index 35137f1aec..a883930b8e 100755 --- a/src/ci_scripts/travis.sh +++ b/src/ci_scripts/travis.sh @@ -1,9 +1,15 @@ #!/usr/bin/env bash +set -e + if [ "${TEST_SUITE}" == "js_unittests" ]; then cd $TRAVIS_BUILD_DIR/src grunt ci exit +elif [ "${TEST_SUITE}" == "selenium" ]; then + FLAGS="postgres django${DJANGO_VERSION} selenium" +else + FLAGS="sqlite3 django${DJANGO_VERSION} unittest" fi @@ -11,12 +17,11 @@ export WC_INSTANCE_NAME=test_instance [ -n "${IP_ADDR}" ] || IP_ADDR="localhost" WORKSPACE=${TRAVIS_BUILD_DIR} -PYTHON_VERSION=`python -c "import sys; print('%s.%s.%s' % sys.version_info[:3])"` COVERAGE_CMD=coverage RADON_CMD=radon # Prepip scripts -for conf in $* +for conf in $FLAGS do file="${TRAVIS_BUILD_DIR}/src/ci_scripts/conf_scripts/${conf}-prepip.sh" if [[ -x "$file" ]] @@ -32,16 +37,13 @@ pip install ${TRAVIS_BUILD_DIR}/src/dist/wirecloud*.whl # Install the required testing tools pip install django-nose mock radon -DJANGO_VERSION=`django-admin.py --version` -DJANGO_VERSION="${DJANGO_VERSION%.*}" - # Create a WireCloud instance -~/virtualenv/python$PYTHON_VERSION/bin/wirecloud-admin startproject ${WC_INSTANCE_NAME} +wirecloud-admin startproject ${WC_INSTANCE_NAME} cd ${WC_INSTANCE_NAME} # And configure it cat ${TRAVIS_BUILD_DIR}/src/ci_scripts/base_settings.py >> ${WC_INSTANCE_NAME}/settings.py -for conf in $* +for conf in $FLAGS do file="${TRAVIS_BUILD_DIR}/src/ci_scripts/conf_scripts/${conf}-prepare.sh" if [[ -x "$file" ]] @@ -51,10 +53,9 @@ do done python manage.py migrate --noinput -python manage.py collectstatic -v 0 --noinput +python manage.py collectstatic -v 0 -c --noinput # Pass the tests -cd ${TRAVIS_BUILD_DIR}/src DJANGO_LIVE_TEST_SERVER_ADDRESS="${IP_ADDR}:28081" # Used by Django 1.8-1.10 DJANGO_LIVE_TEST_SERVER_HOST="${IP_ADDR}" # Custom env variable used on Django 1.11 ${COVERAGE_CMD} run -a --branch --source=wirecloud --omit="*/wirecloud/fp74caast/*,*/wirecloud/semanticwiring/*,*/wirecloud/guidebuilder/*,*/tests/*,*/tests.py" manage.py test --noinput --nologcapture -v 2 ${TESTS} From d00b94dbae3ddbbbd66d4fc95c63d95679d8656c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Sun, 24 Jun 2018 22:45:13 +0200 Subject: [PATCH 02/23] CI: Install geckodriver when running selenium tests --- src/ci_scripts/travis.sh | 2 +- src/ci_scripts/travis_before_script.sh | 2 +- src/ci_scripts/travis_install.sh | 7 +++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/ci_scripts/travis.sh b/src/ci_scripts/travis.sh index a883930b8e..bf9455cfa1 100755 --- a/src/ci_scripts/travis.sh +++ b/src/ci_scripts/travis.sh @@ -7,7 +7,7 @@ if [ "${TEST_SUITE}" == "js_unittests" ]; then grunt ci exit elif [ "${TEST_SUITE}" == "selenium" ]; then - FLAGS="postgres django${DJANGO_VERSION} selenium" + FLAGS="sqlite3 django${DJANGO_VERSION} firefox-local selenium" else FLAGS="sqlite3 django${DJANGO_VERSION} unittest" fi diff --git a/src/ci_scripts/travis_before_script.sh b/src/ci_scripts/travis_before_script.sh index 6c603c4850..b159e20134 100755 --- a/src/ci_scripts/travis_before_script.sh +++ b/src/ci_scripts/travis_before_script.sh @@ -1,4 +1,4 @@ -if [ "${TEST_SUITE}" == "js_unittests" ]; then +if [ "${TEST_SUITE}" == "js_unittests" ] || [ "${TEST_SUITE}" == "selenium" ]; then export DISPLAY=:99.0 sh -e /etc/init.d/xvfb start sleep 3 # give xvfb some time to start diff --git a/src/ci_scripts/travis_install.sh b/src/ci_scripts/travis_install.sh index 38a2f1fc1c..5815f25ddd 100755 --- a/src/ci_scripts/travis_install.sh +++ b/src/ci_scripts/travis_install.sh @@ -6,3 +6,10 @@ if [ "${TEST_SUITE}" == "js_unittests" ]; then else pip install coveralls fi + +if [ "${TEST_SUITE}" == "selenium" ]; then + wget https://github.com/mozilla/geckodriver/releases/download/v0.20.1/geckodriver-v0.20.1-linux64.tar.gz + mkdir geckodriver + tar -xzf geckodriver-v0.20.1-linux64.tar.gz -C geckodriver + export PATH=$PATH:$PWD/geckodriver +fi From e36b59229cfb8ebf73dec18f1d2efb9ddfec9dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Sun, 29 Jul 2018 12:05:51 +0200 Subject: [PATCH 03/23] Update setup.py to require Django 1.9 as minimum --- src/setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/setup.py b/src/setup.py index 9655a4dbd5..0193c3c842 100755 --- a/src/setup.py +++ b/src/setup.py @@ -113,7 +113,7 @@ def run(self): from django.core.management import call_command except: import pip - pip.main(['install', 'Django>=1.8,<1.12']) + pip.main(['install', 'Django>=1.9,<1.12']) from django.core.management import call_command @@ -169,7 +169,7 @@ def run(self): }, include_package_data=True, install_requires=( - 'Django>=1.8,<1.12', + 'Django>=1.9,<1.12', 'lxml>=2.3', 'django-appconf>=1.0.1,<2.0', 'django_compressor>=2.0,<3.0', From 025751b903d37a063c1aa23685c29e1e34665eaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Sun, 29 Jul 2018 12:49:38 +0200 Subject: [PATCH 04/23] Enable postgres on the selenium tests --- .../conf_scripts/postgres-local-prepare.sh | 9 --------- src/ci_scripts/conf_scripts/postgres-prepare.sh | 5 +---- src/ci_scripts/templates/postgres-conf.template | 13 ++++++++----- src/ci_scripts/travis.sh | 2 +- 4 files changed, 10 insertions(+), 19 deletions(-) delete mode 100755 src/ci_scripts/conf_scripts/postgres-local-prepare.sh diff --git a/src/ci_scripts/conf_scripts/postgres-local-prepare.sh b/src/ci_scripts/conf_scripts/postgres-local-prepare.sh deleted file mode 100755 index 175fa22d66..0000000000 --- a/src/ci_scripts/conf_scripts/postgres-local-prepare.sh +++ /dev/null @@ -1,9 +0,0 @@ -export DB_USER=wirecloud_ci -export DB_NAME=${DB_USER} - -pip install psycopg2 - -createdb -U ${DB_USER} ${DB_NAME} -createdb -U ${DB_USER} test_${DB_NAME} - -cat ${WORKSPACE}/src/ci_scripts/templates/postgres-conf.template >> ${WC_INSTANCE_NAME}/settings.py diff --git a/src/ci_scripts/conf_scripts/postgres-prepare.sh b/src/ci_scripts/conf_scripts/postgres-prepare.sh index 15eda3462c..00aa935560 100755 --- a/src/ci_scripts/conf_scripts/postgres-prepare.sh +++ b/src/ci_scripts/conf_scripts/postgres-prepare.sh @@ -1,8 +1,5 @@ -export DB_USER=postgres -export DB_NAME=wirecloud_ci - pip install psycopg2 -createdb -U postgres -h ${DB_HOST} -p ${DB_PORT} -O ${DB_USER} ${DB_NAME} +createdb -U postgres -h ${DB_HOST:-localhost} -p ${DB_PORT:-5432} -O ${DB_USER:-postgres} ${DB_NAME:-wirecloud} cat ${WORKSPACE}/src/ci_scripts/templates/postgres-conf.template >> ${WC_INSTANCE_NAME}/settings.py diff --git a/src/ci_scripts/templates/postgres-conf.template b/src/ci_scripts/templates/postgres-conf.template index 7cba47bf2e..b89e1d2062 100644 --- a/src/ci_scripts/templates/postgres-conf.template +++ b/src/ci_scripts/templates/postgres-conf.template @@ -2,11 +2,14 @@ import os DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': os.environ['DB_NAME'], - 'USER': os.environ['DB_USER'], + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': os.environ.get('DB_NAME', 'wirecloud'), + 'USER': os.environ.get('DB_USER', 'postgres'), 'PASSWORD': '', - 'HOST': os.environ.get('DB_HOST', ''), - 'PORT': os.environ.get('DB_PORT', ''), + 'HOST': os.environ.get('DB_HOST', 'localhost'), + 'PORT': os.environ.get('DB_PORT', '5432'), + 'TEST': { + 'NAME': os.environ.get('DB_NAME', 'wirecloud'), + }, } } diff --git a/src/ci_scripts/travis.sh b/src/ci_scripts/travis.sh index bf9455cfa1..88489ff31c 100755 --- a/src/ci_scripts/travis.sh +++ b/src/ci_scripts/travis.sh @@ -7,7 +7,7 @@ if [ "${TEST_SUITE}" == "js_unittests" ]; then grunt ci exit elif [ "${TEST_SUITE}" == "selenium" ]; then - FLAGS="sqlite3 django${DJANGO_VERSION} firefox-local selenium" + FLAGS="postgres django${DJANGO_VERSION} firefox-local selenium" else FLAGS="sqlite3 django${DJANGO_VERSION} unittest" fi From 55061e46d8e412a298194cfe0e4d5645264c4df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Sun, 29 Jul 2018 14:16:11 +0200 Subject: [PATCH 05/23] Remove some selenium tests by implementing unittests --- src/GruntFile.js | 2 + src/js_tests/wirecloud/bootstrap.js | 5 +- src/js_tests/wirecloud/ui/MACSearchSpec.js | 376 ++++++++++++++++++ .../static/js/wirecloud/ui/ResourcePainter.js | 2 +- src/wirecloud/catalogue/tests/selenium.py | 23 +- .../static/js/wirecloud/ui/MACSearch.js | 83 ++-- src/wirecloud/platform/wiring/tests.py | 45 +-- 7 files changed, 438 insertions(+), 98 deletions(-) create mode 100644 src/js_tests/wirecloud/ui/MACSearchSpec.js diff --git a/src/GruntFile.js b/src/GruntFile.js index fdda5f8eef..52812c6808 100644 --- a/src/GruntFile.js +++ b/src/GruntFile.js @@ -103,9 +103,11 @@ var WirecloudFiles = [ 'wirecloud/platform/static/js/wirecloud/LogManager.js', 'wirecloud/commons/static/js/wirecloud/Task.js', 'wirecloud/commons/static/js/wirecloud/ui/Draggable.js', + 'wirecloud/commons/static/js/wirecloud/ui/MACSearch.js', 'wirecloud/commons/static/js/wirecloud/ui/WindowMenu.js', 'wirecloud/commons/static/js/wirecloud/ui/AlertWindowMenu.js', 'wirecloud/catalogue/static/js/wirecloud/WirecloudCatalogue.js', + 'wirecloud/catalogue/static/js/wirecloud/ui/ResourcePainter.js', 'wirecloud/platform/static/js/wirecloud/io.js', 'wirecloud/platform/static/js/wirecloud/LocalCatalogue.js', 'wirecloud/platform/static/js/wirecloud/PersistentVariableDef.js', diff --git a/src/js_tests/wirecloud/bootstrap.js b/src/js_tests/wirecloud/bootstrap.js index 9b82e4581c..d98f7c2b5a 100644 --- a/src/js_tests/wirecloud/bootstrap.js +++ b/src/js_tests/wirecloud/bootstrap.js @@ -11,7 +11,10 @@ const Wirecloud = { currentTheme: { templates: { 'wirecloud/logs/details': '
Exception details

Stacktrace
', - 'wirecloud/modals/base': '
' + 'wirecloud/macsearch/base': '
', + 'wirecloud/modals/base': '
', + 'wirecloud/macsearch/component': '

', + 'wirecloud/component_sidebar': ' ' } }, location: { diff --git a/src/js_tests/wirecloud/ui/MACSearchSpec.js b/src/js_tests/wirecloud/ui/MACSearchSpec.js new file mode 100644 index 0000000000..aef36dd4b4 --- /dev/null +++ b/src/js_tests/wirecloud/ui/MACSearchSpec.js @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. + * + * This file is part of Wirecloud Platform. + * + * Wirecloud Platform is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Wirecloud 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 Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Wirecloud Platform. If not, see + * . + * + */ + +/* globals StyledElements, Wirecloud */ + +(function (ns, se) { + + "use strict"; + + const component = { + "creation_date": "2018-06-06T09:52:14Z", + "description": "Browse the available entity types of a given Orio context broker server", + "image": "https://dashboards.opplafy.eu/catalogue/media/CoNWeT/ngsi-type-browser/1.0.4/images/catalogue.png", + "input_friendcodes": [], + "name": "ngsi-type-browser", + "others": ["1.0.3"], + "output_friendcodes": [], + "public": false, + "smartphoneimage": "", + "template_uri": "CoNWeT_ngsi-type-browser_1.0.4.wgt", + "title": "NGSI Type browser", + "type": "widget", + "uri": "CoNWeT/ngsi-type-browser/1.0.4", + "vendor": "CoNWeT", + "vendor_name": "CoNWeT/ngsi-type-browser", + "version": "1.0.4" + }; + Object.freeze(component); + + describe("MACSearch(options)", () => { + + beforeEach(() => { + jasmine.clock().install(); + }); + + afterEach(() => { + jasmine.clock().uninstall(); + }); + + it("options is required", () => { + expect(() => { + new ns.MACSearch(); + }).toThrowError(TypeError); + }); + + it("resourceButtonListener or resource_painter is required", () => { + expect(() => { + new ns.MACSearch({}); + }).toThrowError(TypeError); + }); + + it("should work when only passing the resourceButtonListener option", () => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + expect(element.input).toEqual(jasmine.any(se.TextField)); + expect(element.list).toEqual(jasmine.any(se.Container)); + expect(element.resource_painter).toBe(null); + }); + + it("should work when only passing the resource_painter option", () => { + let rp = {paint: jasmine.createSpy()}; + let element = new ns.MACSearch({resource_painter: rp}); + expect(element.input).toEqual(jasmine.any(se.TextField)); + expect(element.list).toEqual(jasmine.any(se.Container)); + expect(element.resource_painter).toBe(rp); + }); + + it("supports custom templates", () => { + // TODO current implementation requires that the root element be the one at index 1 + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy(), template: "wirecloud/component_sidebar"}); + expect(element.input).toEqual(jasmine.any(se.TextField)); + expect(element.list).toEqual(jasmine.any(se.Container)); + expect(element.resource_painter).toBe(null); + }); + + it("should search on text input", (done) => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + spyOn(Wirecloud.LocalCatalogue, "search").and.returnValue( + Promise.resolve({total_count: 1, resources: [Object.assign({}, component)]}) + ); + + element.input.value = "keywords"; + jasmine.clock().tick(901); + jasmine.clock().uninstall(); + + setTimeout(() => { + expect(Wirecloud.LocalCatalogue.search).toHaveBeenCalledWith({scope: '', search_criteria: 'keywords'}); + expect(element.resource_painter).not.toBe(null); + done(); + }, 0); + }); + + it("should support searching with custom resource_painter", (done) => { + let rp = {paint: jasmine.createSpy()}; + let element = new ns.MACSearch({resource_painter: rp}); + let parsed_component = Object.assign({}, component); + parsed_component.version = new Wirecloud.Version(component.version); + parsed_component.others = component.others.map((version) => {return new Wirecloud.Version(version);}); + spyOn(Wirecloud.LocalCatalogue, "search").and.returnValue( + Promise.resolve({total_count: 1, resources: [Object.assign({}, component)]}) + ); + + element.input.value = "keywords"; + jasmine.clock().tick(901); + jasmine.clock().uninstall(); + + setTimeout(() => { + expect(Wirecloud.LocalCatalogue.search).toHaveBeenCalledWith({scope: '', search_criteria: 'keywords'}); + expect(element.resource_painter).toBe(rp); + expect(element.resource_painter.paint).toHaveBeenCalledWith(parsed_component); + done(); + }, 0); + }); + + it("should support the resourceButtonTooltip option", (done) => { + let tooltip = jasmine.createSpy(); + let element = new ns.MACSearch({resourceButtonTooltip: tooltip, resourceButtonListener: jasmine.createSpy()}); + expect(element.resourceButtonTooltip).toBe(tooltip); + spyOn(Wirecloud.LocalCatalogue, "search").and.returnValue( + Promise.resolve({total_count: 1, resources: [Object.assign({}, component)]}) + ); + + element.input.value = "keywords"; + jasmine.clock().tick(901); + jasmine.clock().uninstall(); + + setTimeout(() => { + expect(Wirecloud.LocalCatalogue.search).toHaveBeenCalledWith({scope: '', search_criteria: 'keywords'}); + expect(element.resource_painter).not.toBe(null); + done(); + }, 0); + }); + + it("should handle corrected queries", (done) => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + spyOn(Wirecloud.LocalCatalogue, "search").and.returnValue( + Promise.resolve({corrected_query: "other", total_count: 1, resources: [Object.assign({}, component)]}) + ); + spyOn(element, "paintInfo"); + + element.input.value = "keywords"; + jasmine.clock().tick(901); + jasmine.clock().uninstall(); + + setTimeout(() => { + expect(Wirecloud.LocalCatalogue.search).toHaveBeenCalledWith({scope: '', search_criteria: 'keywords'}); + expect(element.resource_painter).not.toBe(null); + expect(element.paintInfo).toHaveBeenCalled(); + done(); + }, 0); + }); + + it("empty search", (done) => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + spyOn(Wirecloud.LocalCatalogue, "search").and.returnValue( + Promise.resolve({total_count: 0, resources: []}) + ); + + element.input.value = "keywords"; + jasmine.clock().tick(900); + jasmine.clock().uninstall(); + + setTimeout(() => { + expect(Wirecloud.LocalCatalogue.search).toHaveBeenCalledWith({scope: '', search_criteria: 'keywords'}); + done(); + }, 0); + }); + + it("should ignore text input on a given time period", (done) => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy(), scope: "widget"}); + spyOn(Wirecloud.LocalCatalogue, "search").and.returnValue( + Promise.resolve({total_count: 0, resources: []}) + ); + + element.input.value = "keywords"; + jasmine.clock().tick(320); + element.input.value = "other"; + jasmine.clock().tick(900); + jasmine.clock().uninstall(); + + setTimeout(() => { + expect(Wirecloud.LocalCatalogue.search).toHaveBeenCalledWith({scope: 'widget', search_criteria: 'other'}); + expect(Wirecloud.LocalCatalogue.search.calls.count()).toBe(1); + done(); + }, 0); + }); + + it("should handle connection errors", () => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + spyOn(Wirecloud.LocalCatalogue, "search").and.returnValue( + Promise.reject("Error") + ); + spyOn(element, "paintError"); + + element.input.value = "keywords"; + element.input.dispatchEvent("keydown", [], "Enter"); + + expect(Wirecloud.LocalCatalogue.search).toHaveBeenCalledWith({scope: '', search_criteria: 'keywords'}); + }); + + it("should handle keydown events", () => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + spyOn(Wirecloud.LocalCatalogue, "search").and.returnValue( + Promise.reject("Error") + ); + + element.input.dispatchEvent("keydown", [], "a"); + + expect(Wirecloud.LocalCatalogue.search).not.toHaveBeenCalled(); + }); + + var empty_result = (scope) => { + return (done) => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy(), scope: scope}); + spyOn(Wirecloud.LocalCatalogue, "search").and.returnValue( + Promise.resolve({total_count: 0, resources: []}) + ); + spyOn(element, "paintError"); + + element.input.dispatchEvent("keydown", [], "Enter"); + + expect(Wirecloud.LocalCatalogue.search).toHaveBeenCalledWith({scope: scope, search_criteria: ''}); + jasmine.clock().uninstall(); + setTimeout(() => { + expect(element.paintError).toHaveBeenCalled(); + done(); + }, 0); + }; + }; + + it("empty result without keywords (empty scope)", empty_result("")); + it("empty result without keywords (scope: widget)", empty_result("widget")); + + }); + + describe("clear()", () => { + + it("should clear the list container", () => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + spyOn(element.list, "clear"); + + expect(element.clear()).toBe(element); + + expect(element.list.clear).toHaveBeenCalledWith(); + }); + + }); + + describe("paintInfo(message[, context])", () => { + + var element; + + beforeEach(() => { + element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + }); + + it("should support simple messages", () => { + expect(element.paintInfo("info message")).toBe(element); + }); + + it("should support messages with context", () => { + expect(element.paintInfo("info message", {})).toBe(element); + }); + + }); + + describe("paintError(message)", () => { + + it("should support simple messages", () => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + element.paintError("info message"); + }); + + }); + + describe("focus()", () => { + + it("should focus the input text box", () => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + spyOn(element.input, "focus"); + + expect(element.focus()).toBe(element); + + expect(element.input.focus).toHaveBeenCalledWith(); + }); + + }); + + describe("refresh()", () => { + + it("should make an immediate request", () => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + + spyOn(Wirecloud.LocalCatalogue, "search").and.returnValue( + Promise.resolve({total_count: 0, resources: []}) + ); + + expect(element.refresh()).toBe(element); + + expect(Wirecloud.LocalCatalogue.search).toHaveBeenCalledWith({scope: '', search_criteria: ''}); + expect(Wirecloud.LocalCatalogue.search.calls.count()).toBe(1); + }); + + it("should cancel previous pending searches", (done) => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + + spyOn(Wirecloud.LocalCatalogue, "search").and.returnValue( + Promise.resolve({total_count: 0, resources: []}) + ); + + element.input.value = "keywords"; + + setTimeout(() => { + expect(Wirecloud.LocalCatalogue.search).not.toHaveBeenCalled(); + + expect(element.refresh()).toBe(element); + + expect(Wirecloud.LocalCatalogue.search).toHaveBeenCalled(); + expect(Wirecloud.LocalCatalogue.search.calls.count()).toBe(1); + done(); + }, 300); + }); + + it("should abort current requests", (done) => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + let promise = new Wirecloud.Task("request", () => {}); + + spyOn(promise, "abort"); + spyOn(Wirecloud.LocalCatalogue, "search").and.returnValue(promise); + + element.input.value = "keywords"; + + setTimeout(() => { + expect(Wirecloud.LocalCatalogue.search).toHaveBeenCalled(); + + expect(element.refresh()).toBe(element); + + expect(promise.abort).toHaveBeenCalled(); + expect(Wirecloud.LocalCatalogue.search).toHaveBeenCalled(); + done(); + }, 800); + }); + + }); + + describe("repaint()", () => { + + it("should repaint the list container", () => { + let element = new ns.MACSearch({resourceButtonListener: jasmine.createSpy()}); + spyOn(element.list, "repaint"); + + expect(element.repaint()).toBe(element); + + expect(element.list.repaint).toHaveBeenCalledWith(); + }); + + }); + +})(Wirecloud.ui, StyledElements); diff --git a/src/wirecloud/catalogue/static/js/wirecloud/ui/ResourcePainter.js b/src/wirecloud/catalogue/static/js/wirecloud/ui/ResourcePainter.js index e4d7e3348c..63d3eac04e 100644 --- a/src/wirecloud/catalogue/static/js/wirecloud/ui/ResourcePainter.js +++ b/src/wirecloud/catalogue/static/js/wirecloud/ui/ResourcePainter.js @@ -19,7 +19,7 @@ * */ -/* globals StyledElements, Wirecloud */ +/* globals moment, StyledElements, Wirecloud */ (function (se, utils) { diff --git a/src/wirecloud/catalogue/tests/selenium.py b/src/wirecloud/catalogue/tests/selenium.py index 3446c304d4..29ef78aa18 100644 --- a/src/wirecloud/catalogue/tests/selenium.py +++ b/src/wirecloud/catalogue/tests/selenium.py @@ -28,13 +28,7 @@ class CatalogueSeleniumTests(WirecloudSeleniumTestCase): tags = ('wirecloud-selenium', 'wirecloud-catalogue', 'wirecloud-catalogue-selenium') - - def test_upload_packaged_widget(self): - - self.login() - - with self.myresources_view as myresources: - myresources.upload_resource('Wirecloud_Test_Selenium_1.0.wgt', 'Test_Selenium', shared=True) + populate = False def test_upload_packaged_mashup(self): @@ -86,18 +80,3 @@ def test_upload_and_delete_widget(self): with self.myresources_view as myresources: myresources.upload_resource('Wirecloud_Test_Selenium_1.0.wgt', 'Test_Selenium', shared=True) myresources.delete_resource('Test_Selenium') - - def test_search_empty_results(self): - - self.login() - - with self.myresources_view as myresources: - myresources.search('nousedkeyword') - catalogue_base_element = myresources.wait_catalogue_ready() - - resources = catalogue_base_element.find_elements_by_css_selector('.resource_list .resource') - self.assertEqual(len(resources), 0) - - alert = catalogue_base_element.find_elements_by_css_selector('.alert') - self.assertEqual(len(alert), 1) - self.assertIn('nousedkeyword', alert[0].text) diff --git a/src/wirecloud/commons/static/js/wirecloud/ui/MACSearch.js b/src/wirecloud/commons/static/js/wirecloud/ui/MACSearch.js index cf199d624b..ec3e569c88 100644 --- a/src/wirecloud/commons/static/js/wirecloud/ui/MACSearch.js +++ b/src/wirecloud/commons/static/js/wirecloud/ui/MACSearch.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2014-2017 CoNWeT Lab., Universidad Politécnica de Madrid + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. * * This file is part of Wirecloud Platform. * @@ -30,10 +31,14 @@ var MACSearch = function MACSearch(options) { + if (options == null || typeof options !== "object" || (typeof options.resourceButtonListener !== "function" && options.resource_painter == null)) { + throw new TypeError(); + } + options = utils.merge({ - 'extra_template_context': null, - 'scope': '', - 'template': 'wirecloud/macsearch/base', + extra_template_context: null, + scope: '', + template: 'wirecloud/macsearch/base', resource_painter: null }, options); @@ -45,36 +50,36 @@ var priv = { request: null, - list: new StyledElements.Container({class: 'wc-macsearch-list wc-resource-results loading'}) + search_timeout: null }; privates.set(this, priv); this.resource_painter = options.resource_painter; var input; + var list = new StyledElements.Container({class: 'wc-macsearch-list wc-resource-results loading'}); var template = Wirecloud.currentTheme.templates[options.template]; this.wrapperElement = builder.parse(template, utils.merge({ - searchinput: function () { + searchinput: () => { input = new StyledElements.TextField({class: "se-field-search", 'placeholder': utils.gettext('Keywords...')}); input.addEventListener('keydown', _onSearchInputKeyPress.bind(this)); input.addEventListener('change', _onSearchInput.bind(this)); return input; - }.bind(this), - list: priv.list + }, + list: list }, options.extra_template_context)).elements[1]; if (this.wrapperElement instanceof StyledElements.StyledElement) { this.wrapperElement = this.wrapperElement.get(); } Object.defineProperties(this, { - 'inputField': {value: input}, + 'input': {value: input}, + 'list': {value: list}, 'search_scope': {value: options.scope, writable: true}, 'resourceButtonIconClass': {value: options.resourceButtonIconClass}, 'resourceButtonListener': {value: options.resourceButtonListener}, 'resourceButtonTooltip': {value: options.resourceButtonTooltip} }); - - this.input = input; }; utils.inherit(MACSearch, StyledElements.StyledElement); @@ -83,31 +88,49 @@ message = builder.parse(builder.DEFAULT_OPENING + message + builder.DEFAULT_CLOSING, context); } - return builder.parse(this.info_template, { + this.list.appendChild(builder.parse(this.info_template, { 'message': message - }); + })); + + return this; }; MACSearch.prototype.paintError = function paintError(message) { - return builder.parse(this.error_template, { + this.list.appendChild(builder.parse(this.error_template, { 'message': message - }); + })); + + return this; }; MACSearch.prototype.clear = function clear() { - privates.get(this).list.clear(); + this.list.clear(); + + return this; }; MACSearch.prototype.repaint = function repaint() { - privates.get(this).list.repaint(); + this.list.repaint(); + + return this; }; MACSearch.prototype.refresh = function refresh() { + var priv = privates.get(this); + + if (priv.search_timeout != null) { + clearTimeout(priv.search_timeout); + priv.search_timeout = null; + } _keywordTimeoutHandler.call(this, this.input); + + return this; }; MACSearch.prototype.focus = function focus() { - this.inputField.focus(); + this.input.focus(); + + return this; }; // ========================================================================= @@ -123,7 +146,7 @@ // Abort current request due user input priv.request.abort("User input", true); } - priv.list.disable(); + this.list.disable(); this.dispatchEvent('search'); priv.request = Wirecloud.LocalCatalogue.search({ scope: this.search_scope, @@ -134,11 +157,11 @@ var msg = utils.gettext("Connection error: No resource retrieved"); _load_resource_painter.call(this); - priv.list.clear().appendChild(this.paintError(msg)); + this.clear().paintError(msg); return Promise.resolve(); }).then(() => { priv.request = null; - priv.list.enable(); + this.list.enable(); }); }; @@ -172,7 +195,7 @@ var priv = privates.get(this); // Cancel current timeout - if (priv.search_timeout !== null) { + if (priv.search_timeout != null) { clearTimeout(priv.search_timeout); } @@ -185,7 +208,7 @@ var priv = privates.get(this); // Cancel current timeout - if (priv.search_timeout !== null) { + if (priv.search_timeout != null) { clearTimeout(priv.search_timeout); } @@ -195,23 +218,23 @@ }; var on_search_success = function on_search_success(keywords, components, search_info) { - var msg, priv = privates.get(this); + var msg; - _load_resource_painter.call(this); - priv.list.clear(); + this.list.clear(); if (search_info.total_count !== 0) { + _load_resource_painter.call(this); if ('corrected_query' in search_info) { msg = utils.gettext("

Showing results for

"); - priv.list.appendChild(this.paintInfo(msg, { + this.paintInfo(msg, { corrected_query: search_info.corrected_query - })); + }); } components.forEach(function (component) { try { component.version = new Wirecloud.Version(component.version); - component.others = component.others.map(function (version) {return new Wirecloud.Version(version);}); - priv.list.appendChild(this.resource_painter.paint(component)); + component.others = component.others.map((version) => {return new Wirecloud.Version(version);}); + this.list.appendChild(this.resource_painter.paint(component)); } catch (e) { // } @@ -226,7 +249,7 @@ } else { msg = utils.gettext("

Currently, you do not have access to any component. You can get components using the Marketplace view or by uploading components manually using the Upload button on the My Resources view.

"); } - priv.list.appendChild(this.paintError(new StyledElements.Fragment(msg))); + this.paintError(new StyledElements.Fragment(msg)); } }; diff --git a/src/wirecloud/platform/wiring/tests.py b/src/wirecloud/platform/wiring/tests.py index ffca1086ed..fa39471f01 100644 --- a/src/wirecloud/platform/wiring/tests.py +++ b/src/wirecloud/platform/wiring/tests.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2011-2017 CoNWeT Lab., Universidad Politécnica de Madrid +# Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. # This file is part of Wirecloud. @@ -2621,50 +2622,6 @@ def test_missing_endpoints_cannot_be_ordered(self): draggable_widget.change_version("3.0") draggable_widget.show_preferences().check(must_be_disabled=("Order endpoints",)) - @uses_extra_resources(('Wirecloud_api-test_0.9.wgt',), shared=True) - def test_search_components_by_keywords(self): - self.login(username='user_with_workspaces', next="/user_with_workspaces/Workspace") - - with self.wiring_view as wiring: - with wiring.component_sidebar as sidebar: - groups = sidebar.find_component_groups('widget', keywords="api") - self.assertEqual(len(groups), 1) - group = groups[0] - self.assertEqual(group.id, "Wirecloud/api-test") - - def test_search_components_by_keywords_no_results(self): - self.login(username='user_with_workspaces', next="/user_with_workspaces/Workspace") - - with self.wiring_view as wiring: - with wiring.component_sidebar as sidebar: - groups = sidebar.find_component_groups('widget', keywords="api") - self.assertEqual(len(groups), 0) - alert = sidebar.alert - self.assertIsNotNone(alert) - self.assertTrue(alert.has_class('alert-error')) - - @uses_extra_workspace('user_with_workspaces', 'Wirecloud_mashup-with-behaviours_1.0.wgt', shared=True) - def test_check_component_sidebar(self): - self.login(username='user_with_workspaces', next='/user_with_workspaces/mashup-with-behaviours') - self._check_component_sidebar() - # Get back to dashboard - self._check_component_sidebar() - - def _check_component_sidebar(self): - with self.wiring_view as wiring: - with wiring.component_sidebar as sidebar: - widgets = sidebar.find_components('widget', "Wirecloud/Test") - self.assertEqual(len(widgets), 2) - self.assertEqual(widgets[0].title, "Test 1") - self.assertEqual(widgets[0].state, "in use") - self.assertEqual(widgets[1].title, "Test 2") - self.assertEqual(widgets[1].state, "in use") - - operators = sidebar.find_components('operator', "Wirecloud/TestOperator") - self.assertEqual(len(operators), 1) - self.assertEqual(operators[0].title, "TestOperator") - self.assertEqual(operators[0].state, "in use") - @wirecloud_selenium_test_case class ComponentMissingTestCase(WirecloudSeleniumTestCase): From 3b670fdb13348f736bab0ba4bb5d996ec4cd9df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Mon, 30 Jul 2018 15:26:54 +0200 Subject: [PATCH 06/23] Fix endpoint ordering --- src/wirecloud/commons/utils/remote.py | 8 +- .../ui/WiringEditor/EndpointGroup.js | 83 ++++++------------- 2 files changed, 27 insertions(+), 64 deletions(-) diff --git a/src/wirecloud/commons/utils/remote.py b/src/wirecloud/commons/utils/remote.py index 22a04a0688..37d49cd0f5 100644 --- a/src/wirecloud/commons/utils/remote.py +++ b/src/wirecloud/commons/utils/remote.py @@ -1098,13 +1098,9 @@ def title(self): def change_position(self, endpoint): new_index = endpoint.index - actions = ActionChains(self.testcase.driver).click_and_hold(self.element) + actions = ActionChains(self.testcase.driver).click_and_hold(self.element).move_to_element(endpoint.element).release().perform() - for i in range(abs(new_index - self.index)): - actions.move_to_element(endpoint.element) - - actions.release().perform() - self.testcase.assertEqual(self.index, new_index) + WebDriverWait(self.testcase.driver, 3).until(lambda driver: self.index == new_index) return self def create_connection(self, endpoint, must_recommend=(), must_expand=()): diff --git a/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor/EndpointGroup.js b/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor/EndpointGroup.js index 31cff3feb0..e56b71658c 100644 --- a/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor/EndpointGroup.js +++ b/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor/EndpointGroup.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2016 CoNWeT Lab., Universidad Politécnica de Madrid + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. * * This file is part of Wirecloud Platform. * @@ -317,35 +318,25 @@ endpoint.addClassName("dragging"); - context.marginVertical = 5; - - context.refHeigth = endpointBCR.height + context.marginVertical; - context.refHeigthUp = (endpointBCR.height / 2) + context.marginVertical; - context.refHeigthDown = context.refHeigthUp; - - context.canMoveUp = endpoint.index; - context.canMoveDown = context.group.children.length - (context.canMoveUp + 1); + let groupBCR = context.group.getBoundingClientRect(); + context.topBorder = groupBCR.top - layoutBCR.top; + context.ratio = groupBCR.height / context.group.children.length; }, function drag(e, draggable, context, xDelta, yDelta) { - context.clonedEndpoint.style.left = Math.round(context.x + xDelta) + 'px'; - context.clonedEndpoint.style.top = Math.round(context.y + yDelta) + 'px'; - - if ((context.canMoveUp > 0) && (-(yDelta + context.offsetHeight) > context.refHeigthUp)) { - context.canMoveUp -= 1; - context.refHeigthUp += context.refHeigth; + let yPos = context.y + yDelta; - context.canMoveDown += 1; - context.refHeigthDown -= context.refHeigth; + context.clonedEndpoint.style.left = (context.x + xDelta) + 'px'; + context.clonedEndpoint.style.top = yPos + 'px'; - moveUpEndpoint.call(context.group, endpoint); - } else if ((context.canMoveDown > 0) && ((yDelta + context.offsetHeight) > context.refHeigthDown)) { - context.canMoveUp += 1; - context.refHeigthUp -= context.refHeigth; - - context.canMoveDown -= 1; - context.refHeigthDown += context.refHeigth; + let new_index = Math.round((yPos - context.topBorder) / context.ratio); + if (new_index < 0) { + new_index = 0; + } else if (new_index >= context.group.children.length) { + new_index = context.group.children.length - 1; + } - moveDownEndpoint.call(context.group, endpoint); + if (new_index != endpoint.index) { + moveEndpoint.call(context.group, endpoint, new_index); } }, function dragend(draggable, context) { @@ -360,42 +351,18 @@ return this; }; - var moveDownEndpoint = function moveDownEndpoint(endpoint) { - var nextEndpoint, index = endpoint.index; - - if (index == (this.children.length - 1)) { - return this; + var moveEndpoint = function moveEndpoint(endpoint, new_index) { + se.Container.prototype.removeChild.call(this, endpoint); + let refElement = this.children[new_index - 1]; + if (refElement) { + se.Container.prototype.appendChild.call(this, endpoint, refElement); + } else { + se.Container.prototype.prependChild.call(this, endpoint); } - nextEndpoint = this.children[index + 1]; - endpoint.parent().insertBefore(endpoint.get(), nextEndpoint.get().nextSibling); - - endpoint.index = index + 1; - nextEndpoint.index = index; - - this.children[index + 1] = endpoint; - this.children[index] = nextEndpoint; - - return this.refresh(); - }; - - var moveUpEndpoint = function moveUpEndpoint(endpoint) { - var previousEndpoint, index; - - index = endpoint.index; - - if (index === 0) { - return this; - } - - previousEndpoint = this.children[index - 1]; - endpoint.parent().insertBefore(endpoint.get(), previousEndpoint.get()); - - endpoint.index = index - 1; - previousEndpoint.index = index; - - this.children[index - 1] = endpoint; - this.children[index] = previousEndpoint; + this.children.forEach((endpoint, index) => { + endpoint.index = index; + }); return this.refresh(); }; From 3db687991e06e98ec14cf2405ebc8cf86d10029d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Mon, 30 Jul 2018 15:56:14 +0200 Subject: [PATCH 07/23] Improve test speed --- src/wirecloud/platform/markets/tests.py | 1 + src/wirecloud/platform/tests/selenium.py | 1 + src/wirecloud/platform/wiring/tests.py | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/src/wirecloud/platform/markets/tests.py b/src/wirecloud/platform/markets/tests.py index 2a4cb97ab5..83427af925 100644 --- a/src/wirecloud/platform/markets/tests.py +++ b/src/wirecloud/platform/markets/tests.py @@ -38,6 +38,7 @@ class MarketManagementSeleniumTestCase(WirecloudSeleniumTestCase): }, } tags = ('wirecloud-selenium', 'wirecloud-markets', 'wirecloud-markets-selenium') + use_search_indexes = False def check_resource_buttons(self, marketplace, resources, button_text=None): for resource_name in resources: diff --git a/src/wirecloud/platform/tests/selenium.py b/src/wirecloud/platform/tests/selenium.py index 4076f31538..093d033e52 100644 --- a/src/wirecloud/platform/tests/selenium.py +++ b/src/wirecloud/platform/tests/selenium.py @@ -54,6 +54,7 @@ class BasicSeleniumTests(WirecloudSeleniumTestCase): fixtures = ('selenium_test_data', 'user_with_workspaces') tags = ('wirecloud-selenium', 'wirecloud-basics-selenium') + populate = False def test_basic_workspace_operations(self): diff --git a/src/wirecloud/platform/wiring/tests.py b/src/wirecloud/platform/wiring/tests.py index fa39471f01..a7e81e994f 100644 --- a/src/wirecloud/platform/wiring/tests.py +++ b/src/wirecloud/platform/wiring/tests.py @@ -71,6 +71,7 @@ class WiringTestCase(WirecloudTestCase, TransactionTestCase): fixtures = ('test_data',) tags = ('wirecloud-wiring', 'wirecloud-noselenium', 'wirecloud-wiring-noselenium') populate = False + use_search_indexes = False def setUp(self): @@ -2057,6 +2058,7 @@ class OperatorCodeEntryTestCase(WirecloudTestCase, TestCase): fixtures = ('selenium_test_data',) tags = ('wirecloud-wiring', 'wirecloud-noselenium', 'wirecloud-wiring-noselenium', 'wirecloud-operator-code-transformation') populate = False + use_search_indexes = False XML_NORMALIZATION_RE = re.compile(b'>\\s+<') COMPRESS_HASH_RE = re.compile(b'/[a-z0-9]{12}\.js') @@ -2120,6 +2122,7 @@ class WiringBasicOperationTestCase(WirecloudSeleniumTestCase): fixtures = ('selenium_test_data', 'user_with_workspaces') tags = ('wirecloud-selenium', 'wirecloud-wiring', 'wirecloud-wiring-selenium') + populate = False def test_sends_event_after_connecting_two_widgets(self): @@ -2375,6 +2378,7 @@ class WiringRecoveringTestCase(WirecloudSeleniumTestCase): fixtures = ('selenium_test_data', 'user_with_workspaces') tags = ('wirecloud-selenium', 'wirecloud-wiring', 'wirecloud-wiring-selenium') + use_search_indexes = False def _read_json_fixtures(self, filename): testdir_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test-data')) @@ -2836,6 +2840,7 @@ class ConnectionManagementTestCase(WirecloudSeleniumTestCase): fixtures = ('selenium_test_data', 'user_with_workspaces') tags = ('wirecloud-selenium', 'wirecloud-wiring', 'wirecloud-wiring-selenium', 'wirecloud-wiring-connection-management') + use_search_indexes = False def test_readonly_connections_cannot_be_deleted(self): # Change the connection state to readonly @@ -2978,6 +2983,7 @@ class EndpointManagementTestCase(WirecloudSeleniumTestCase): fixtures = ('selenium_test_data', 'user_with_workspaces') tags = ('wirecloud-selenium', 'wirecloud-wiring', 'wirecloud-wiring-selenium', 'wirecloud-wiring-endpoint-management') + use_search_indexes = False @classmethod def setUpClass(cls): @@ -3197,6 +3203,7 @@ class BehaviourManagementTestCase(WirecloudSeleniumTestCase): fixtures = ('selenium_test_data', 'user_with_workspaces') tags = ('wirecloud-selenium', 'wirecloud-wiring', 'wirecloud-wiring-selenium', 'wirecloud-wiring-behaviour-management') + clear_search_indexes = False def test_behaviour_engine_is_disabled_by_default(self): # Create a new workspace to ensure we are testing the default status of From 9e456aa0a4dc0857146f49595a991a1b0d5a2157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Tue, 31 Jul 2018 12:43:32 +0200 Subject: [PATCH 08/23] Fix some problems on the gui_tutorial test --- src/wirecloud/platform/tests/selenium.py | 4 ++-- src/wirecloud/platform/wiring/tests.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wirecloud/platform/tests/selenium.py b/src/wirecloud/platform/tests/selenium.py index 093d033e52..e07e26da03 100644 --- a/src/wirecloud/platform/tests/selenium.py +++ b/src/wirecloud/platform/tests/selenium.py @@ -939,7 +939,7 @@ def test_gui_tutorials(self): with self.resource_sidebar as sidebar: # Add the youtube browser widget - WebDriverWait(self.driver, timeout=15).until(WEC.component_instantiable(sidebar, 'YouTube Browser')).click() + WebDriverWait(self.driver, timeout=15).until(WEC.component_instantiable(sidebar, 'YouTube Browser')) # Next tutorial step next_button = self.wait_element_visible_by_xpath("//*[contains(@class, 'window_menu')]//*[text()='Next']") @@ -947,7 +947,7 @@ def test_gui_tutorials(self): next_button.click() # Add the input box widget - WebDriverWait(self.driver, timeout=15).until(WEC.component_instantiable(sidebar, 'Input Box')).click() + WebDriverWait(self.driver, timeout=15).until(WEC.component_instantiable(sidebar, 'Input Box')) # cancel current tutorial self.wait_element_visible_by_xpath("//*[contains(@class, 'window_menu')]//*[text()='Cancel']").click() diff --git a/src/wirecloud/platform/wiring/tests.py b/src/wirecloud/platform/wiring/tests.py index a7e81e994f..8e3b94b716 100644 --- a/src/wirecloud/platform/wiring/tests.py +++ b/src/wirecloud/platform/wiring/tests.py @@ -3203,7 +3203,7 @@ class BehaviourManagementTestCase(WirecloudSeleniumTestCase): fixtures = ('selenium_test_data', 'user_with_workspaces') tags = ('wirecloud-selenium', 'wirecloud-wiring', 'wirecloud-wiring-selenium', 'wirecloud-wiring-behaviour-management') - clear_search_indexes = False + use_search_indexes = False def test_behaviour_engine_is_disabled_by_default(self): # Create a new workspace to ensure we are testing the default status of @@ -3310,7 +3310,7 @@ def test_dashboard_management_api_support(self): # and directly clickable without scrolling the view self.driver.execute_script("document.getElementById('dashboard_management_button').click();") # Wait until the test finish with a success message - WebDriverWait(self.driver, timeout=3).until(lambda driver: driver.find_element_by_id('dashboard_management_test').text == 'Success!!') + WebDriverWait(self.driver, timeout=6).until(lambda driver: driver.find_element_by_id('dashboard_management_test').text == 'Success!!') # Two widgets are created when clicking the dashboard management button # one of them is connected directly, the other is connected through and From b7d836289089e7064e7524e9ef91b3eeea6d3295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Fri, 17 Aug 2018 12:46:27 +0200 Subject: [PATCH 09/23] Update karma to v3 --- src/package-lock.json | 1218 ++++------------------------------------- src/package.json | 2 +- 2 files changed, 108 insertions(+), 1112 deletions(-) diff --git a/src/package-lock.json b/src/package-lock.json index 575068af62..311edaee12 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -42,28 +42,12 @@ } } }, - "addressparser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", - "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", - "dev": true, - "optional": true - }, "after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", "dev": true }, - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, "ajv": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", @@ -108,49 +92,6 @@ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, - "amqplib": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", - "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", - "dev": true, - "optional": true, - "requires": { - "bitsyntax": "~0.0.4", - "bluebird": "^3.4.6", - "buffer-more-ints": "0.0.2", - "readable-stream": "1.x >=1.1.9", - "safe-buffer": "^5.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true, - "optional": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - } - } - }, "ansi-escapes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", @@ -280,13 +221,6 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, - "ast-types": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", - "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==", - "dev": true, - "optional": true - }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -329,28 +263,6 @@ "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", "dev": true }, - "axios": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", - "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", - "dev": true, - "optional": true, - "requires": { - "follow-redirects": "1.0.0" - }, - "dependencies": { - "follow-redirects": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", - "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", - "dev": true, - "optional": true, - "requires": { - "debug": "^2.2.0" - } - } - } - }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -499,57 +411,6 @@ "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "dev": true }, - "bitsyntax": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", - "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", - "dev": true, - "optional": true, - "requires": { - "buffer-more-ints": "0.0.2" - } - }, - "bl": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", - "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", - "dev": true, - "optional": true, - "requires": { - "readable-stream": "~2.0.5" - }, - "dependencies": { - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true, - "optional": true - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - } - } - }, "blob": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", @@ -580,15 +441,6 @@ "type-is": "~1.6.16" } }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.x.x" - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -637,33 +489,33 @@ "pako": "~0.2.0" } }, - "buffer-from": { + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", - "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", "dev": true }, - "buffer-more-ints": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", - "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", "dev": true }, - "buildmail": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", - "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", - "dev": true, - "optional": true, - "requires": { - "addressparser": "1.0.1", - "libbase64": "0.1.0", - "libmime": "3.0.0", - "libqp": "1.1.0", - "nodemailer-fetch": "1.6.0", - "nodemailer-shared": "1.1.0", - "punycode": "1.4.1" - } + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", + "dev": true }, "builtin-modules": { "version": "1.1.1", @@ -933,13 +785,6 @@ "delayed-stream": "~1.0.0" } }, - "commander": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz", - "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==", - "dev": true, - "optional": true - }, "component-bind": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", @@ -1065,16 +910,6 @@ "which": "^1.2.9" } }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "optional": true, - "requires": { - "boom": "2.x.x" - } - }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -1108,13 +943,6 @@ "assert-plus": "^1.0.0" } }, - "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", - "dev": true, - "optional": true - }, "date-format": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", @@ -1199,27 +1027,6 @@ } } }, - "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "dev": true, - "optional": true, - "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true, - "optional": true - } - } - }, "del": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", @@ -1274,13 +1081,6 @@ "void-elements": "^2.0.0" } }, - "double-ended-queue": { - "version": "2.1.0-0", - "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", - "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", - "dev": true, - "optional": true - }, "duplexify": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", @@ -1325,9 +1125,9 @@ } }, "engine.io": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", - "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.0.tgz", + "integrity": "sha512-mRbgmAtQ4GAlKwuPnnAvXXwdPhEx+jkc0OBCLrXuD/CRvwNK3AxRSnqK4FSqmAMRRHryVJP8TopOvmEaA64fKw==", "dev": true, "requires": { "accepts": "~1.3.4", @@ -1335,7 +1135,6 @@ "cookie": "0.3.1", "debug": "~3.1.0", "engine.io-parser": "~2.1.0", - "uws": "~9.14.0", "ws": "~3.3.1" }, "dependencies": { @@ -1351,9 +1150,9 @@ } }, "engine.io-client": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", - "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { "component-emitter": "1.2.1", @@ -1444,21 +1243,6 @@ "event-emitter": "~0.3.5" } }, - "es6-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", - "dev": true - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3" - } - }, "es6-set": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", @@ -1506,29 +1290,6 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "escodegen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", - "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", - "dev": true, - "optional": true, - "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true, - "optional": true - } - } - }, "escope": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", @@ -1920,13 +1681,6 @@ "object-assign": "^4.0.1" } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", @@ -2032,9 +1786,9 @@ } }, "follow-redirects": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.1.tgz", - "integrity": "sha512-v9GI1hpaqq1ZZR6pBD1+kI7O24PhDvNGNodjS3MdcEqyrahCp8zbtpv+2B/krUnSmUH80lbAS7MrdeK5IylgKg==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.5.tgz", + "integrity": "sha512-GHjtHDlY/ehslqv0Gr5N0PUJppgg/q0rOBvX0na1s7y1A3LWxPqCYU76s3Z1bM4+UZB4QF0usaXLT5wFpof5PA==", "dev": true, "requires": { "debug": "^3.1.0" @@ -2636,46 +2390,6 @@ } } }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "dev": true, - "optional": true, - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true, - "optional": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - } - } - }, "generate-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", @@ -2697,21 +2411,6 @@ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, - "get-uri": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", - "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", - "dev": true, - "optional": true, - "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "3", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "2" - } - }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -3402,36 +3101,6 @@ } } }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "optional": true, - "requires": { - "boom": "2.x.x", - "cryptiles": "2.x.x", - "hoek": "2.x.x", - "sntp": "1.x.x" - } - }, - "hipchat-notifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", - "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", - "dev": true, - "optional": true, - "requires": { - "lodash": "^4.0.0", - "request": "^2.0.0" - } - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, "hooker": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", @@ -3467,27 +3136,6 @@ "requires-port": "^1.0.0" } }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -3499,64 +3147,19 @@ "sshpk": "^1.7.0" } }, - "httpntlm": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", - "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", "dev": true, "requires": { - "httpreq": ">=0.4.22", - "underscore": "~1.7.0" - }, - "dependencies": { - "underscore": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", - "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", - "dev": true - } + "safer-buffer": ">= 2.1.2 < 3" } }, - "httpreq": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", - "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", - "dev": true - }, - "https-proxy-agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", - "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", - "dev": true, - "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz", - "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==", + "ignore": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz", + "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==", "dev": true }, "imurmurhash": { @@ -3580,13 +3183,6 @@ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", "dev": true }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "dev": true, - "optional": true - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3657,12 +3253,6 @@ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -3939,10 +3529,13 @@ "dev": true }, "isbinaryfile": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", - "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", - "dev": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } }, "isexe": { "version": "2.0.0", @@ -4159,9 +3752,9 @@ } }, "karma": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.5.tgz", - "integrity": "sha512-rECezBeY7mjzGUWhFlB7CvPHgkHJLXyUmWg+6vHCEsdWNUTnmiS6jRrIMcJEWgU2DUGZzGWG0bTRVky8fsDTOA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-3.0.0.tgz", + "integrity": "sha512-ZTjyuDXVXhXsvJ1E4CnZzbCjSxD6sEdzEsFYogLuZM0yqvg/mgz+O+R1jb0J7uAQeuzdY8kJgx6hSNXLwFuHIQ==", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -4179,15 +3772,15 @@ "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", "lodash": "^4.17.4", - "log4js": "^2.5.3", - "mime": "^1.3.4", + "log4js": "^3.0.0", + "mime": "^2.3.1", "minimatch": "^3.0.2", "optimist": "^0.6.1", "qjobs": "^1.1.4", "range-parser": "^1.2.0", "rimraf": "^2.6.0", "safe-buffer": "^5.0.1", - "socket.io": "2.0.4", + "socket.io": "2.1.1", "source-map": "^0.6.1", "tmp": "0.0.33", "useragent": "2.2.1" @@ -4322,37 +3915,6 @@ "type-check": "~0.3.2" } }, - "libbase64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", - "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", - "dev": true - }, - "libmime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", - "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", - "dev": true, - "requires": { - "iconv-lite": "0.4.15", - "libbase64": "0.1.0", - "libqp": "1.1.0" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true - } - } - }, - "libqp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", - "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", - "dev": true - }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -4391,23 +3953,15 @@ "dev": true }, "log4js": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.11.0.tgz", - "integrity": "sha512-z1XdwyGFg8/WGkOyF6DPJjivCWNLKrklGdViywdYnSKOvgtEBo2UyEMZS5sD2mZrQlU3TvO8wDWLc8mzE1ncBQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.5.tgz", + "integrity": "sha512-IX5c3G/7fuTtdr0JjOT2OIR12aTESVhsH6cEsijloYwKgcPRlO6DgOU72v0UFhWcoV1HN6+M3dwT89qVPLXm0w==", "dev": true, "requires": { - "amqplib": "^0.5.2", - "axios": "^0.15.3", - "circular-json": "^0.5.4", + "circular-json": "^0.5.5", "date-format": "^1.2.0", "debug": "^3.1.0", - "hipchat-notifier": "^1.1.0", - "loggly": "^1.1.0", - "mailgun-js": "^0.18.0", - "nodemailer": "^2.5.0", - "redis": "^2.7.1", - "semver": "^5.5.0", - "slack-node": "~0.2.0", + "rfdc": "^1.1.2", "streamroller": "0.7.0" }, "dependencies": { @@ -4428,157 +3982,6 @@ } } }, - "loggly": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", - "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", - "dev": true, - "optional": true, - "requires": { - "json-stringify-safe": "5.0.x", - "request": "2.75.x", - "timespan": "2.3.x" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "optional": true - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true, - "optional": true - }, - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true, - "optional": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "optional": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "form-data": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", - "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", - "dev": true, - "optional": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.11" - } - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "optional": true, - "requires": { - "chalk": "^1.1.1", - "commander": "^2.9.0", - "is-my-json-valid": "^2.12.4", - "pinkie-promise": "^2.0.0" - } - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "node-uuid": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", - "dev": true, - "optional": true - }, - "qs": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", - "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", - "dev": true, - "optional": true - }, - "request": { - "version": "2.75.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", - "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", - "dev": true, - "optional": true, - "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "bl": "~1.1.2", - "caseless": "~0.11.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.0.0", - "har-validator": "~2.0.6", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "node-uuid": "~1.4.7", - "oauth-sign": "~0.8.1", - "qs": "~6.2.0", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "~0.4.1" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "optional": true - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true, - "optional": true - } - } - }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -4605,57 +4008,6 @@ "yallist": "^2.1.2" } }, - "mailcomposer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", - "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", - "dev": true, - "optional": true, - "requires": { - "buildmail": "4.0.1", - "libmime": "3.0.0" - } - }, - "mailgun-js": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.1.tgz", - "integrity": "sha512-lvuMP14u24HS2uBsJEnzSyPMxzU2b99tQsIx1o6QNjqxjk8b3WvR+vq5oG1mjqz/IBYo+5gF+uSoDS0RkMVHmg==", - "dev": true, - "optional": true, - "requires": { - "async": "~2.6.0", - "debug": "~3.1.0", - "form-data": "~2.3.0", - "inflection": "~1.12.0", - "is-stream": "^1.1.0", - "path-proxy": "~1.0.0", - "promisify-call": "^2.0.2", - "proxy-agent": "~3.0.0", - "tsscmp": "~1.0.0" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "optional": true, - "requires": { - "lodash": "^4.17.10" - } - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -4783,9 +4135,9 @@ } }, "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", "dev": true }, "mime-db": { @@ -4906,104 +4258,12 @@ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", "dev": true }, - "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", - "dev": true, - "optional": true - }, "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, - "nodemailer": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", - "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", - "dev": true, - "optional": true, - "requires": { - "libmime": "3.0.0", - "mailcomposer": "4.0.1", - "nodemailer-direct-transport": "3.3.2", - "nodemailer-shared": "1.1.0", - "nodemailer-smtp-pool": "2.8.2", - "nodemailer-smtp-transport": "2.7.2", - "socks": "1.1.9" - }, - "dependencies": { - "socks": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", - "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", - "dev": true, - "optional": true, - "requires": { - "ip": "^1.1.2", - "smart-buffer": "^1.0.4" - } - } - } - }, - "nodemailer-direct-transport": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", - "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-fetch": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", - "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", - "dev": true - }, - "nodemailer-shared": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", - "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", - "dev": true, - "requires": { - "nodemailer-fetch": "1.6.0" - } - }, - "nodemailer-smtp-pool": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", - "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-smtp-transport": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", - "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", - "dev": true, - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-wellknown": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", - "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", - "dev": true - }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -5207,60 +4467,6 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "pac-proxy-agent": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz", - "integrity": "sha512-cDNAN1Ehjbf5EHkNY5qnRhGPUCp6SnpyVof5fRzN800QV1Y2OkzbH9rmjZkbBRa8igof903yOnjIl6z0SlAhxA==", - "dev": true, - "optional": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "get-uri": "^2.0.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "pac-resolver": "^3.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "^3.0.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "socks-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz", - "integrity": "sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==", - "dev": true, - "optional": true, - "requires": { - "agent-base": "^4.1.0", - "socks": "^1.1.10" - } - } - } - }, - "pac-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", - "dev": true, - "optional": true, - "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", - "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" - } - }, "pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", @@ -5362,25 +4568,6 @@ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, - "path-proxy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", - "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", - "dev": true, - "optional": true, - "requires": { - "inflection": "~1.3.0" - }, - "dependencies": { - "inflection": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", - "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", - "dev": true, - "optional": true - } - } - }, "path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", @@ -5465,52 +4652,6 @@ "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", "dev": true }, - "promisify-call": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", - "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", - "dev": true, - "optional": true, - "requires": { - "with-callback": "^1.0.2" - } - }, - "proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.1.tgz", - "integrity": "sha512-mAZexaz9ZxQhYPWfAjzlrloEjW+JHiBFryE4AJXFDTnaXfmH/FKqC1swTRKuEPbHWz02flQNXFOyDUF7zfEG6A==", - "dev": true, - "optional": true, - "requires": { - "agent-base": "^4.2.0", - "debug": "^3.1.0", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^4.1.2", - "pac-proxy-agent": "^2.0.1", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^4.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", - "dev": true, - "optional": true - }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -5650,32 +4791,6 @@ "strip-indent": "^1.0.1" } }, - "redis": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", - "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", - "dev": true, - "optional": true, - "requires": { - "double-ended-queue": "^2.1.0-0", - "redis-commands": "^1.2.0", - "redis-parser": "^2.6.0" - } - }, - "redis-commands": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.5.tgz", - "integrity": "sha512-foGF8u6MXGFF++1TZVC6icGXuMYPftKXt1FBT2vrfU9ZATNtZJ8duRC5d1lEfE8hyVe3jhelHGB91oB7I6qLsA==", - "dev": true, - "optional": true - }, - "redis-parser": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", - "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", - "dev": true, - "optional": true - }, "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", @@ -5756,19 +4871,6 @@ "uuid": "^3.1.0" } }, - "requestretry": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", - "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", - "dev": true, - "optional": true, - "requires": { - "extend": "^3.0.0", - "lodash": "^4.15.0", - "request": "^2.74.0", - "when": "^3.7.7" - } - }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -5836,6 +4938,12 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, + "rfdc": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", + "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "dev": true + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -5949,39 +5057,12 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, - "slack-node": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", - "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", - "dev": true, - "optional": true, - "requires": { - "requestretry": "^1.2.2" - } - }, "slice-ansi": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", "dev": true }, - "smart-buffer": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", - "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", - "dev": true, - "optional": true - }, - "smtp-connection": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", - "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", - "dev": true, - "requires": { - "httpntlm": "1.6.1", - "nodemailer-shared": "1.1.0" - } - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -6095,27 +5176,29 @@ } } }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "optional": true, - "requires": { - "hoek": "2.x.x" - } - }, "socket.io": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", - "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { - "debug": "~2.6.6", - "engine.io": "~3.1.0", + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.0.4", - "socket.io-parser": "~3.1.1" + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } } }, "socket.io-adapter": { @@ -6125,35 +5208,46 @@ "dev": true }, "socket.io-client": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", - "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { "backo2": "1.0.2", "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", "component-emitter": "1.2.1", - "debug": "~2.6.4", - "engine.io-client": "~3.1.0", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", "has-cors": "1.1.0", "indexof": "0.0.1", "object-component": "0.0.3", "parseqs": "0.0.5", "parseuri": "0.0.5", - "socket.io-parser": "~3.1.1", + "socket.io-parser": "~3.2.0", "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } } }, "socket.io-parser": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", - "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { "component-emitter": "1.2.1", "debug": "~3.1.0", - "has-binary2": "~1.0.2", "isarray": "2.0.1" }, "dependencies": { @@ -6174,48 +5268,6 @@ } } }, - "socks": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", - "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", - "dev": true, - "optional": true, - "requires": { - "ip": "^1.1.4", - "smart-buffer": "^1.0.13" - } - }, - "socks-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", - "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", - "dev": true, - "optional": true, - "requires": { - "agent-base": "~4.2.0", - "socks": "~2.2.0" - }, - "dependencies": { - "smart-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.1.tgz", - "integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==", - "dev": true, - "optional": true - }, - "socks": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.1.tgz", - "integrity": "sha512-0GabKw7n9mI46vcNrVfs0o6XzWzjVa3h6GaSo2UPxtWAROXUWavfJWh1M4PR5tnE0dcnQXZIDFP4yrAysLze/w==", - "dev": true, - "optional": true, - "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.0.1" - } - } - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -6381,13 +5433,6 @@ "safe-buffer": "~5.1.0" } }, - "stringstream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", - "dev": true, - "optional": true - }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -6590,20 +5635,6 @@ } } }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", - "dev": true, - "optional": true - }, - "timespan": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", - "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", - "dev": true, - "optional": true - }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -6696,13 +5727,6 @@ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, - "tsscmp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", - "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", - "dev": true, - "optional": true - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -6950,13 +5974,6 @@ "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", "dev": true }, - "uws": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/uws/-/uws-9.14.0.tgz", - "integrity": "sha512-HNMztPP5A1sKuVFmdZ6BPVpBQd5bUjNC8EFMFiICK+oho/OQsAJy5hnIx4btMHiOk8j04f/DbIlqnEZ9d72dqg==", - "dev": true, - "optional": true - }, "vali-date": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", @@ -7038,13 +6055,6 @@ "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", "dev": true }, - "when": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", - "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", - "dev": true, - "optional": true - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -7061,13 +6071,6 @@ "dev": true, "optional": true }, - "with-callback": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/with-callback/-/with-callback-1.0.2.tgz", - "integrity": "sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE=", - "dev": true, - "optional": true - }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -7112,13 +6115,6 @@ "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", "dev": true }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", - "dev": true, - "optional": true - }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", diff --git a/src/package.json b/src/package.json index 70bc6c82c5..aadfabb4e9 100644 --- a/src/package.json +++ b/src/package.json @@ -10,7 +10,7 @@ "grunt-lcov-merge": "^1.2.3", "gruntify-eslint": "^3.1.0", "jasmine-core": "<2.5.0", - "karma": "^2.0.5", + "karma": "^3.0.0", "karma-chrome-launcher": "^1.0.1", "karma-coverage": "^1.1.2", "karma-firefox-launcher": "^1.0.0", From 5cf207f1a47eee3ea793400f26ad4a926e562ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Mon, 10 Sep 2018 11:04:14 +0200 Subject: [PATCH 10/23] Update django_relative dependency --- docs/installation_guide.md | 2 +- src/setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation_guide.md b/docs/installation_guide.md index 541b707fe1..f85b2991f1 100644 --- a/docs/installation_guide.md +++ b/docs/installation_guide.md @@ -26,7 +26,7 @@ step, as they will be installed throughout the documentation:** - futures 2.1.3+ (only on python 2.7) - selenium 3.4+ - pytz - - django_relatives + - django_relatives 0.3.x - user-agents - regex - markdown diff --git a/src/setup.py b/src/setup.py index 0193c3c842..b50b5cadd6 100755 --- a/src/setup.py +++ b/src/setup.py @@ -177,7 +177,7 @@ def run(self): 'requests>=2.1.0', 'selenium>=3.4', 'pytz', - 'django_relatives', + 'django_relatives<1.0.0', 'user-agents', 'regex', 'markdown', From 16cea653937168f336afeea360a176567a853c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Mon, 10 Sep 2018 14:12:18 +0200 Subject: [PATCH 11/23] Improve search indexes handling when passing selenium tests --- src/wirecloud/commons/utils/remote.py | 2 +- src/wirecloud/commons/utils/testcases.py | 91 ++++++++++++++---------- 2 files changed, 53 insertions(+), 40 deletions(-) diff --git a/src/wirecloud/commons/utils/remote.py b/src/wirecloud/commons/utils/remote.py index 37d49cd0f5..c222da46b3 100644 --- a/src/wirecloud/commons/utils/remote.py +++ b/src/wirecloud/commons/utils/remote.py @@ -1342,7 +1342,7 @@ def wait_loading_window_fadding(driver): self.wait_element_visible('.wc-body:not(.se-on-transition)') - time.sleep(0.1) # work around some problems + time.sleep(0.2) # work around some problems def login(self, username='admin', password='admin', next=None): diff --git a/src/wirecloud/commons/utils/testcases.py b/src/wirecloud/commons/utils/testcases.py index bf0155a588..87fa5a7426 100644 --- a/src/wirecloud/commons/utils/testcases.py +++ b/src/wirecloud/commons/utils/testcases.py @@ -28,6 +28,7 @@ import stat import sys from tempfile import mkdtemp +import time from six.moves.urllib.error import URLError, HTTPError from six.moves.urllib.parse import unquote, urlparse @@ -301,8 +302,6 @@ def unmock_requests(self): def prepare_temporal_resource_directories(cls): - from django.conf import settings - cls.tmp_dir = mkdtemp() # catalogue deployer @@ -386,21 +385,21 @@ def setUpClass(cls): prepare_temporal_resource_directories(cls) # Prepare haystack configuration - cls.old_haystack_conf = settings.HAYSTACK_CONNECTIONS - try: - settings.HAYSTACK_CONNECTIONS = copy.deepcopy(settings.TEST_HAYSTACK_CONNECTIONS) - # Update whoosh index dir if not set by user - if settings.HAYSTACK_CONNECTIONS['default']['ENGINE'] == 'wirecloud.commons.haystack_backends.whoosh_backend.WhooshEngine' and settings.HAYSTACK_CONNECTIONS['default'].get("PATH") is None: + if cls.use_search_indexes: + cls.old_haystack_conf = settings.HAYSTACK_CONNECTIONS + try: + settings.HAYSTACK_CONNECTIONS = copy.deepcopy(settings.TEST_HAYSTACK_CONNECTIONS) + # Update whoosh index dir if not set by user + if settings.HAYSTACK_CONNECTIONS['default']['ENGINE'] == 'wirecloud.commons.haystack_backends.whoosh_backend.WhooshEngine' and settings.HAYSTACK_CONNECTIONS['default'].get("PATH") is None: + settings.HAYSTACK_CONNECTIONS['default']['PATH'] = os.path.join(cls.tmp_dir, 'test_whoosh_indexes') + except: + settings.HAYSTACK_CONNECTIONS = copy.deepcopy(DEFAULT_TEST_HAYSTACK_CONNECTIONS) settings.HAYSTACK_CONNECTIONS['default']['PATH'] = os.path.join(cls.tmp_dir, 'test_whoosh_indexes') - except: - settings.HAYSTACK_CONNECTIONS = copy.deepcopy(DEFAULT_TEST_HAYSTACK_CONNECTIONS) - settings.HAYSTACK_CONNECTIONS['default']['PATH'] = os.path.join(cls.tmp_dir, 'test_whoosh_indexes') - - # Reload the connection - haystack.connections.connections_info = settings.HAYSTACK_CONNECTIONS - haystack.connections.reload('default') - if not cls.use_search_indexes: + # Reload the connection + haystack.connections.connections_info = settings.HAYSTACK_CONNECTIONS + haystack.connections.reload('default') + else: apps.get_app_config('haystack').signal_processor.teardown() super(WirecloudTestCase, cls).setUpClass() @@ -425,12 +424,13 @@ def tearDownClass(cls): # Restore old haystack configuration if not cls.use_search_indexes: apps.get_app_config('haystack').signal_processor.setup() - elif not cls.clear_search_indexes and settings.HAYSTACK_CONNECTIONS['default']['ENGINE'] == 'wirecloud.commons.haystack_backends.whoosh_backend.WhooshEngine': - # If self.clear_search_indexes is True, this step is done in a per - # test basis in the tearDown method - management.call_command('clear_index', interactive=False, verbosity=0) + else: + if not cls.clear_search_indexes and settings.HAYSTACK_CONNECTIONS['default']['ENGINE'] == 'wirecloud.commons.haystack_backends.whoosh_backend.WhooshEngine': + # If self.clear_search_indexes is True, this step is done in a per + # test basis in the tearDown method + management.call_command('clear_index', interactive=False, verbosity=0) - settings.HAYSTACK_CONNECTIONS = cls.old_haystack_conf + settings.HAYSTACK_CONNECTIONS = cls.old_haystack_conf # Clear cache from django.core.cache import cache @@ -473,6 +473,10 @@ def tearDown(self): if self.clear_search_indexes: management.call_command('clear_index', interactive=False, verbosity=0) + # Reload the connection + haystack.connections.connections_info = settings.HAYSTACK_CONNECTIONS + haystack.connections.reload('default') + super(WirecloudTestCase, self).tearDown() def changeLanguage(self, new_language): @@ -593,21 +597,21 @@ def setUpClass(cls): prepare_temporal_resource_directories(cls) # Prepare haystack configuration - cls.old_haystack_conf = settings.HAYSTACK_CONNECTIONS - try: - settings.HAYSTACK_CONNECTIONS = copy.deepcopy(settings.TEST_HAYSTACK_CONNECTIONS) - # Update whoosh index dir if not set by user - if settings.HAYSTACK_CONNECTIONS['default']['ENGINE'] == 'wirecloud.commons.haystack_backends.whoosh_backend.WhooshEngine' and settings.HAYSTACK_CONNECTIONS['default'].get("PATH") is None: + if cls.use_search_indexes: + cls.old_haystack_conf = settings.HAYSTACK_CONNECTIONS + try: + settings.HAYSTACK_CONNECTIONS = copy.deepcopy(settings.TEST_HAYSTACK_CONNECTIONS) + # Update whoosh index dir if not set by user + if settings.HAYSTACK_CONNECTIONS['default']['ENGINE'] == 'wirecloud.commons.haystack_backends.whoosh_backend.WhooshEngine' and settings.HAYSTACK_CONNECTIONS['default'].get("PATH") is None: + settings.HAYSTACK_CONNECTIONS['default']['PATH'] = os.path.join(cls.tmp_dir, 'test_whoosh_indexes') + except: + settings.HAYSTACK_CONNECTIONS = copy.deepcopy(DEFAULT_TEST_HAYSTACK_CONNECTIONS) settings.HAYSTACK_CONNECTIONS['default']['PATH'] = os.path.join(cls.tmp_dir, 'test_whoosh_indexes') - except: - settings.HAYSTACK_CONNECTIONS = copy.deepcopy(DEFAULT_TEST_HAYSTACK_CONNECTIONS) - settings.HAYSTACK_CONNECTIONS['default']['PATH'] = os.path.join(cls.tmp_dir, 'test_whoosh_indexes') - - # Reload the connection - haystack.connections.connections_info = settings.HAYSTACK_CONNECTIONS - haystack.connections.reload('default') - if not cls.use_search_indexes: + # Reload the connection + haystack.connections.connections_info = settings.HAYSTACK_CONNECTIONS + haystack.connections.reload('default') + else: apps.get_app_config('haystack').signal_processor.teardown() # Browsers doesn't use content negotiation using ETags with HTTP 1.0 servers @@ -643,12 +647,13 @@ def tearDownClass(cls): # Restore old haystack configuration if not cls.use_search_indexes: apps.get_app_config('haystack').signal_processor.setup() - elif not cls.clear_search_indexes and settings.HAYSTACK_CONNECTIONS['default']['ENGINE'] == 'wirecloud.commons.haystack_backends.whoosh_backend.WhooshEngine': - # If self.clear_search_indexes is True, this step is done in a per - # test basis in the tearDown method - management.call_command('clear_index', interactive=False, verbosity=0) + else: + if not cls.clear_search_indexes and settings.HAYSTACK_CONNECTIONS['default']['ENGINE'] == 'wirecloud.commons.haystack_backends.whoosh_backend.WhooshEngine': + # If self.clear_search_indexes is True, this step is done in a per + # test basis in the tearDown method + management.call_command('clear_index', interactive=False, verbosity=0) - settings.HAYSTACK_CONNECTIONS = cls.old_haystack_conf + settings.HAYSTACK_CONNECTIONS = cls.old_haystack_conf super(WirecloudSeleniumTestCase, cls).tearDownClass() @@ -673,7 +678,15 @@ def setUp(self): def tearDown(self): - management.call_command('clear_index', interactive=False, verbosity=0) + from django.conf import settings + if self.clear_search_indexes: + management.call_command('clear_index', interactive=False, verbosity=0) + + # Reload the connection + haystack.connections.connections_info = settings.HAYSTACK_CONNECTIONS + haystack.connections.reload('default') + + time.sleep(0.2) LiveServerTestCase.tearDown(self) WirecloudRemoteTestCase.tearDown(self) From 02b04b5f83980b15a4ccf28fa24e720e87946e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Mon, 10 Sep 2018 23:38:49 +0200 Subject: [PATCH 12/23] Fix some problems entering WiringView contexts --- src/wirecloud/commons/utils/remote.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/wirecloud/commons/utils/remote.py b/src/wirecloud/commons/utils/remote.py index c222da46b3..2ca0d59877 100644 --- a/src/wirecloud/commons/utils/remote.py +++ b/src/wirecloud/commons/utils/remote.py @@ -1290,11 +1290,14 @@ def tearDown(self): self.driver.delete_all_cookies() - def find_navbar_button(self, classname): - try: - return ButtonTester(self, self.driver.find_element_by_css_selector(".wc-toolbar .%s" % classname)) - except NoSuchElementException: - return None + def find_navbar_button(self, classname, wait=False): + if wait: + return ButtonTester(self, self.wait_element_visible(".wc-toolbar .%s" % classname)) + else: + try: + return ButtonTester(self, self.driver.find_element_by_css_selector(".wc-toolbar .%s" % classname)) + except NoSuchElementException: + return None def scroll_and_click(self, element): @@ -2001,7 +2004,7 @@ def wait_ready(self, timeout=10): class WiringViewTester(BaseWiringViewTester): def __enter__(self): - self.testcase.find_navbar_button("wc-show-wiring-button").click() + self.testcase.find_navbar_button("wc-show-wiring-button", wait=True).click() self.testcase.wait_element_visible('.wc-body:not(.se-on-transition)') if self.expect_error is False: WebDriverWait(self.testcase.driver, timeout=5).until(lambda driver: self.testcase.get_current_view() == 'wiring' and not self.disabled) From e9c336646a76fde992af13497949272a89d9c127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Tue, 11 Sep 2018 16:17:24 +0200 Subject: [PATCH 13/23] Remove some selenium tests by implementing WirecloudCatalogue unittests --- .../wirecloud/WirecloudCatalogueSpec.js | 781 ++++++++++++++++++ .../static/js/wirecloud/WirecloudCatalogue.js | 90 +- src/wirecloud/catalogue/tests/selenium.py | 15 - .../static/js/catalogue/CatalogueView.js | 12 +- .../static/js/wirecloud/ui/MyResourcesView.js | 12 +- 5 files changed, 840 insertions(+), 70 deletions(-) create mode 100644 src/js_tests/wirecloud/WirecloudCatalogueSpec.js diff --git a/src/js_tests/wirecloud/WirecloudCatalogueSpec.js b/src/js_tests/wirecloud/WirecloudCatalogueSpec.js new file mode 100644 index 0000000000..d5dbfc9ed7 --- /dev/null +++ b/src/js_tests/wirecloud/WirecloudCatalogueSpec.js @@ -0,0 +1,781 @@ +/* + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. + * + * This file is part of Wirecloud Platform. + * + * Wirecloud Platform is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Wirecloud 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 Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Wirecloud Platform. If not, see + * . + * + */ + +/* globals StyledElements, Wirecloud */ + + +(function (ns, se) { + + "use strict"; + + describe("WirecloudCatalogue", () => { + + describe("WirecloudCatalogue(options)", () => { + + it("options parameter is optional", () => { + let catalogue = new ns.WirecloudCatalogue(); + expect(catalogue.url).toBe(ns.URLs.LOCAL_REPOSITORY); + }); + + it("all options are optional", () => { + let catalogue = new ns.WirecloudCatalogue(); + expect(catalogue.url).toBe(ns.URLs.LOCAL_REPOSITORY); + }); + + it("url is taken as root", () => { + let catalogue = new ns.WirecloudCatalogue({ + url: "http://server.com" + }); + expect(catalogue.url).toBe("http://server.com/"); + }); + + it("url is taken as root", () => { + let catalogue = new ns.WirecloudCatalogue({ + url: "http://server.com/" + }); + expect(catalogue.url).toBe("http://server.com/"); + }); + }); + + describe("isAllow(action)", () => { + + var catalogue; + + beforeEach(() => { + catalogue = new ns.WirecloudCatalogue({ + permissions: { + 'delete': true, + 'other': false + } + }); + }); + + it("undefined permission", () => { + expect(catalogue.isAllow("undefined")).toBe(false); + }); + + it("defined permission (true)", () => { + expect(catalogue.isAllow("delete")).toBe(true); + }); + + it("defined permission (false)", () => { + expect(catalogue.isAllow("other")).toBe(false); + }); + + }); + + describe("getResourceDetails(vendor, name)", () => { + + it("should request resource details", (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => {fullfill({responseText: "{}"});} + )); + // TODO needed before adding ResourceDetails to the tested code + ns.WirecloudCatalogue.ResourceDetails = function () {}; + + let t = catalogue.getResourceDetails(); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then((details) => { + expect(details).toEqual(jasmine.any(ns.WirecloudCatalogue.ResourceDetails)); + done(); + }); + }); + + }); + + describe("addComponent(options)", () => { + + var catalogue; + + beforeEach(() => { + catalogue = new ns.WirecloudCatalogue(); + }); + + it("options parameter is required", () => { + expect(() => { + catalogue.addComponent(); + }).toThrowError(TypeError); + }); + + it("one file, market_endpoint or url option is required", () => { + expect(() => { + catalogue.addComponent({}); + }).toThrowError(TypeError); + }); + + it("market_endpoint option can only be used on the local catalogue", () => { + catalogue = new ns.WirecloudCatalogue({ + name: "custom", + url: "https://hub.wirecloud.example.com" + }); + expect(() => { + catalogue.addComponent({market_endpoint: {}}); + }).toThrowError(TypeError); + }); + + it("should allow uploading packaged components", (done) => { + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 201, responseText: "{}"}); + } + )); + let file = new File(["foo"], "foo.txt", { + type: "text/plain", + }); + + let t = catalogue.addComponent({file: file}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({}); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + it("should allow to import components from external marketplaces", (done) => { + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 201, responseText: "{}"}); + } + )); + + let t = catalogue.addComponent({market_endpoint: {}}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({}); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + it("should allow to upload components using a url reference", (done) => { + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 201, responseText: "{}"}); + } + )); + + let t = catalogue.addComponent({url: "https://static.example.org/widget.wgt"}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({}); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + it("should allow to upload components to external catalogues", (done) => { + catalogue = new ns.WirecloudCatalogue({ + name: "custom", + url: "https://hub.wirecloud.example.com" + }); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 201, responseText: "{}"}); + } + )); + let file = new File(["foo"], "foo.txt", { + type: "text/plain", + }); + + let t = catalogue.addComponent({file: file}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({}); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + it("should support the install_embedded_resources option", (done) => { + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 201, responseText: "{}"}); + } + )); + let file = new File(["foo"], "foo.txt", { + type: "text/plain", + }); + + let t = catalogue.addComponent({file: file, install_embedded_resources: false}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({}); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + it("should support the force_create option", (done) => { + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 201, responseText: "{}"}); + } + )); + let file = new File(["foo"], "foo.txt", { + type: "text/plain", + }); + + let t = catalogue.addComponent({file: file, force_create: true}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({}); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + describe("should manage expected error responses", () => { + let test = function test(status_code) { + return (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: status_code, responseText: 'Not Found'}); + } + )); + + let t = catalogue.addComponent({market_endpoint: {}}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + fail('fullfill function called'); + }, + (error) => { + expect(error).not.toBe(null); + done(); + } + ); + } + }; + + it("400", test(400)); + it("401", test(401)); + it("403", test(403)); + it("409", test(409)); + }); + + it("should manage unexpected error codes", (done) => { + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 404, responseText: "Not Found"}); + } + )); + let file = new File(["foo"], "foo.txt", { + type: "text/plain", + }); + + let t = catalogue.addComponent({file: file}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + fail('fullfill function called'); + }, + (error) => { + expect(error).not.toBe(null); + done(); + } + ); + }); + + }); + + describe("deleteResource(resource, options)", () => { + + it("should remove current version by default", (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 200, responseText: "{}"}); + } + )); + + let t = catalogue.deleteResource({ + vendor: "Wirecloud", + name: "MyWidget", + version: { + text: "0.1" + } + }); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({ + affectedVersions: ["0.1"] + }); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + it("should manage unexpected responses", (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 422}); + } + )); + + let t = catalogue.deleteResource({ + vendor: "Wirecloud", + name: "MyWidget", + version: "0.1" + }); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + () => { + fail('fullfill function called'); + }, + (error) => { + expect(error).toEqual(jasmine.any(Error)); + done(); + } + ); + }); + + it("should manage unexpected responses (invalid payload)", (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 200, responseText: "NoJSON"}); + } + )); + + let t = catalogue.deleteResource({ + vendor: "Wirecloud", + name: "MyWidget", + version: "0.1" + }); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + () => { + fail('fullfill function called'); + }, + (error) => { + expect(error).toEqual(jasmine.any(Error)); + done(); + } + ); + }); + + it("should support removing all versions of the component", (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({ + status: 200, + responseText: '{"affectedVersions": ["0.1", "0.2"]}' + }); + } + )); + + let t = catalogue.deleteResource({ + vendor: "Wirecloud", + name: "MyWidget", + version: "0.1" + }, { + allversions: true + }); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({ + affectedVersions: ["0.1", "0.2"] + }); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + }); + + describe("search(resource, options)", () => { + + it("should allow empty searches", (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 200, responseText: '{"results": [], "pagenum": 1, "total": 0}'}); + } + )); + + let t = catalogue.search(); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({ + resources: [], + current_page: 1, + total_count: 0 + }); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + it("should support searching by criteria", (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 200, responseText: '{"results": [], "pagenum": 1, "total": 0}'}); + } + )); + + let t = catalogue.search({search_criteria: "keyword"}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({ + resources: [], + current_page: 1, + total_count: 0 + }); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + it("should support searching by criteria (corrected_query)", (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 200, responseText: '{"results": [], "pagenum": 1, "total": 0, "corrected_q": "keyword"}'}); + } + )); + + let t = catalogue.search({search_criteria: "keyworkd"}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({ + resources: [], + current_page: 1, + total_count: 0, + corrected_query: "keyword" + }); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + it("should support limiting search scope", (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 200, responseText: '{"results": [], "pagenum": 1, "total": 0}'}); + } + )); + + let t = catalogue.search({scope: "widget"}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({ + resources: [], + current_page: 1, + total_count: 0 + }); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + it("should validate search scope", () => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 200, responseText: '{"results": [], "pagenum": 1, "total": 0}'}); + } + )); + + expect(() => { + catalogue.search({scope: "potato"}); + }).toThrowError(TypeError); + }); + + it("should support limiting search results", (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 200, responseText: '{"results": [], "pagenum": 1, "total": 0}'}); + } + )); + + let t = catalogue.search({maxresults: 50}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({ + resources: [], + current_page: 1, + total_count: 0 + }); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + it("should validate search maxresults", () => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 200, responseText: '{"results": [], "pagenum": 1, "total": 0}'}); + } + )); + + expect(() => { + catalogue.search({maxresults: "potato"}); + }).toThrowError(TypeError); + }); + + it("should support providing a page offset", (done) => { + // TODO improve server response + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 200, responseText: '{"results": [], "pagenum": 1, "total": 0}'}); + } + )); + + let t = catalogue.search({pagenum: 2}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({ + resources: [], + current_page: 1, + total_count: 0 + }); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + it("should validate pagenum option", () => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 200, responseText: '{"results": [], "pagenum": 1, "total": 0}'}); + } + )); + + expect(() => { + catalogue.search({pagenum: "potato"}); + }).toThrowError(TypeError); + }); + + it("should support the order_by option", (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 200, responseText: '{"results": [], "pagenum": 1, "total": 0}'}); + } + )); + + let t = catalogue.search({order_by: "creation_date"}); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + expect(response).toEqual({ + resources: [], + current_page: 1, + total_count: 0 + }); + done(); + }, + () => { + fail('reject function called'); + } + ); + }); + + it("should manage unexpected responses", (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 404, responseText: 'Not Found'}); + } + )); + + let t = catalogue.search(); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + fail('fullfill function called'); + }, + (error) => { + expect(error).not.toBe(null); + done(); + } + ); + }); + + describe("should manage expected error responses", () => { + let test = function test(status_code) { + return (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: status_code, responseText: 'Not Found'}); + } + )); + let t = catalogue.search(); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + fail('fullfill function called'); + }, + (error) => { + expect(error).not.toBe(null); + done(); + } + ); + } + }; + + it("401", test(401)); + it("403", test(403)); + }); + + it("should manage unexpected responses (invalid payload)", (done) => { + let catalogue = new ns.WirecloudCatalogue(); + spyOn(ns.io, 'makeRequest').and.returnValue(new ns.Task( + 'making request', + (fullfill) => { + fullfill({status: 200, responseText: 'Not Found'}); + } + )); + + let t = catalogue.search(); + + expect(t).toEqual(jasmine.any(ns.Task)); + t.then( + (response) => { + fail('fullfill function called'); + }, + (error) => { + expect(error).not.toBe(null); + done(); + } + ); + }); + + }); + + }); + +})(Wirecloud, StyledElements); diff --git a/src/wirecloud/catalogue/static/js/wirecloud/WirecloudCatalogue.js b/src/wirecloud/catalogue/static/js/wirecloud/WirecloudCatalogue.js index a77411c7ac..2fdadc588c 100644 --- a/src/wirecloud/catalogue/static/js/wirecloud/WirecloudCatalogue.js +++ b/src/wirecloud/catalogue/static/js/wirecloud/WirecloudCatalogue.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2017 CoNWeT Lab., Universidad Politécnica de Madrid + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. * * This file is part of Wirecloud Platform. * @@ -37,19 +38,28 @@ */ var WirecloudCatalogue = function WirecloudCatalogue(options) { - se.ObjectWithEvents.call(this, ["change", "install", "uninstall"]); + if (options == null) { + options = {}; + } - Object.defineProperty(this, 'title', {'value': options.title || options.name}); - Object.defineProperty(this, 'name', {'value': options.name}); - Object.defineProperty(this, 'permissions', {'value': options.permissions}); + if (options.permissions == null) { + options.permissions = {}; + } + + se.ObjectWithEvents.call(this, ["change", "install", "uninstall"]); if (options.url == null) { options.url = Wirecloud.URLs.LOCAL_REPOSITORY; + options.name = 'local'; } else if (options.url[options.url.length - 1] !== '/') { options.url += '/'; } Object.defineProperties(this, { + 'title': {'value': options.title || options.name}, + 'name': {'value': options.name}, + 'permissions': {'value': options.permissions}, + 'url': {value: options.url}, 'RESOURCE_CHANGELOG_ENTRY': {value: new utils.Template(options.url + 'catalogue/resource/%(vendor)s/%(name)s/%(version)s/changelog')}, 'RESOURCE_USERGUIDE_ENTRY': {value: new utils.Template(options.url + 'catalogue/resource/%(vendor)s/%(name)s/%(version)s/userguide')}, 'RESOURCE_COLLECTION': {value: options.url + 'catalogue/resources'}, @@ -76,7 +86,7 @@ */ WirecloudCatalogue.prototype.search = function search(options) { if (options == null) { - throw new TypeError(); + options = {}; } var params = {}; @@ -115,51 +125,35 @@ requestHeaders: {'Accept': 'application/json'}, parameters: params }).then((response) => { - return new Promise((resolve, reject) => { - if ([200, 401, 403, 500].indexOf(response.status) === -1) { - return reject(utils.gettext("Unexpected response from server")); - } else if ([401, 403, 500].indexOf(response.status) !== -1) { - return reject(Wirecloud.GlobalLogManager.parseErrorResponse(response)); - } + if ([200, 401, 403, 500].indexOf(response.status) === -1) { + return Promise.reject(utils.gettext("Unexpected response from server")); + } else if ([401, 403, 500].indexOf(response.status) !== -1) { + return Promise.reject(Wirecloud.GlobalLogManager.parseErrorResponse(response)); + } - var raw_data = JSON.parse(response.responseText); - var data = { - 'resources': raw_data.results, - 'current_page': parseInt(raw_data.pagenum, 10), - 'total_count': parseInt(raw_data.total, 10) - }; - if ('corrected_q' in raw_data) { - data.corrected_query = raw_data.corrected_q; - } - resolve(data); - }); + var raw_data = JSON.parse(response.responseText); + var data = { + 'resources': raw_data.results, + 'current_page': parseInt(raw_data.pagenum, 10), + 'total_count': parseInt(raw_data.total, 10) + }; + if ('corrected_q' in raw_data) { + data.corrected_query = raw_data.corrected_q; + } + return Promise.resolve(data); }).toTask(utils.gettext("Doing catalogue search")); }; - WirecloudCatalogue.prototype.getResourceDetails = function getResourceDetails(vendor, name, options) { - - if (options == null) { - options = {}; - } + WirecloudCatalogue.prototype.getResourceDetails = function getResourceDetails(vendor, name) { var url = this.RESOURCE_UNVERSIONED_ENTRY.evaluate({vendor: vendor, name: name}); - Wirecloud.io.makeRequest(url, { - method: 'GET', - onSuccess: function (response) { - var resource_details = new Wirecloud.WirecloudCatalogue.ResourceDetails(JSON.parse(response.responseText), this); - try { - options.onSuccess(resource_details); - } catch (e) {} - }.bind(this), - onFailure: options.onFailure, - onComplete: options.onComplete + return Wirecloud.io.makeRequest(url, { + method: 'GET' + }).then((response) => { + return Promise.resolve(new Wirecloud.WirecloudCatalogue.ResourceDetails(JSON.parse(response.responseText), this)); }); }; - WirecloudCatalogue.prototype.is_purchased = function is_purchased() { - return true; - }; - /** * Installs a component into this catalogue. * @@ -170,7 +164,7 @@ WirecloudCatalogue.prototype.addComponent = function addComponent(options) { var url, parameters, requestHeaders, contentType, body; - if (typeof options == null) { + if (options == null) { throw new TypeError("missing options parameter"); } @@ -178,8 +172,10 @@ install_embedded_resources: true }, options); - if (this.name !== 'local' && options.market_endpoint !== null) { + if (this.name !== 'local' && options.market_endpoint != null) { throw new TypeError(utils.gettext("market_endpoint option can only be used on local catalogues")); + } else if (options.market_endpoint == null && options.file == null && options.url == null) { + throw new TypeError(utils.gettext("at least one of the following options has to be used: file or market_endpoint")); } requestHeaders = { @@ -190,10 +186,11 @@ url = Wirecloud.URLs.LOCAL_RESOURCE_COLLECTION; } else { url = this.RESOURCE_COLLECTION; - + /* TODO future support for external catalogues with authentication if (this.accesstoken != null) { requestHeaders.Authorization = 'Bearer ' + this.accesstoken; } + */ } if (options.file != null) { @@ -285,7 +282,7 @@ return new Promise(function (resolve, reject) { var result; if (response.status !== 200) { - reject(new Error("Unexpected response from server")); + return reject(new Error("Unexpected response from server")); } try { @@ -294,8 +291,7 @@ result.affectedVersions = [resource.version.text]; } } catch (e) { - reject(e); - return; + return reject(new Error("Unexpected response from server")); } resolve(result); }); diff --git a/src/wirecloud/catalogue/tests/selenium.py b/src/wirecloud/catalogue/tests/selenium.py index 29ef78aa18..3733279ffe 100644 --- a/src/wirecloud/catalogue/tests/selenium.py +++ b/src/wirecloud/catalogue/tests/selenium.py @@ -30,13 +30,6 @@ class CatalogueSeleniumTests(WirecloudSeleniumTestCase): tags = ('wirecloud-selenium', 'wirecloud-catalogue', 'wirecloud-catalogue-selenium') populate = False - def test_upload_packaged_mashup(self): - - self.login() - - with self.myresources_view as myresources: - myresources.upload_resource('Wirecloud_PackagedTestMashup_1.0.zip', 'PackagedTestMashup', shared=True) - def test_upload_packaged_mashup_embedded_resources(self): self.login() @@ -72,11 +65,3 @@ def test_upload_and_instantiate_widget(self): myresources.upload_resource('Wirecloud_Test_Selenium_1.0.wgt', 'Test_Selenium', shared=True) self.create_widget('Test_Selenium') - - def test_upload_and_delete_widget(self): - - self.login() - - with self.myresources_view as myresources: - myresources.upload_resource('Wirecloud_Test_Selenium_1.0.wgt', 'Test_Selenium', shared=True) - myresources.delete_resource('Test_Selenium') diff --git a/src/wirecloud/platform/static/js/catalogue/CatalogueView.js b/src/wirecloud/platform/static/js/catalogue/CatalogueView.js index a4068b10d3..d5fd683786 100644 --- a/src/wirecloud/platform/static/js/catalogue/CatalogueView.js +++ b/src/wirecloud/platform/static/js/catalogue/CatalogueView.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2017 CoNWeT Lab., Universidad Politécnica de Madrid + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. * * This file is part of Wirecloud Platform. * @@ -197,10 +198,13 @@ onSuccess.call(this, resource); onComplete.call(this); } else { - this.catalogue.getResourceDetails(resource.vendor, resource.name, { - onSuccess: onSuccess.bind(this), - onComplete: onComplete.bind(this) - }); + this.catalogue.getResourceDetails(resource.vendor, resource.name).then( + (resource) => { + onSuccess.call(this, resource); + onComplete.call(this); + }, + onComplete.bind(this) + ); } }.bind(this); }; diff --git a/src/wirecloud/platform/static/js/wirecloud/ui/MyResourcesView.js b/src/wirecloud/platform/static/js/wirecloud/ui/MyResourcesView.js index 7676a93d62..a364f089c6 100644 --- a/src/wirecloud/platform/static/js/wirecloud/ui/MyResourcesView.js +++ b/src/wirecloud/platform/static/js/wirecloud/ui/MyResourcesView.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2017 CoNWeT Lab., Universidad Politécnica de Madrid + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. * * This file is part of Wirecloud Platform. * @@ -321,10 +322,13 @@ onSuccess.call(this, resource); onCompleteRequest.call(this); } else { - this.catalogue.getResourceDetails(resource.vendor, resource.name, { - onSuccess: onSuccess.bind(this), - onComplete: onCompleteRequest.bind(this) - }); + this.catalogue.getResourceDetails(resource.vendor, resource.name).then( + (resource) => { + onSuccess.call(this, resource); + onCompleteRequest.call(this); + }, + onCompleteRequest.bind(this) + ); } }.bind(this); }; From 8ceabc91e38b1cee22fdcc86a7cc6eb66917054c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Tue, 11 Sep 2018 21:39:45 +0200 Subject: [PATCH 14/23] Fix out of bounds problems in the component_dropped_out_of_bounds_should_be_added test --- src/wirecloud/platform/wiring/tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wirecloud/platform/wiring/tests.py b/src/wirecloud/platform/wiring/tests.py index 8e3b94b716..99c13ec91b 100644 --- a/src/wirecloud/platform/wiring/tests.py +++ b/src/wirecloud/platform/wiring/tests.py @@ -2429,8 +2429,8 @@ def test_component_dropped_out_of_bounds_should_be_added(self): with self.wiring_view as wiring: with wiring.component_sidebar as sidebar: - self.assertIsNotNone(sidebar.add_component('operator', "Wirecloud/TestOperator", y=-250)) - self.assertIsNotNone(sidebar.add_component('widget', "Wirecloud/Test", title="Test (1)", x=-450)) + self.assertIsNotNone(sidebar.add_component('operator', "Wirecloud/TestOperator", y=-20)) + self.assertIsNotNone(sidebar.add_component('widget', "Wirecloud/Test", title="Test (1)", x=-4)) def test_rename_widget_from_component_preferences(self): new_title = "New title" From 816e76f69df40405ec7c8b66ac3889579f501e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Tue, 11 Sep 2018 21:41:58 +0200 Subject: [PATCH 15/23] Move MessageWindowMenu to commons --- src/GruntFile.js | 2 +- .../static/js/wirecloud/ui/MessageWindowMenu.js | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/wirecloud/{platform => commons}/static/js/wirecloud/ui/MessageWindowMenu.js (100%) diff --git a/src/GruntFile.js b/src/GruntFile.js index 52812c6808..4154176416 100644 --- a/src/GruntFile.js +++ b/src/GruntFile.js @@ -106,6 +106,7 @@ var WirecloudFiles = [ 'wirecloud/commons/static/js/wirecloud/ui/MACSearch.js', 'wirecloud/commons/static/js/wirecloud/ui/WindowMenu.js', 'wirecloud/commons/static/js/wirecloud/ui/AlertWindowMenu.js', + 'wirecloud/commons/static/js/wirecloud/ui/MessageWindowMenu.js', 'wirecloud/catalogue/static/js/wirecloud/WirecloudCatalogue.js', 'wirecloud/catalogue/static/js/wirecloud/ui/ResourcePainter.js', 'wirecloud/platform/static/js/wirecloud/io.js', @@ -119,7 +120,6 @@ var WirecloudFiles = [ 'wirecloud/platform/static/js/wirecloud/Wiring.js', 'wirecloud/platform/static/js/wirecloud/Workspace.js', 'wirecloud/platform/static/js/wirecloud/wiring/Operator.js', - 'wirecloud/platform/static/js/wirecloud/ui/MessageWindowMenu.js', 'wirecloud/platform/static/js/wirecloud/ui/WiringEditor.js', 'wirecloud/platform/static/js/wirecloud/ui/WiringEditor/Endpoint.js', 'wirecloud/platform/static/js/wirecloud/wiring/KeywordSuggestion.js', diff --git a/src/wirecloud/platform/static/js/wirecloud/ui/MessageWindowMenu.js b/src/wirecloud/commons/static/js/wirecloud/ui/MessageWindowMenu.js similarity index 100% rename from src/wirecloud/platform/static/js/wirecloud/ui/MessageWindowMenu.js rename to src/wirecloud/commons/static/js/wirecloud/ui/MessageWindowMenu.js From 60ae3198addf0407e686764712e376710799151e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Wed, 12 Sep 2018 17:12:35 +0200 Subject: [PATCH 16/23] Improve Widget unit tests --- src/js_tests/wirecloud/WidgetSpec.js | 640 +++++++++++++++++- src/js_tests/wirecloud/wiring/OperatorSpec.js | 13 + src/wirecloud/platform/tests/selenium.py | 11 +- 3 files changed, 638 insertions(+), 26 deletions(-) diff --git a/src/js_tests/wirecloud/WidgetSpec.js b/src/js_tests/wirecloud/WidgetSpec.js index 35639e3c2c..d81423ab7a 100644 --- a/src/js_tests/wirecloud/WidgetSpec.js +++ b/src/js_tests/wirecloud/WidgetSpec.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 CoNWeT Lab., Universidad Politécnica de Madrid + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. * * This file is part of Wirecloud Platform. * @@ -28,16 +29,36 @@ var WORKSPACE_TAB = { workspace: { + contextManager: { + addCallback: jasmine.createSpy('addCallback'), + removeCallback: jasmine.createSpy('removeCallback') + }, isAllowed: jasmine.createSpy('isAllowed').and.callFake(() => { return true; }), restricted: false, view: {} }, - addEventListener: jasmine.createSpy('addEventListener') + addEventListener: jasmine.createSpy('addEventListener'), + removeEventListener: jasmine.createSpy('removeEventListener') }; Object.freeze(WORKSPACE_TAB); + var WORKSPACEVIEW_TAB = { + workspace: { + contextManager: { + addCallback: jasmine.createSpy('addCallback'), + removeCallback: jasmine.createSpy('removeCallback') + }, + restricted: false, + view: { + workspaceview: "id232" + } + }, + addEventListener: jasmine.createSpy('addEventListener'), + }; + Object.freeze(WORKSPACEVIEW_TAB); + var LOCKED_WORKSPACE_TAB = { workspace: { isAllowed: jasmine.createSpy('isAllowed').and.callFake(() => { @@ -64,6 +85,34 @@ }; Object.freeze(EMPTY_WIDGET_META); + var MISSING_WIDGET_META = { + title: "My Widget", + hasEndpoints: jasmine.createSpy("hasEndpoints").and.returnValue(false), + hasPreferences: jasmine.createSpy("hasPreferences").and.returnValue(false), + inputList: [], + missing: true, + requirements: [], + outputList: [], + preferenceList: [], + propertyList: [], + codeurl: "https://wirecloud.example.com/widgets/MyWidget/index.html" + }; + Object.freeze(EMPTY_WIDGET_META); + + var FULLSCREEN_WIDGET_META = { + title: "My Widget", + hasEndpoints: jasmine.createSpy("hasEndpoints").and.returnValue(false), + hasPreferences: jasmine.createSpy("hasPreferences").and.returnValue(false), + inputList: [], + missing: false, + requirements: [{}, {type: "feature", name: "FullscreenWidget"}], + outputList: [], + preferenceList: [], + propertyList: [], + codeurl: "https://wirecloud.example.com/widgets/MyWidget/index.html" + }; + Object.freeze(FULLSCREEN_WIDGET_META); + var PREF = new Wirecloud.UserPrefDef({name: "pref", type: "text", default: "other"}); var PROP = new Wirecloud.PersistentVariableDef({name: "prop", type: "text"}); var WIDGET_META = { @@ -94,25 +143,36 @@ Object.freeze(WIDGET_META); - // endsWith polyfill - if (!String.prototype.endsWith) { - String.prototype.endsWith = function (searchString, position) { - var subjectString = this.toString(); - if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { - position = subjectString.length; - } - position -= searchString.length; - var lastIndex = subjectString.indexOf(searchString, position); - return lastIndex !== -1 && lastIndex === position; - }; - } - - - describe("Wirecloud.Widget", function () { + // TODO beforeEach(() => { - Wirecloud.PropertyCommiter = jasmine.createSpy("PropertyCommiter"); + Wirecloud.PropertyCommiter = jasmine.createSpy("PropertyCommiter").and.returnValue({ + commit: jasmine.createSpy('commit') + }); + Wirecloud.ui.LogWindowMenu = jasmine.createSpy("LogWindowMenu").and.returnValue({ + htmlElement: { + classList: { + add: jasmine.createSpy("add") + } + }, + show: jasmine.createSpy("show") + }); + Wirecloud.Widget.PreferencesWindowMenu = jasmine.createSpy("PreferencesWindowMenu").and.returnValue({ + show: jasmine.createSpy("show") + }); + Wirecloud.contextManager = { + addCallback: jasmine.createSpy("addCallback"), + removeCallback: jasmine.createSpy("removeCallback") + }; + + }); + + // TODO + afterAll(() => { + delete Wirecloud.PropertyCommiter; + delete Wirecloud.ui.LogWindowMenu; + delete Wirecloud.Widget.PreferencesWindowMenu; }); describe("new Widget(tab, meta, data)", () => { @@ -220,6 +280,34 @@ expect(new URL(widget.codeurl)).toEqual(jasmine.any(URL)); }); + it("allow to instantiate fullscreen capable widgets", () => { + var widget = new Wirecloud.Widget(WORKSPACE_TAB, FULLSCREEN_WIDGET_META, { + id: "1" + }); + + expect(widget.wrapperElement.getAttribute("allowfullscreen")).toBe("true"); + }); + + it("handles tab remove events", () => { + WORKSPACE_TAB.addEventListener.calls.reset(); + let widget = new Wirecloud.Widget(WORKSPACE_TAB, EMPTY_WIDGET_META, { + id: "1" + }); + let listener = jasmine.createSpy("listener"); + widget.addEventListener("remove", listener); + + WORKSPACE_TAB.addEventListener.calls.argsFor(0)[1](WORKSPACE_TAB); + + expect(listener).toHaveBeenCalled(); + }); + + it("allow to instantiate widgets on workspaceviews", () => { + let widget = new Wirecloud.Widget(WORKSPACEVIEW_TAB, EMPTY_WIDGET_META, { + id: "1" + }); + expect(widget.codeurl).toBe("https://wirecloud.example.com/widgets/MyWidget/index.html#id=1&workspaceview=id232"); + }); + }); describe("changeTab(tab)", () => { @@ -293,6 +381,246 @@ }); + describe("load()", () => { + + it("loads unloaded widgets", () => { + + let widget = new Wirecloud.Widget(WORKSPACE_TAB, WIDGET_META, { + id: "1" + }); + let element = widget.wrapperElement; + + widget.wrapperElement = { + contentDocument: { + defaultView: { + addEventListener: jasmine.createSpy("addEventListener") + } + }, + contentWindow: { + location: { + replace: jasmine.createSpy("replace") + } + }, + setAttribute: jasmine.createSpy("setAttribute") + }; + + expect(widget.load()).toBe(widget); + + // Widget should now be in loading false + expect(widget.loaded).toBe(false); + expect(widget.wrapperElement.contentWindow.location.replace).toHaveBeenCalledWith(widget.codeurl); + expect(widget.wrapperElement.setAttribute).toHaveBeenCalledWith("type", widget.codecontenttype); + + // Should ignore initial load events raised in between + element.dispatchEvent(new Event("load")); + expect(widget.wrapperElement.contentDocument.defaultView.addEventListener).not.toHaveBeenCalled(); + + // Emulate final load event + widget.wrapperElement.contentWindow.location.href = widget.codeurl; + element.dispatchEvent(new Event("load")); + + // Now the widget should be fully loaded + expect(widget.loaded).toBe(true); + expect(widget.wrapperElement.contentDocument.defaultView.addEventListener).toHaveBeenCalled(); + }); + + it("loads missing widgets", () => { + let widget = new Wirecloud.Widget(WORKSPACE_TAB, MISSING_WIDGET_META, { + id: "1" + }); + let element = widget.wrapperElement; + + widget.wrapperElement = { + contentDocument: { + defaultView: { + addEventListener: jasmine.createSpy("addEventListener") + } + }, + contentWindow: { + location: { + replace: jasmine.createSpy("replace") + } + }, + setAttribute: jasmine.createSpy("setAttribute") + }; + + expect(widget.load()).toBe(widget); + + // Emulate final load event + widget.wrapperElement.contentWindow.location.href = widget.codeurl; + element.dispatchEvent(new Event("load")); + + // Now the widget should be fully loaded + expect(widget.loaded).toBe(true); + expect(widget.wrapperElement.contentDocument.defaultView.addEventListener).toHaveBeenCalled(); + }); + + it("sends pending events", () => { + var widget = new Wirecloud.Widget(WORKSPACE_TAB, WIDGET_META, { + id: "1" + }); + let element = widget.wrapperElement; + widget.wrapperElement = { + contentDocument: { + defaultView: { + addEventListener: jasmine.createSpy("addEventListener") + } + }, + contentWindow: { + location: { + href: widget.codeurl, + replace: jasmine.createSpy("replace") + } + }, + setAttribute: jasmine.createSpy("setAttribute") + }; + widget.pending_events.push({endpoint: "input", value: "hello world"}); + + widget.load(); + element.dispatchEvent(new Event("load")); + + // Now the widget should be fully loaded + expect(widget.loaded).toBe(true); + expect(widget.wrapperElement.contentDocument.defaultView.addEventListener).toHaveBeenCalled(); + expect(widget.pending_events).toEqual([]); + }); + + it("does nothing for widgets in loading state", () => { + + let widget = new Wirecloud.Widget(WORKSPACE_TAB, WIDGET_META, { + id: "1" + }); + widget.wrapperElement = { + contentWindow: { + location: { + replace: jasmine.createSpy("replace") + } + }, + setAttribute: jasmine.createSpy("setAttribute") + }; + expect(widget.load()).toBe(widget); + widget.wrapperElement.contentWindow.location.replace.calls.reset(); + widget.wrapperElement.setAttribute.calls.reset(); + + expect(widget.load()).toBe(widget); + + expect(widget.wrapperElement.contentWindow.location.replace).not.toHaveBeenCalled(); + expect(widget.wrapperElement.setAttribute).not.toHaveBeenCalled(); + }); + + it("does nothing for loaded widgets", () => { + + let widget = new Wirecloud.Widget(WORKSPACE_TAB, WIDGET_META, { + id: "1" + }); + let element = widget.wrapperElement; + widget.wrapperElement = { + contentDocument: { + defaultView: { + addEventListener: jasmine.createSpy("addEventListener") + } + }, + contentWindow: { + location: { + href: widget.codeurl, + replace: jasmine.createSpy("replace") + } + }, + setAttribute: jasmine.createSpy("setAttribute") + }; + expect(widget.load()).toBe(widget); + widget.wrapperElement.contentWindow.location.replace.calls.reset(); + widget.wrapperElement.setAttribute.calls.reset(); + element.dispatchEvent(new Event("load")); + expect(widget.loaded).toBe(true); + + expect(widget.load()).toBe(widget); + + expect(widget.wrapperElement.contentWindow.location.replace).not.toHaveBeenCalled(); + expect(widget.wrapperElement.setAttribute).not.toHaveBeenCalled(); + }); + + it("handles unload events", () => { + + let widget = new Wirecloud.Widget(WORKSPACE_TAB, WIDGET_META, { + id: "1" + }); + let listener = jasmine.createSpy(); + widget.registerContextAPICallback("iwidget", listener); + widget.registerContextAPICallback("mashup", listener); + widget.registerContextAPICallback("platform", listener); + let element = widget.wrapperElement; + + widget.wrapperElement = { + contentDocument: { + defaultView: { + addEventListener: jasmine.createSpy("addEventListener") + } + }, + contentWindow: { + location: { + replace: jasmine.createSpy("replace") + } + }, + setAttribute: jasmine.createSpy("setAttribute") + }; + + expect(widget.load()).toBe(widget); + + // Emulate final load event + widget.wrapperElement.contentWindow.location.href = widget.codeurl; + element.dispatchEvent(new Event("load")); + + // Now the widget should be fully loaded + expect(widget.loaded).toBe(true); + + // Send unload event + widget.wrapperElement.contentDocument.defaultView.addEventListener.calls.argsFor(0)[1](); + + expect(widget.callbacks.iwidget).toEqual([]); + expect(widget.callbacks.mashup).toEqual([]); + expect(widget.callbacks.platform).toEqual([]); + }); + + it("ignores unload events when unloaded", () => { + + let widget = new Wirecloud.Widget(WORKSPACE_TAB, WIDGET_META, { + id: "1" + }); + let element = widget.wrapperElement; + + widget.wrapperElement = { + contentDocument: { + defaultView: { + addEventListener: jasmine.createSpy("addEventListener") + } + }, + contentWindow: { + location: { + replace: jasmine.createSpy("replace") + } + }, + setAttribute: jasmine.createSpy("setAttribute") + }; + + expect(widget.load()).toBe(widget); + + // Emulate final load event + widget.wrapperElement.contentWindow.location.href = widget.codeurl; + element.dispatchEvent(new Event("load")); + + // Send unload event + widget.wrapperElement.contentDocument.defaultView.addEventListener.calls.argsFor(0)[1](); + + // Now the widget should be fully unloaded + expect(widget.loaded).toBe(false); + + // Send a second unload event + widget.wrapperElement.contentDocument.defaultView.addEventListener.calls.argsFor(0)[1](); + }); + + }); + describe("fullDisconnect()", () => { it("is a shortcut for calling fullDisconnect on every endpoint", () => { @@ -402,6 +730,17 @@ expect(widget.isAllowed("close")).toBe(true); }); + it("readonly widget", () => { + var widget = new Wirecloud.Widget(WORKSPACE_TAB, EMPTY_WIDGET_META, { + id: "1", + permissions: { + close: true + }, + readonly: true + }); + expect(widget.isAllowed("close")).toBe(false); + }); + }); describe("move", () => { @@ -489,9 +828,82 @@ }); + describe("registerContextAPICallback(scope, callback)", () => { + var widget; + + beforeEach(() => { + widget = new Wirecloud.Widget(WORKSPACE_TAB, EMPTY_WIDGET_META, { + id: "1", + title: "old title" + }); + }); + + it("throws a TypeError exception when passing an invalid scope", () => { + let listener = jasmine.createSpy(); + expect(() => { + widget.registerContextAPICallback("invalid", listener); + }).toThrowError(TypeError); + }); + + it("support registering widget context callbacks", () => { + let listener = jasmine.createSpy(); + widget.registerContextAPICallback("iwidget", listener); + }); + + it("support registering mashup context callbacks", () => { + let listener = jasmine.createSpy(); + WORKSPACE_TAB.workspace.contextManager.addCallback.calls.reset(); + + widget.registerContextAPICallback("mashup", listener); + + expect(WORKSPACE_TAB.workspace.contextManager.addCallback).toHaveBeenCalledWith(listener); + }); + + it("support registering platform context callbacks", () => { + let listener = jasmine.createSpy(); + widget.registerContextAPICallback("platform", listener); + }); + + }); + + describe("registerPrefCallback(callback)", () => { + + it("should register preference callbacks", () => { + var listener = jasmine.createSpy("listener"); + var widget = new Wirecloud.Widget(WORKSPACE_TAB, EMPTY_WIDGET_META, { + id: "1", + title: "old title" + }); + expect(widget.registerPrefCallback(listener)).toBe(widget); + }); + + }); + + describe("reload()", () => { + + it("should reload widget view", () => { + var widget = new Wirecloud.Widget(WORKSPACE_TAB, EMPTY_WIDGET_META, { + id: "1", + title: "old title" + }); + widget.wrapperElement = { + contentWindow: { + location: { + reload: jasmine.createSpy("reload") + } + }, + setAttribute: jasmine.createSpy("setAttribute") + }; + expect(widget.reload()).toBe(widget); + + expect(widget.wrapperElement.contentWindow.location.reload).toHaveBeenCalledWith(); + }); + + }); + describe("remove()", () => { - it("support removing volatile widgets", (done) => { + it("supports removing volatile widgets", (done) => { var listener = jasmine.createSpy("listener"); var widget = new Wirecloud.Widget(LOCKED_WORKSPACE_TAB, EMPTY_WIDGET_META, { id: "1/1", @@ -508,6 +920,40 @@ }); }); + it("supports removing loaded widgets", (done) => { + let listener = jasmine.createSpy("listener"); + let widget = new Wirecloud.Widget(LOCKED_WORKSPACE_TAB, EMPTY_WIDGET_META, { + id: "1/1", + title: "old title", + volatile: true + }); + let element = widget.wrapperElement; + widget.wrapperElement = { + contentDocument: { + defaultView: { + addEventListener: jasmine.createSpy("addEventListener") + } + }, + contentWindow: { + location: { + href: widget.codeurl, + replace: jasmine.createSpy("replace") + } + }, + setAttribute: jasmine.createSpy("setAttribute") + }; + widget.load(); + element.dispatchEvent(new Event("load")); + + widget.addEventListener("remove", listener); + var p = widget.remove(); + p.then((value) => { + expect(value).toBe(value); + expect(listener).toHaveBeenCalled(); + done(); + }); + }); + it("removes widget from persistence", (done) => { var widget = new Wirecloud.Widget(WORKSPACE_TAB, EMPTY_WIDGET_META, { @@ -652,6 +1098,122 @@ }); + describe("setPosition(position)", () => { + + var widget; + + beforeEach(() => { + widget = new Wirecloud.Widget(LOCKED_WORKSPACE_TAB, EMPTY_WIDGET_META, { + id: "1/1", + title: "old title" + }); + }); + + it("should do nothing when passing an empty position", () => { + let initial_position = widget.position; + + expect(widget.setPosition({})).toBe(widget); + + expect(widget.position).toEqual(initial_position); + }); + + it("should allow to modify all the position properties", () => { + const new_position = { + x: 1, + y: 2, + z: 3 + }; + expect(widget.setPosition(new_position)).toBe(widget); + + expect(widget.position).toEqual(new_position); + }); + + it("should ignore extra properties", () => { + const new_position = { + extra: 123, + x: 1, + y: 2, + z: 3 + }; + expect(widget.setPosition(new_position)).toBe(widget); + + expect(widget.position).toEqual({ + x: 1, + y: 2, + z: 3 + }); + }); + + }); + + describe("setShape(shape)", () => { + + var widget; + + beforeEach(() => { + widget = new Wirecloud.Widget(LOCKED_WORKSPACE_TAB, EMPTY_WIDGET_META, { + id: "1/1", + title: "old title" + }); + }); + + it("should do nothing when passing an empty shape", () => { + let initial_shape = widget.shape; + + expect(widget.setShape({})).toBe(widget); + + expect(widget.shape).toEqual(initial_shape); + }); + + it("should allow to modify all the shape properties", () => { + const new_shape = { + width: 2, + height: 3 + }; + expect(widget.setShape(new_shape)).toBe(widget); + + expect(widget.shape).toEqual(new_shape); + }); + + it("should ignore extra properties", () => { + const new_shape = { + extra: 123, + width: 2, + height: 3 + }; + expect(widget.setShape(new_shape)).toBe(widget); + + expect(widget.shape).toEqual({ + width: 2, + height: 3 + }); + }); + + }); + + describe("showLogs()", () => { + + it("shows a log window menu", () => { + var widget = new Wirecloud.Widget(WORKSPACE_TAB, EMPTY_WIDGET_META, { + id: "1" + }); + + expect(widget.showLogs()).toBe(widget); + }); + + }); + + describe("showSettings()", () => { + + it("shows a window menu for changing widget preferences", () => { + var widget = new Wirecloud.Widget(WORKSPACE_TAB, EMPTY_WIDGET_META, { + id: "1" + }); + expect(widget.showSettings()).toBe(widget); + }); + + }); + describe("upgrade(meta)", () => { var failOnPreferences = false; var failOnProperties = false; @@ -847,6 +1409,48 @@ }); + it("handle status transition from loaded widget", (done) => { + + var widget = new Wirecloud.Widget(WORKSPACE_TAB, EMPTY_WIDGET_META, { + id: "1" + }); + let element = widget.wrapperElement; + widget.wrapperElement = { + contentDocument: { + defaultView: { + addEventListener: jasmine.createSpy("addEventListener") + } + }, + contentWindow: { + location: { + href: widget.codeurl, + replace: jasmine.createSpy("replace") + } + }, + setAttribute: jasmine.createSpy("setAttribute") + }; + widget.load(); + element.dispatchEvent(new Event("load")); + + var new_meta = new Wirecloud.WidgetMeta(); + new_meta.version.compareTo.and.returnValue(1); + var p = widget.upgrade(new_meta); + p.then( + (value) => { + expect(Wirecloud.io.makeRequest).toHaveBeenCalled(); + expect(widget.meta).toBe(new_meta); + expect(widget.preferences.npref).toEqual(jasmine.any(Wirecloud.UserPref)); + expect(widget.preferences.npref.value).toBe("upgraded value"); + expect(widget.preferences.pref).toBe(undefined); + done(); + }, + (error) => { + fail("error callback called"); + } + ); + + }); + it("handle error saving meta change into the server", (done) => { var widget = new Wirecloud.Widget(WORKSPACE_TAB, EMPTY_WIDGET_META, { diff --git a/src/js_tests/wirecloud/wiring/OperatorSpec.js b/src/js_tests/wirecloud/wiring/OperatorSpec.js index e83703d9e4..bdeeff40d9 100644 --- a/src/js_tests/wirecloud/wiring/OperatorSpec.js +++ b/src/js_tests/wirecloud/wiring/OperatorSpec.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 CoNWeT Lab., Universidad Politécnica de Madrid + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. * * This file is part of Wirecloud Platform. * @@ -90,6 +91,18 @@ describe("Wirecloud.wiring.Operator", function () { + // TODO + beforeEach(() => { + Wirecloud.PropertyCommiter = jasmine.createSpy("PropertyCommiter").and.returnValue({ + commit: jasmine.createSpy('commit') + }); + }); + + // TODO + afterAll(() => { + delete Wirecloud.PropertyCommiter; + }); + describe("new Operator(wiring, meta, [data])", function () { it("throws a TypeError exception if wiring is not a Wiring instance", function () { diff --git a/src/wirecloud/platform/tests/selenium.py b/src/wirecloud/platform/tests/selenium.py index e07e26da03..fe2ee345b3 100644 --- a/src/wirecloud/platform/tests/selenium.py +++ b/src/wirecloud/platform/tests/selenium.py @@ -125,21 +125,16 @@ def test_remove_tab_from_workspace(self): with self.wiring_view as wiring: self.assertIsNone(wiring.find_draggable_component('widget', title="Test 1")) - def test_read_only_widgets_cannot_be_removed(self): + def test_tabs_with_read_only_widgets_cannot_be_removed(self): self.login(username='user_with_workspaces', next='/user_with_workspaces/pending-events') tab = self.find_tab(title="Tab 2") - tab.click() + tab.show_preferences().check(must_be_disabled=('Remove',)) + tab.click() tab_widget = tab.find_widget(title="Test 2") self.assertTrue(tab_widget.remove_button.is_disabled) - def test_tabs_with_read_only_widgets_cannot_be_removed(self): - self.login(username='user_with_workspaces', next='/user_with_workspaces/pending-events') - - tab = self.find_tab(title="Tab 2") - tab.show_preferences().check(must_be_disabled=('Remove',)) - def test_refresh_widget(self): self.login(username="user_with_workspaces", next="/user_with_workspaces/Workspace") From a8c873d17e25690e45f8b041a43e8351998e5eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Thu, 13 Sep 2018 14:38:04 +0200 Subject: [PATCH 17/23] Fix some problems using AlertWindowMenu --- .../js/WirecloudAPI/DashboardManagementAPI.js | 6 ++--- .../wirecloud/ui/MarketplaceViewMenuItems.js | 6 ++--- .../static/js/wirecloud/ui/MyResourcesView.js | 6 ++--- .../static/js/wirecloud/ui/WiringEditor.js | 6 ++--- .../js/wirecloud/ui/WiringEditor/Behaviour.js | 6 ++--- .../ui/WiringEditor/BehaviourEngine.js | 23 ++++++++----------- .../js/wirecloud/ui/WorkspaceTabView.js | 6 ++--- 7 files changed, 26 insertions(+), 33 deletions(-) diff --git a/src/wirecloud/platform/static/js/WirecloudAPI/DashboardManagementAPI.js b/src/wirecloud/platform/static/js/WirecloudAPI/DashboardManagementAPI.js index 30acbd0332..47145b9ab0 100644 --- a/src/wirecloud/platform/static/js/WirecloudAPI/DashboardManagementAPI.js +++ b/src/wirecloud/platform/static/js/WirecloudAPI/DashboardManagementAPI.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2017 CoNWeT Lab., Universidad Politécnica de Madrid + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. * * This file is part of Wirecloud Platform. * @@ -154,10 +155,9 @@ name: workspace.owner + '/' + workspace.name }) ); - dialog.setHandler(function () { + dialog.setHandler(() => { Wirecloud.removeWorkspace(workspace).then(options.onSuccess, options.onFailure); - }.bind(this)); - dialog.show(); + }).show(); }; var addWidget = function addWidget(ref, options) { diff --git a/src/wirecloud/platform/static/js/wirecloud/ui/MarketplaceViewMenuItems.js b/src/wirecloud/platform/static/js/wirecloud/ui/MarketplaceViewMenuItems.js index 7883d59ecc..b1972f73f4 100644 --- a/src/wirecloud/platform/static/js/wirecloud/ui/MarketplaceViewMenuItems.js +++ b/src/wirecloud/platform/static/js/wirecloud/ui/MarketplaceViewMenuItems.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2017 CoNWeT Lab., Universidad Politécnica de Madrid + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. * * This file is part of Wirecloud Platform. * @@ -117,7 +118,7 @@ var msg = utils.gettext('Do you really want to remove the marketplace "%(marketName)s"?'); msg = utils.interpolate(msg, {'marketName': this.market.alternatives.getCurrentAlternative().getLabel()}); var dialog = new Wirecloud.ui.AlertWindowMenu(msg); - dialog.setHandler(function () { + dialog.setHandler(() => { Wirecloud.UserInterfaceManager.monitorTask( Wirecloud.MarketManager.deleteMarket(this.market.alternatives.getCurrentAlternative().desc) .then(this.market.refreshViewInfo.bind(this.market)) @@ -126,8 +127,7 @@ Wirecloud.GlobalLogManager.log(error); }) ); - }.bind(this)); - dialog.show(); + }).show(); }.bind(this)); item.addIconClass('fa fa-trash'); item.setDisabled(current_catalogue == null || current_catalogue.isAllow == null || !current_catalogue.isAllow('delete')); diff --git a/src/wirecloud/platform/static/js/wirecloud/ui/MyResourcesView.js b/src/wirecloud/platform/static/js/wirecloud/ui/MyResourcesView.js index a364f089c6..4bc9a1bc7a 100644 --- a/src/wirecloud/platform/static/js/wirecloud/ui/MyResourcesView.js +++ b/src/wirecloud/platform/static/js/wirecloud/ui/MyResourcesView.js @@ -353,8 +353,7 @@ msg = utils.interpolate(msg, resource, true); return function () { var dialog = new Wirecloud.ui.AlertWindowMenu(msg); - dialog.setHandler(doRequest.bind(this)); - dialog.show(); + dialog.setHandler(doRequest.bind(this)).show(); }.bind(this); }; @@ -385,8 +384,7 @@ msg = utils.interpolate(msg, context, true); return function () { var dialog = new Wirecloud.ui.AlertWindowMenu(msg); - dialog.setHandler(doRequest.bind(this)); - dialog.show(); + dialog.setHandler(doRequest.bind(this)).show(); }.bind(this); }; diff --git a/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor.js b/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor.js index dc23624869..86f03da1e2 100644 --- a/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor.js +++ b/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor.js @@ -3,6 +3,7 @@ * * Copyright (c) 2012-2016 Universidad Politécnica de Madrid * Copyright (c) 2012-2014 the Center for Open Middleware + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. * * Licensed under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance @@ -659,10 +660,9 @@ Wirecloud.ui = Wirecloud.ui || {}; message = builder.parse(builder.DEFAULT_OPENING + utils.gettext("The connection will also be modified for the rest of behaviours, would you like to continue?") + builder.DEFAULT_CLOSING); modal = new Wirecloud.ui.AlertWindowMenu(message); - modal.acceptHandler = function () { + modal.setHandler(() => { this.behaviourEngine.removeConnection(connection, true); - }.bind(this); - modal.show(); + }).show(); }; var component_onremove = function component_onremove(component) { diff --git a/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor/Behaviour.js b/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor/Behaviour.js index 5ea2b45e77..601c8d662c 100644 --- a/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor/Behaviour.js +++ b/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor/Behaviour.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2016 CoNWeT Lab., Universidad Politécnica de Madrid + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. * * This file is part of Wirecloud Platform. * @@ -388,10 +389,9 @@ acceptLabel: utils.gettext("Continue"), cancelLabel: utils.gettext("No, thank you") }); - dialog.acceptHandler = function () { + dialog.setHandler(() => { this.dispatchEvent('optremove'); - }.bind(this); - dialog.show(); + }).show(); }; var displayUpdateForm = function displayUpdateForm() { diff --git a/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor/BehaviourEngine.js b/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor/BehaviourEngine.js index 64fcb2a68c..2eb75dba3f 100644 --- a/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor/BehaviourEngine.js +++ b/src/wirecloud/platform/static/js/wirecloud/ui/WiringEditor/BehaviourEngine.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2016 CoNWeT Lab., Universidad Politécnica de Madrid + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. * * This file is part of Wirecloud Platform. * @@ -740,7 +741,7 @@ cancelLabel: utils.gettext("Cancel"), message: message }); - dialog.acceptHandler = function () { + dialog.setHandler(() => { for (var i = this.behaviours.length - 1; i >= 0; i--) { this.body.removeChild(this.behaviours[i]); } @@ -749,8 +750,7 @@ delete this.behaviour; this.enabled = false; this.dispatchEvent('enable', this.enabled); - }.bind(this); - dialog.show(); + }).show(); } else { this.enabled = true; this.createBehaviour(); @@ -815,8 +815,7 @@ }); modal = new Wirecloud.ui.AlertWindowMenu(message); - modal.acceptHandler = _removeComponent.bind(this, component, false); - modal.show(); + modal.setHandler(_removeComponent.bind(this, component, false)).show(); return this; }; @@ -839,16 +838,14 @@ components: components })); - modal = new Wirecloud.ui.AlertWindowMenu(); - modal.setMsg(message); - modal.acceptHandler = function () { + modal = new Wirecloud.ui.AlertWindowMenu(message); + modal.setHandler(() => { var i; for (i = 0; i < componentList.length; i++) { _removeComponent.call(this, componentList[i], false); } - }.bind(this); - modal.show(); + }).show(); return this; }; @@ -861,10 +858,8 @@ title: component.title }); - modal = new Wirecloud.ui.AlertWindowMenu(); - modal.setMsg(message); - modal.acceptHandler = _removeComponent.bind(this, component, true); - modal.show(); + modal = new Wirecloud.ui.AlertWindowMenu(message); + modal.setHandler(_removeComponent.bind(this, component, true)).show(); return this; }; diff --git a/src/wirecloud/platform/static/js/wirecloud/ui/WorkspaceTabView.js b/src/wirecloud/platform/static/js/wirecloud/ui/WorkspaceTabView.js index 65f2a70437..ade4a47496 100644 --- a/src/wirecloud/platform/static/js/wirecloud/ui/WorkspaceTabView.js +++ b/src/wirecloud/platform/static/js/wirecloud/ui/WorkspaceTabView.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2017 CoNWeT Lab., Universidad Politécnica de Madrid + * Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. * * This file is part of Wirecloud Platform. * @@ -223,10 +224,9 @@ if (privates.get(this).widgets.length) { var dialog = new Wirecloud.ui.AlertWindowMenu(utils.gettext("The tab's widgets will also be removed. Would you like to continue?")); - dialog.setHandler(function () { + dialog.setHandler(() => { _remove.call(this); - }.bind(this)); - dialog.show(); + }).show(); } else { _remove.call(this); } From 8e70356ecb529eb09b04f70269c882cc7eba2ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Thu, 13 Sep 2018 16:03:26 +0200 Subject: [PATCH 18/23] Make get_current_view return none if wirecloud is in transition --- src/wirecloud/commons/utils/remote.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wirecloud/commons/utils/remote.py b/src/wirecloud/commons/utils/remote.py index 2ca0d59877..accc3488c0 100644 --- a/src/wirecloud/commons/utils/remote.py +++ b/src/wirecloud/commons/utils/remote.py @@ -1368,7 +1368,7 @@ def login(self, username='admin', password='admin', next=None): def get_current_view(self): try: - return self.driver.execute_script("return Wirecloud.UserInterfaceManager.header.currentView.view_name;") + return self.driver.execute_script("return document.querySelector('.wc-body').classList.contains('se-on-transition') ? '' : Wirecloud.UserInterfaceManager.header.currentView.view_name;") except: return "" From 096eaf9e70e8fa22db4be97fdcc921fe40924ef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Thu, 13 Sep 2018 17:16:01 +0200 Subject: [PATCH 19/23] Fix some problems in the wait_wirecloud_ready method --- src/wirecloud/commons/utils/remote.py | 7 +++++-- src/wirecloud/platform/tests/selenium.py | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/wirecloud/commons/utils/remote.py b/src/wirecloud/commons/utils/remote.py index accc3488c0..df4b2730e2 100644 --- a/src/wirecloud/commons/utils/remote.py +++ b/src/wirecloud/commons/utils/remote.py @@ -1327,7 +1327,7 @@ def wait_wirecloud_unload(self, timeout=15): loading_window = self.wait_element_visible('#loading-window') WebDriverWait(self.driver, timeout).until(EC.staleness_of(loading_window)) - def wait_wirecloud_ready(self, start_timeout=10, timeout=10): + def wait_wirecloud_ready(self, start_timeout=10, timeout=10, embedded=False): loading_window = None @@ -1343,7 +1343,10 @@ def wait_loading_window_fadding(driver): except: pass - self.wait_element_visible('.wc-body:not(.se-on-transition)') + if embedded: + self.wait_element_visible('.wc-body:not(.se-on-transition)') + else: + WebDriverWait(self.driver, 10).until(lambda driver: self.get_current_view() != '') time.sleep(0.2) # work around some problems diff --git a/src/wirecloud/platform/tests/selenium.py b/src/wirecloud/platform/tests/selenium.py index fe2ee345b3..1ed09bb304 100644 --- a/src/wirecloud/platform/tests/selenium.py +++ b/src/wirecloud/platform/tests/selenium.py @@ -699,7 +699,7 @@ def test_embedded_view(self): # Swicth to Wirecloud's iframe iframe = self.driver.find_element_by_id('iframe') self.driver.switch_to.frame(iframe) - self.wait_wirecloud_ready() + self.wait_wirecloud_ready(embedded=True) self.check_public_workspace(frame_id='iframe') def check_public_workspace(self, frame_id=None): From d4677a1f4a2d4dd8f79a307eef8f322a43fb1db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Fri, 14 Sep 2018 00:38:09 +0200 Subject: [PATCH 20/23] Fix problems selecting components on the wirecloud view (WiringViewTester.select) --- src/wirecloud/commons/utils/remote.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/wirecloud/commons/utils/remote.py b/src/wirecloud/commons/utils/remote.py index df4b2730e2..5259893230 100644 --- a/src/wirecloud/commons/utils/remote.py +++ b/src/wirecloud/commons/utils/remote.py @@ -2032,8 +2032,9 @@ def disabled(self): return 'disabled' in self.testcase.driver.find_element_by_css_selector(".wiring-view").get_attribute('class').split() def select(self, components=(), key=Keys.CONTROL): - actions = ActionChains(self.testcase.driver).key_down(key) + actions = ActionChains(self.testcase.driver) for component in components: - actions.click(component.element) - actions.key_up(key).perform() + actions.key_down(key).click(component.element) + actions.perform() + ActionChains(self.testcase.driver).key_up(key).perform() return self From 9ce4e6082f0eb766325b7c564ecc44fd38568475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Fri, 14 Sep 2018 19:35:56 +0200 Subject: [PATCH 21/23] Reduce time spent passing local catalogue selenium tests --- src/wirecloud/commons/utils/remote.py | 18 +- .../platform/localcatalogue/tests.py | 211 ++++++------------ 2 files changed, 83 insertions(+), 146 deletions(-) diff --git a/src/wirecloud/commons/utils/remote.py b/src/wirecloud/commons/utils/remote.py index 5259893230..8984d30248 100644 --- a/src/wirecloud/commons/utils/remote.py +++ b/src/wirecloud/commons/utils/remote.py @@ -474,10 +474,10 @@ def tab_created(driver): return WebDriverWait(self.driver, timeout=5).until(tab_created) - def create_widget(self, query, new_title=None): + def create_widget(self, query, new_title=None, version=None): with self.resource_sidebar as sidebar: resource = sidebar.search_component('widget', query) - tab_widget = resource.create_component() + tab_widget = resource.create_component(version=version) if new_title is not None: tab_widget.rename(new_title) @@ -561,7 +561,17 @@ def id(self): def title(self): return self.find_element('.we-component-meta .panel-title').text - def create_component(self): + @property + def version_select(self): + return Select(self.element.find_element_by_css_selector('.se-select select')) + + def switch_to(self, version): + self.version_select.select_by_value(version) + + def create_component(self, version=None): + if version is not None: + self.switch_to(version) + ids = [WidgetTester(self.testcase, e).id for e in self.testcase.driver.find_elements_by_css_selector(".wc-workspace .wc-widget")] self.testcase.scroll_and_click(self.find_element(".wc-create-resource-component")) @@ -1753,6 +1763,7 @@ def delete_resource(self, resource_name, version=None): if should_disappear_from_listings: WebDriverWait(self.testcase.driver, 5).until(EC.staleness_of(resource.element)) + time.sleep(0.2) resource = self.search_in_results(resource_name) if should_disappear_from_listings: self.testcase.assertIsNone(resource) @@ -1787,6 +1798,7 @@ def uninstall_resource(self, resource_name, version=None, expect_error=False): if should_disappear_from_listings: WebDriverWait(self.testcase.driver, 5).until(EC.staleness_of(resource.element)) + time.sleep(0.2) resource = self.search_in_results(resource_name) if should_disappear_from_listings: self.testcase.assertIsNone(resource) diff --git a/src/wirecloud/platform/localcatalogue/tests.py b/src/wirecloud/platform/localcatalogue/tests.py index 12d7dcf01a..854e852cb7 100644 --- a/src/wirecloud/platform/localcatalogue/tests.py +++ b/src/wirecloud/platform/localcatalogue/tests.py @@ -547,11 +547,18 @@ class LocalCatalogueSeleniumTests(WirecloudSeleniumTestCase): fixtures = ('selenium_test_data', 'user_with_workspaces') tags = ('wirecloud-localcatalogue', 'wirecloud-selenium', 'wirecloud-localcatalogue-selenium') + populate = False - def test_basic_resource_details(self): + def test_public_resources(self): + # Check admin can make use of the public Test widget + self.login(username="admin", next="/admin/Workspace") + self.create_widget('Test') - self.login() + # Check normuser also can make use of the public Test widget + self.login(username='normuser', next="/normuser/Workspace") + self.create_widget('Test') + # Also widget details can be accessed with self.myresources_view as myresources: myresources.wait_catalogue_ready() myresources.search('Test') @@ -569,13 +576,8 @@ def test_basic_resource_details(self): headings = documentation_contents.find_elements_by_css_selector('h1, h2') self.assertEqual(len(headings), 2) - def test_public_resources(self): - - self.login(username="admin", next="/admin/Workspace") - self.create_widget('Test') - - self.login(username='normuser', next="/normuser/Workspace") - self.create_widget('Test') + # But cannot be uninstalled by normal users + myresources.uninstall_resource('Test', expect_error=True) def test_resource_visibility(self): @@ -621,7 +623,7 @@ def test_resource_visibility(self): widget = myresources.search_in_results('Test') self.assertIsNotNone(widget) - def test_resource_deletion(self): + def test_resource_deletion_affects_other_workspaces(self): self.login(username="admin", next="/admin/Workspace") @@ -653,87 +655,6 @@ def test_resource_deletion(self): widget = myresources.search_in_results('Test') self.assertIsNone(widget) - def test_public_resources_are_uninstallable(self): - - self.login(username='normuser') - - with self.myresources_view as myresources: - myresources.uninstall_resource('Test', expect_error=True) - - def test_resource_uninstall(self): - - test_widget = CatalogueResource.objects.get(short_name='Test') - test_widget.public = False - test_widget.save() - - self.login(username='user_with_workspaces', next="/user_with_workspaces/Workspace") - - # WireCloud has cached current workspace - initial_workspace_widgets = len(self.widgets) - - # Switch to another workspace - self.change_current_workspace('Public Workspace') - current_workspace_widgets = len(self.widgets) - - # Uninstall Test widget - with self.myresources_view as myresources: - myresources.uninstall_resource('Test') - - # Check current workspace has no been affected - self.assertEqual(len(self.widgets), current_workspace_widgets) - - # Check WireCloud can load the initial workspace - self.change_current_workspace('Workspace') - self.assertEqual(len(self.widgets), initial_workspace_widgets) - - # Check admin still has access to the Test widget - self.login(username="admin", next="/admin/Workspace") - - self.create_widget('Test') - - def test_resource_uninstall_last_usage(self): - - norm_user = User.objects.get(username='normuser') - - test_widget = CatalogueResource.objects.get(short_name='Test') - test_widget.public = False - test_widget.users.clear() - test_widget.users.add(norm_user) - test_widget.groups.clear() - test_widget.save() - - self.login(username="normuser", next="/normuser/Workspace") - - # Add a Test widget to the initial workspace and cache it - self.create_widget('Test') - self.change_current_workspace('Workspace') - - # Create a new workspace with a test widget - self.create_workspace('Test') - self.create_widget('Test') - - # Uninstall Test widget - with self.myresources_view as myresources: - myresources.uninstall_resource('Test') - - # Check current workspace has only a missing widget - self.assertEqual(len(self.widgets), 1) - self.assertEqual(self.widgets[0].error_count, 1) - - # Check initial workspace has only a missing widget - self.change_current_workspace('Workspace') - self.assertEqual(len(self.widgets), 1) - self.assertEqual(self.widgets[0].error_count, 1) - - def test_resources_are_always_deletable_by_superusers(self): - - self.login() - - with self.myresources_view as myresources: - myresources.delete_resource('Test') - myresources.delete_resource('TestOperator') - myresources.delete_resource('Test Mashup') - def check_multiversioned_widget(self, admin): with self.myresources_view as myresources: @@ -759,8 +680,18 @@ def test_resource_with_several_versions(self): self.login(username='normuser') self.check_multiversioned_widget(admin=False) - @uses_extra_resources(('Wirecloud_Test_2.0.wgt',), shared=True, public=False, users=('user_with_workspaces',)) - def test_resource_uninstall_all_version(self): + @uses_extra_resources(( + 'Wirecloud_Test_2.0.wgt', + 'Wirecloud_Test_3.0.wgt', + 'Wirecloud_Test_Selenium_1.0.wgt', + 'Wirecloud_Test_Selenium_1.0-dev.wgt', + ), + shared=True, + public=False, + creator='user_with_workspaces', + users=('user_with_workspaces',) + ) + def test_resource_uninstall(self): user_with_workspaces = User.objects.get(username='user_with_workspaces') @@ -771,80 +702,74 @@ def test_resource_uninstall_all_version(self): test_widget.groups.clear() test_widget.save() - self.login(username='user_with_workspaces', next='/user_with_workspaces/pending-events') - - widgetV2 = self.create_widget('Test') - - # Uninstall all Test widget versions - with self.myresources_view as myresources: - myresources.uninstall_resource('Test') - - # The workspace should contain three missig widgets - self.assertEqual(len(self.widgets), 3) - # A Test v2.0 widget just created in this test - self.assertEqual(widgetV2.wait_loaded().error_count, 1) - - # And two Test v1.0 widget - # one in the first tab and another in the second one - self.assertEqual(self.find_widget(title="Test 1").error_count, 1) - self.find_tab(title="Tab 2").click() - self.assertEqual(self.find_widget(title="Test 2").error_count, 1) - - @uses_extra_resources(('Wirecloud_Test_2.0.wgt',), shared=True, public=False, users=('user_with_workspaces',)) - def test_resource_uninstall_version(self): - - self.login(username='user_with_workspaces', next="/user_with_workspaces/Workspace") + self.login(username='user_with_workspaces', next="/user_with_workspaces/pending-events") initial_widgets = self.widgets - # This is the only widget using version 2.0 and should automatically be - # unloaded after uninstalling version 2.0 of the Test widget - added_widget = self.create_widget('Test') + # add a widget using Test v3.0 + widgetV3 = self.create_widget('Test') + widgetT1 = self.create_widget('Test_Selenium', version='1.0') + widgetT2 = self.create_widget('Test_Selenium', version='1.0-dev') # Uninstall Test widget with self.myresources_view as myresources: - myresources.uninstall_resource('Test', version="2.0") + # Uninstall all versions of the Test_Selenium widget + myresources.uninstall_resource('Test_Selenium') + # Uninstall only one version of the Test widget + myresources.uninstall_resource('Test', version="1.0") - # Check current workspace has only a missing widget - self.assertEqual(len(self.widgets), len(initial_widgets) + 1) - self.assertEqual(added_widget.wait_loaded().error_count, 1) - for widget in initial_widgets: - self.assertEqual(widget.error_count, 0) - - @uses_extra_resources(('Wirecloud_Test_2.0.wgt',), shared=True) - def test_resource_delete_all_version(self): + # The workspace should contain four missig widgets and a surviving widget + self.assertEqual(len(self.widgets), 5) + # Test v3.0 widget is just the surviving one + self.assertEqual(widgetV3.wait_loaded().error_count, 0) - self.login() - - # Delete all versions of the Test widget - with self.myresources_view as myresources: - myresources.delete_resource('Test') + # But both Test_Selenium widget should be now marked as missing + self.assertEqual(widgetT1.wait_loaded().error_count, 1) + self.assertEqual(widgetT2.wait_loaded().error_count, 1) - self.login(username='normuser') - with self.myresources_view as myresources: - myresources.search('Test') - self.assertIsNone(myresources.search_in_results('Test')) - - @uses_extra_resources(('Wirecloud_Test_2.0.wgt',), shared=True) - def test_resource_delete_version(self): + # As the two Test v1.0 widgets + # one in the first tab and another in the second one + self.assertEqual(self.find_widget(title="Test 1").error_count, 1) + self.find_tab(title="Tab 2").click() + self.assertEqual(self.find_widget(title="Test 2").wait_loaded().error_count, 1) + + @uses_extra_resources(( + 'Wirecloud_Test_2.0.wgt', + 'Wirecloud_Test_3.0.wgt', + 'Wirecloud_Test_Selenium_1.0.wgt', + 'Wirecloud_Test_Selenium_1.0-dev.wgt', + ), + shared=True, + public=True, + creator='user_with_workspaces' + ) + def test_resource_delete(self): self.login() - # Delete Test widget with self.myresources_view as myresources: + # Delete all versions of the Test_Selenium widget + myresources.delete_resource('Test_Selenium') + # Delete version 1.0 of the Test widget myresources.delete_resource('Test', version="1.0") + # Delete also TestOperator and Test Mashup to check that + # those components can also be removed + myresources.delete_resource('TestOperator') + myresources.delete_resource('Test Mashup') self.login(username='normuser') with self.myresources_view as myresources: - myresources.wait_catalogue_ready() + myresources.search('Test_Selenium') + self.assertIsNone(myresources.search_in_results('Test_Selenium')) + myresources.search('Test') with myresources.search_in_results('Test') as test_widget: version_list = test_widget.get_version_list() versions = set(version_list) self.assertEqual(len(versions), len(version_list), 'Repeated versions') - self.assertEqual(versions, set(('v2.0',))) + self.assertEqual(versions, set(('v2.0', 'v3.0'))) @uses_extra_resources(('Wirecloud_Test_2.0.wgt',), shared=True) def test_myresources_navigation(self): From 5f194d196b5d9031dbc581c16eef3416052189c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Fri, 14 Sep 2018 23:35:40 +0200 Subject: [PATCH 22/23] Selenium: Fix some races conditions --- src/wirecloud/commons/utils/remote.py | 22 +++++++++++++++++----- src/wirecloud/platform/markets/tests.py | 17 +++++++++-------- src/wirecloud/platform/tests/selenium.py | 4 +--- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/wirecloud/commons/utils/remote.py b/src/wirecloud/commons/utils/remote.py index 8984d30248..117d7f1b33 100644 --- a/src/wirecloud/commons/utils/remote.py +++ b/src/wirecloud/commons/utils/remote.py @@ -1050,7 +1050,7 @@ def change_endpoint(self, endpoint, new_endpoint): if not self.has_class('active'): self.click() ActionChains(self.testcase.driver).click_and_hold(endpoint.element).move_to_element(new_endpoint.element).perform() - self.testcase.assertTrue(self.has_class('temporal')) + WebDriverWait(self.testcase.driver, 2).until(lambda driver: self.has_class('temporal')) ActionChains(self.testcase.driver).release().perform() return self @@ -1571,12 +1571,18 @@ def get_current_marketplace_name(self): def get_subview(self): - return self.testcase.driver.execute_script('return Wirecloud.UserInterfaceManager.views.marketplace.alternatives.getCurrentAlternative().alternatives.getCurrentAlternative().view_name;') + return self.testcase.driver.execute_script(''' + var alternatives = Wirecloud.UserInterfaceManager.views.marketplace.alternatives.getCurrentAlternative().alternatives; + return alternatives.hasClassName('se-on-transition') ? "" : alternatives.getCurrentAlternative().view_name; + ''') def get_current_resource(self): if self.get_subview() == 'details': - return self.testcase.driver.find_element_by_css_selector('#wirecloud_breadcrum .resource_title').text + try: + return self.testcase.driver.find_element_by_css_selector('#wirecloud_breadcrum .resource_title').text + except StaleElementReferenceException: + return "" def switch_to(self, market, timeout=5): @@ -1691,12 +1697,18 @@ def get_current_catalogue_base_element(self): def get_subview(self): - return self.testcase.driver.execute_script('return Wirecloud.UserInterfaceManager.views.myresources.alternatives.getCurrentAlternative().view_name;') + return self.testcase.driver.execute_script(''' + var alternatives = Wirecloud.UserInterfaceManager.views.myresources.alternatives; + return alternatives.hasClassName('se-on-transition') ? "" : alternatives.getCurrentAlternative().view_name; + ''') def get_current_resource(self): if self.get_subview() == 'details': - return self.testcase.driver.find_element_by_css_selector('#wirecloud_breadcrum .second_level').text + try: + return self.testcase.driver.find_element_by_css_selector('#wirecloud_breadcrum .second_level').text + except StaleElementReferenceException: + return "" def upload_resource(self, wgt_file, resource_name, shared=False, expect_error=False): diff --git a/src/wirecloud/platform/markets/tests.py b/src/wirecloud/platform/markets/tests.py index 83427af925..9d684d6f38 100644 --- a/src/wirecloud/platform/markets/tests.py +++ b/src/wirecloud/platform/markets/tests.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2012-2017 CoNWeT Lab., Universidad Politécnica de Madrid +# Copyright (c) 2018 Future Internet Consulting and Development Solutions S.L. # This file is part of Wirecloud. @@ -153,15 +154,15 @@ def test_marketplace_navigation(self): self.assertEqual(self.marketplace_view.get_current_marketplace_name(), 'origin') self.driver.back() - WebDriverWait(self.driver, timeout=5).until(lambda driver: self.marketplace_view.get_subview() == 'details') - self.assertEqual(self.marketplace_view.get_current_resource(), 'Test Mashup') + # get_current_resource also checks we are at the details subview + WebDriverWait(self.driver, timeout=5).until(lambda driver: self.marketplace_view.get_current_resource() == 'Test Mashup') self.driver.back() WebDriverWait(self.driver, timeout=5).until(lambda driver: self.marketplace_view.get_subview() == 'search') self.driver.back() - WebDriverWait(self.driver, timeout=5).until(lambda driver: self.marketplace_view.get_subview() == 'details') - self.assertEqual(self.marketplace_view.get_current_resource(), 'Test') + # get_current_resource also checks we are at the details subview + WebDriverWait(self.driver, timeout=5).until(lambda driver: self.marketplace_view.get_current_resource() == 'Test') self.driver.back() WebDriverWait(self.driver, timeout=5).until(lambda driver: self.marketplace_view.get_subview() == 'search') @@ -176,15 +177,15 @@ def test_marketplace_navigation(self): self.assertEqual(self.marketplace_view.get_subview(), 'search') self.driver.forward() - WebDriverWait(self.driver, timeout=5).until(lambda driver: self.marketplace_view.get_subview() == 'details') - self.assertEqual(self.marketplace_view.get_current_resource(), 'Test') + # get_current_resource also checks we are at the details subview + WebDriverWait(self.driver, timeout=5).until(lambda driver: self.marketplace_view.get_current_resource() == 'Test') self.driver.forward() WebDriverWait(self.driver, timeout=5).until(lambda driver: self.marketplace_view.get_subview() == 'search') self.driver.forward() - WebDriverWait(self.driver, timeout=5).until(lambda driver: self.marketplace_view.get_subview() == 'details') - self.assertEqual(self.marketplace_view.get_current_resource(), 'Test Mashup') + # get_current_resource also checks we are at the details subview + WebDriverWait(self.driver, timeout=5).until(lambda driver: self.marketplace_view.get_current_resource() == 'Test Mashup') self.driver.forward() WebDriverWait(self.driver, timeout=5).until(lambda driver: self.marketplace_view.get_subview() == 'search') diff --git a/src/wirecloud/platform/tests/selenium.py b/src/wirecloud/platform/tests/selenium.py index 1ed09bb304..5d78f88e9a 100644 --- a/src/wirecloud/platform/tests/selenium.py +++ b/src/wirecloud/platform/tests/selenium.py @@ -352,9 +352,7 @@ def test_widget_navigation_to_doc(self): self.driver.forward() WebDriverWait(self.driver, timeout=10).until(lambda driver: self.get_current_view() == 'myresources') - WebDriverWait(self.driver, timeout=5).until(lambda driver: self.myresources_view.get_subview() == 'details') - self.assertEqual(self.myresources_view.get_subview(), 'details') - self.assertEqual(self.myresources_view.get_current_resource(), 'Test') + WebDriverWait(self.driver, timeout=5).until(lambda driver: self.myresources_view.get_current_resource() == 'Test') def test_pending_wiring_events(self): From 0a87bbbc813c3c0950c6bb065d44e62d731f5468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Arranz?= Date: Mon, 17 Sep 2018 13:55:05 +0200 Subject: [PATCH 23/23] CI: Use jasmine clock mocks in the Command Queue Spec to avoid some random problems --- .../styledelements/CommandQueueSpec.js | 98 +++++++++++++------ 1 file changed, 69 insertions(+), 29 deletions(-) diff --git a/src/js_tests/styledelements/CommandQueueSpec.js b/src/js_tests/styledelements/CommandQueueSpec.js index 67c44ab2a8..1ada719e72 100644 --- a/src/js_tests/styledelements/CommandQueueSpec.js +++ b/src/js_tests/styledelements/CommandQueueSpec.js @@ -59,9 +59,11 @@ describe("addCommand(command)", function () { + const realSetTimeout = setTimeout; var queue, context, callback; beforeEach(function () { + jasmine.clock().install(); context = {context: true}; callback = jasmine.createSpy('callback').and.callFake(function (context, command) { if (command === "skip") { @@ -86,6 +88,10 @@ queue = new CommandQueue(context, callback); }); + afterEach(() => { + jasmine.clock().uninstall(); + }); + it("ignore calls without a command parameter", function (done) { var p = queue.addCommand(); @@ -124,42 +130,68 @@ expect(error).toEqual("reject"); done(); }); + jasmine.clock().tick(200); }); - it("supports adding commands to empty queues", function (done) { + it("supports adding commands to empty queues", (done) => { expect(queue.running).toBe(false); queue.addCommand(1); expect(queue.running).toBe(true); - setTimeout(function () { + jasmine.clock().tick(200); + jasmine.clock().uninstall(); + + setTimeout(() => { expect(queue.running).toBe(false); expect(callback.calls.count()).toBe(1); expect(callback.calls.argsFor(0)).toEqual([context, 1]); done(); - }, 200); + }, 0); }); - it("supports adding several commands", function (done) { - var listener = jasmine.createSpy(); + it("supports adding several commands", (done) => { + var listener1 = jasmine.createSpy(); + var listener2 = jasmine.createSpy(); + var listener3 = jasmine.createSpy(); expect(queue.running).toBe(false); - queue.addCommand(1); - queue.addCommand(2); - var p = queue.addCommand(3); + var p1 = queue.addCommand(1); + var p2 = queue.addCommand(2); + var p3 = queue.addCommand(3); - expect(p).toEqual(jasmine.any(Promise)); + expect(p1).toEqual(jasmine.any(Promise)); + expect(p2).toEqual(jasmine.any(Promise)); + expect(p3).toEqual(jasmine.any(Promise)); expect(queue.running).toBe(true); - p.then(listener); - - setTimeout(function () { - expect(queue.running).toBe(false); - expect(listener).toHaveBeenCalled(); - expect(callback.calls.count()).toBe(3); - expect(callback.calls.argsFor(0)).toEqual([context, 1]); - expect(callback.calls.argsFor(1)).toEqual([context, 2]); - expect(callback.calls.argsFor(2)).toEqual([context, 3]); - done(); - }, 620); + p1.then(listener1); + p2.then(listener2); + p3.then(listener3); + + // Use realSetTimeout to allow promise resolution + // Wait resolution of command 1 + jasmine.clock().tick(200); + realSetTimeout(() => { + expect(listener1).toHaveBeenCalled(); + expect(listener2).not.toHaveBeenCalled(); + jasmine.clock().tick(200); + // Wait resolution of command 2 + realSetTimeout(() => { + expect(listener2).toHaveBeenCalled(); + expect(listener3).not.toHaveBeenCalled(); + jasmine.clock().tick(200); + // Wait resolution of command 3 + realSetTimeout(() => { + expect(listener3).toHaveBeenCalled(); + + expect(queue.running).toBe(false); + expect(callback.calls.count()).toBe(3); + expect(callback.calls.argsFor(0)).toEqual([context, 1]); + expect(callback.calls.argsFor(1)).toEqual([context, 2]); + expect(callback.calls.argsFor(2)).toEqual([context, 3]); + done(); + }, 0); + }, 0); + }, 0); }); it("supports skiping a command", function (done) { @@ -175,15 +207,23 @@ p.then(listener); - setTimeout(function () { - expect(queue.running).toBe(false); - expect(listener).toHaveBeenCalled(); - expect(callback.calls.count()).toBe(3); - expect(callback.calls.argsFor(0)).toEqual([context, 1]); - expect(callback.calls.argsFor(1)).toEqual([context, "skip"]); - expect(callback.calls.argsFor(2)).toEqual([context, 3]); - done(); - }, 620); + // Use realSetTimeout to allow promise resolution + // Wait resolution of command 1 + jasmine.clock().tick(200); + realSetTimeout(() => { + // Command skip is immediately resolve + // Wait resolution of command 3 + jasmine.clock().tick(200); + realSetTimeout(() => { + expect(queue.running).toBe(false); + expect(listener).toHaveBeenCalled(); + expect(callback.calls.count()).toBe(3); + expect(callback.calls.argsFor(0)).toEqual([context, 1]); + expect(callback.calls.argsFor(1)).toEqual([context, "skip"]); + expect(callback.calls.argsFor(2)).toEqual([context, 3]); + done(); + }, 0); + }, 0); }); });