From b48667c9c7dc8ace219b4d88d3ec94876b511279 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Fri, 28 Jan 2022 10:39:50 +0100 Subject: [PATCH 01/11] allow parametrizing selenium using env vars --- Gruntfile.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index de98367a..eba59579 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -492,7 +492,12 @@ module.exports = function (grunt) { keepAlive: false, // If true, protractor will not use colors in its output noColor: false, - args: {} + args: ( + ( + process.env.PROTRACTOR_ARGS && + JSON.parse(process.env.PROTRACTOR_ARGS) + ) || {} + ) }, all: { options: { From 1772c14328e95aaa44fb17ef67dca67ef615f637 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Sun, 30 Jan 2022 16:53:15 +0100 Subject: [PATCH 02/11] working on the adminLogin helper page --- avAdmin/new-election-send-webspec.js | 5 +-- test/e2e.conf.js | 8 ++++- test/helpers.js | 47 ++++++++++++++++++++++++++-- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/avAdmin/new-election-send-webspec.js b/avAdmin/new-election-send-webspec.js index 71808632..ae090924 100644 --- a/avAdmin/new-election-send-webspec.js +++ b/avAdmin/new-election-send-webspec.js @@ -1,6 +1,6 @@ /** * This file is part of agora-gui-admin. - * Copyright (C) 2015-2016 Agora Voting SL + * Copyright (C) 2022 Sequent Tech Inc * agora-gui-admin is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -20,7 +20,8 @@ var helpers = require('../test/helpers'); /* jshint ignore:start */ describe("Admin Login tests", function() { beforeEach(async function () { - await browser.get('/admin/login/'); + var adminLogin = new helpers.adminLogin(); + await adminLogin.login(); }); it( diff --git a/test/e2e.conf.js b/test/e2e.conf.js index d2061c4f..bb3bc162 100644 --- a/test/e2e.conf.js +++ b/test/e2e.conf.js @@ -42,7 +42,13 @@ exports.config = { }, getPageTimeout: 30000, allScriptsTimeout: 20000, - onPrepare: function () { + + // Use native async/await + // More info: https://www.protractortest.org/#/async-await + SELENIUM_PROMISE_MANAGER: false, + + onPrepare: function () + { var SpecReporter = require('jasmine-spec-reporter').SpecReporter; jasmine .getEnv() diff --git a/test/helpers.js b/test/helpers.js index 0e70c5c4..4fab79ec 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -17,13 +17,54 @@ /* jshint ignore:start */ module.exports = { - getAvConfig: async function() { + /** + * @returns the Config object + */ + getAvConfig: async function() + { return await browser .executeAsyncScript( - function(callback) { + function(callback) + { callback(window.avConfigData); } ); + }, + + /** + * Assumes username + password is the admin authentication method. + */ + adminLogin: function () + { + var usernameEl = element(by.css('[av-login] form input#input1')); + var passwordEl = element( + by.css('[av-login] form input[type=\"password\"]') + ); + var submitEl = element(by.css('[av-login] form button[type=\"submit\"')); + + /** + * Gets the login page and logins the admin user. + */ + this.login = async function() + { + var EC = protractor.ExpectedConditions; + + // enter the login page and write username and password + await browser.get('/admin/login/'); + await usernameEl.sendKeys(browser.params.login.username); + await passwordEl.sendKeys(browser.params.login.password); + + // submit should be enabled -> then submit + expect(submitEl.getAttribute('disable')).toBeUndefined(); + await submitEl.click(); + + // wait for login to work + browser.wait( + EC.urlIs('/admin/elections'), + browser.params.timeout.ECstandards, + "Login didn't redirect to /admin/elections" + ); + }; } }; -/* jshint ignore:end */ \ No newline at end of file +/* jshint ignore:end */ From 0b79bb08b848f70768ff61b3e936074693a10059 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Mon, 31 Jan 2022 10:55:27 +0100 Subject: [PATCH 03/11] automate test for election creation --- avAdmin/new-election-send-webspec.js | 127 ---------------- test/create-election-page.js | 101 ++++++++++++ test/e2e.conf.js | 3 +- test/full-election-cycle-webspec.js | 219 +++++++++++++++++++++++++++ test/helpers.js | 10 +- 5 files changed, 330 insertions(+), 130 deletions(-) delete mode 100644 avAdmin/new-election-send-webspec.js create mode 100644 test/create-election-page.js create mode 100644 test/full-election-cycle-webspec.js diff --git a/avAdmin/new-election-send-webspec.js b/avAdmin/new-election-send-webspec.js deleted file mode 100644 index ae090924..00000000 --- a/avAdmin/new-election-send-webspec.js +++ /dev/null @@ -1,127 +0,0 @@ -/** - * This file is part of agora-gui-admin. - * Copyright (C) 2022 Sequent Tech Inc - - * agora-gui-admin 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. - - * agora-gui-admin 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 agora-gui-admin. If not, see . -**/ - -var helpers = require('../test/helpers'); - -/* jshint ignore:start */ -describe("Admin Login tests", function() { - beforeEach(async function () { - var adminLogin = new helpers.adminLogin(); - await adminLogin.login(); - }); - - it( - "Admin Login site should load with avConfig defined page title", - async function () { - var avConfig = await helpers.getAvConfig(); - expect(await browser.getTitle()) - .toEqual(avConfig.webTitle); - } - ); - - /* - it("should open form for add new question", function() { - var el = element(by.id('newq')); - expect(element(by.id('nq')).isDisplayed()).toBe(false); - el.click(); - expect(element(by.id('nq')).isDisplayed()).toBe(true); - }); - - it("should throw error: Enter a valid election title", function() { - expect(element(by.repeater('e in election.errors')).isPresent()).toBe(false); - element(by.css('.glyphicon-save')).click(); - expect(element(by.repeater('e in election.errors')).isPresent()).toBe(true); - var results = element.all(by.repeater('e in election.errors')); - expect(results.count()).toEqual(3); - expect(results.first().getText()).toEqual('Enter a valid election title'); - expect(results.get(0).getText()).toEqual('Enter a valid election title'); - }); - - it("should throw error: Enter a valid election description", function() { - expect(element(by.repeater('e in election.errors')).isPresent()).toBe(false); - var name = element(by.id('name')); - name.sendKeys("test"); - element(by.css('.glyphicon-save')).click(); - expect(element(by.repeater('e in election.errors')).isPresent()).toBe(true); - var results = element.all(by.repeater('e in election.errors')); - expect(results.first().getText()).toEqual('Enter a valid election description'); - }); - - it("should throw error: Add at least one question", function() { - expect(element(by.repeater('e in election.errors')).isPresent()).toBe(false); - var name = element(by.id('name')); - name.sendKeys("test"); - var desc = element(by.id('desc')); - desc.sendKeys("test description"); - element(by.css('.glyphicon-save')).click(); - expect(element(by.repeater('e in election.errors')).isPresent()).toBe(true); - var results = element.all(by.repeater('e in election.errors')); - expect(results.first().getText()).toEqual('Add at least one question'); - }); - - it("should throw error: Enter a valid question title", function() { - expect(element(by.repeater('e in newquestion.errors')).isPresent()).toBe(false); - element(by.id('newq')).click(); - element(by.id('saveq')).click(); - expect(element(by.repeater('e in newquestion.errors')).isPresent()).toBe(true); - var results = element.all(by.repeater('e in newquestion.errors')); - expect(results.first().getText()).toEqual('Enter a valid question title'); - }); - - it("should throw error: Add at least one option", function() { - expect(element(by.repeater('e in newquestion.errors')).isPresent()).toBe(false); - element(by.id('newq')).click(); - var qtext = element(by.id('qtext')); - qtext.sendKeys("test question"); - element(by.id('saveq')).click(); - expect(element(by.repeater('e in newquestion.errors')).isPresent()).toBe(true); - var results = element.all(by.repeater('e in newquestion.errors')); - expect(results.first().getText()).toEqual('Add at least one option'); - }); - - it("should add one option", function() { - element(by.id('newq')).click(); - var qtext = element(by.id('qtext')); - qtext.sendKeys("test question"); - element(by.id('newopt')).click(); - element(by.id('saveq')).click(); - expect(element(by.repeater('e in newquestion.errors')).isPresent()).toBe(false); - expect(element(by.repeater('q in questions')).isPresent()).toBe(true); - var results = element.all(by.repeater('q in questions')); - expect(results.count()).toEqual(1); - }); - - it("should create a new election", function() { - var name = element(by.id('name')); - name.sendKeys("test"); - var desc = element(by.id('desc')); - desc.sendKeys("test description"); - - element(by.id('newq')).click(); - var qtext = element(by.id('qtext')); - qtext.sendKeys("test question"); - element(by.id('newopt')).click(); - element(by.id('saveq')).click(); - - element(by.css('.glyphicon-save')).click(); - expect(element(by.repeater('e in election.errors')).isPresent()).toBe(false); - }); - */ - -}); -/* jshint ignore:end */ - diff --git a/test/create-election-page.js b/test/create-election-page.js new file mode 100644 index 00000000..8367f6a7 --- /dev/null +++ b/test/create-election-page.js @@ -0,0 +1,101 @@ +/** + * This file is part of agora-gui-admin. + * Copyright (C) 2022 Sequent Tech Inc + + * agora-gui-admin 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. + + * agora-gui-admin 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 agora-gui-admin. If not, see . +**/ + +const { Button } = require("bootstrap"); + +/* jshint ignore:start */ +var CreateElectionPage = function () +{ + /** + * Creates an election using the Edit JSON button. + * @param {*} electionData Data of the election(s) to be created. + * @returns {Number} Id of the (parent) created election + * + * Requirements: Requires Admin to be logged in, you can use helpers.login() + * for that. + */ + this.createElectionEditJson = async function (electionData) + { + // go to create the election + await browser.get('/admin/new/'); + browser.wait( + EC.urlIs('/admin/basic/'), + browser.params.timeout.ECstandards, + "/admin/new/ didn't redirect to /admin/basic/ as expected" + ); + + // go to the last create-election step + var createEl = element( + by.css('[av-admin-sidebar] [href="/admin/create/"]') + ); + expect(createEl.isPresent()).toBe(true); + await createEl.click(); + + // click on edit json to change it to our test-election json + var editJsonEl = element( + by.css('[av-admin-create] .fa-pencil') + ); + expect(editJsonEl.isPresent()).toBe(true); + await editJsonEl.click(); + + // change textarea with election json + var electionJsonEl = element(by.model('electionJson.model')); + expect(electionJsonEl.isPresent()).toBe(true); + await electionJsonEl.clear().sendKeys(electionData); + + // save the new json + var saveEl = element( + by.css('[modal-window] .modal-footer button.btn-success') + ); + expect(saveEl.isPresent()).toBe(true); + await saveEl.click(); + + // Expect no errors in the json + var errorsEls = element.all(by.repeater('error in errors')); + expect(errorsEls.count()).toEqual(0); + + // Procceed to create the election + var createButtonEl = element( + by.css('[av-admin-create] .form-group Button.btn.btn-block.btn-success') + ); + expect(createButtonEl.isPresent()).toBe(true); + expect(createButtonEl.getAttribute('disabled')).toBe(null); + await createButtonEl.click(); + + // Wait for either an error to appear or the redirect to the created + // election dashboard page to happen + var dashboardUrl = EC.urlContains('/admin/dashboard/'); + var creationError = electionCreationErrorEl( + element( + by.css('[av-admin-create] [av-scroll-to-bottom] p.text-brand-danger') + ) + ); + browser.wait( + EC.or(dashboardUrl, creationError), + browser.params.timeout.CreateElections, + "Election creation timedout with no visible error" + ); + var currentUrl = await browser.getCurrentUrl(); + expect(currentUrl) + .toContain('/admin/dashboard/', 'Election creation error'); + + var splitUrl = currentUrl.split('/admin/dashboard/'); + return Number.parseInt(splitUrl[splitUrl.length - 1]); + }; +}; +module.exports = new CreateElectionPage(); +/* jshint ignore:end */ diff --git a/test/e2e.conf.js b/test/e2e.conf.js index bb3bc162..d878f347 100644 --- a/test/e2e.conf.js +++ b/test/e2e.conf.js @@ -32,7 +32,8 @@ exports.config = { acceptInsecureCerts : true }, specs: [ - '../avAdmin/**/*-webspec.js' + '../avAdmin/**/*-webspec.js', + './**/*-webspec.js' ], jasmineNodeOpts: { // remove ugly protractor dot reporter diff --git a/test/full-election-cycle-webspec.js b/test/full-election-cycle-webspec.js new file mode 100644 index 00000000..a36bee8a --- /dev/null +++ b/test/full-election-cycle-webspec.js @@ -0,0 +1,219 @@ +/** + * This file is part of agora-gui-admin. + * Copyright (C) 2022 Sequent Tech Inc + + * agora-gui-admin 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. + + * agora-gui-admin 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 agora-gui-admin. If not, see . +**/ + +/* jshint ignore:start */ +describe( + "Admin Full Election Cycle Tests", + function() + { + var helpers = require('./helpers'); + var CreateElectionPage = require('./create-election-page.js'); + var adminLogin = null; + var simpleElection = [ + { + "title": "E2E test election", + "description": "This is the description of the election. You can add simple html like bold or links to websites.\n\n

You need to use two br element for new paragraphs.", + "authorities": [ + "dev-a2" + ], + "director": "dev-a1", + "presentation": { + "theme": "default", + "share_text": [ + { + "network": "Twitter", + "button_text": "", + "social_message": "I have just voted in election __URL__, you can too! #nvotes", + "active": true + } + ], + "urls": [], + "allow_tally": true, + "theme_css": "" + }, + "layout": "simple", + "num_successful_logins_allowed": 0, + "resultsConfig": { + "version": "master", + "pipes": [ + { + "type": "agora_results.pipes.results.do_tallies", + "params": {} + }, + { + "type": "agora_results.pipes.sort.sort_non_iterative", + "params": {} + } + ] + }, + "census": { + "has_ballot_boxes": false, + "voters": [], + "auth_method": "email", + "census": "close", + "extra_fields": [ + { + "name": "email", + "type": "email", + "required": true, + "unique": true, + "min": 4, + "max": 255, + "required_on_authentication": true, + "must": true + } + ], + "admin_fields": [], + "config": { + "allow_user_resend": false, + "msg": "Vote in __URL__ with code __CODE__", + "subject": "Vote now with nVotes", + "authentication-action": { + "mode": "vote", + "mode-config": { + "url": "" + } + }, + "registration-action": { + "mode": "vote", + "mode-config": null + } + } + }, + "questions": [ + { + "answer_total_votes_percentage": "over-total-valid-votes", + "answers": [ + { + "category": "", + "details": "This is an option with an simple example description.", + "id": 0, + "sort_order": 0, + "text": "Example option 1", + "urls": [ + { + "title": "URL", + "url": "" + }, + { + "title": "Image URL", + "url": "" + } + ] + }, + { + "category": "", + "details": "An option can contain a description. You can add simple html like bold or links to websites. You can also set an image url below, but be sure it's HTTPS or else it won't load.\n\n

You need to use two br element for new paragraphs.", + "id": 1, + "sort_order": 1, + "text": "Example option 2", + "urls": [ + { + "title": "URL", + "url": "https://sequentech.io" + }, + { + "title": "Image URL", + "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/df/The_Fabs.JPG/220px-The_Fabs.JPG" + } + ] + }, + { + "category": "", + "details": "", + "id": 2, + "sort_order": 2, + "text": "Example option 3", + "urls": [ + { + "title": "URL", + "url": "" + }, + { + "title": "Image URL", + "url": "" + } + ] + } + ], + "description": "This is the description of this question. You can have multiple questions. You can add simple html like bold or links to websites.\n\n

You need to use two br element for new paragraphs.", + "layout": "accordion", + "max": 1, + "min": 1, + "num_winners": 1, + "tally_type": "plurality-at-large", + "title": "Test question title", + "extra_options": { + "shuffle_categories": true, + "shuffle_all_options": true, + "shuffle_category_list": [], + "show_points": false + }, + "active": true + } + ], + "extra_data": {} + } + ]; + + /** + * Updates the elections config with the details of current deployment + * configuration: + * - election authorities + * - results config version + * @returns the updated elections + */ + function updateElectionConfig(elections, avConfig) + { + var updatedElections = angular.copy(elections); + _.each( + updatedElections, + function (election) + { + election.director = avConfig.director; + election.authorities = angular.copy(avConfig.authorities); + election.resultsConfig.version = avConfig.mainVersion; + } + ); + return updatedElections; + } + + /** + * Setup the tests by logging in as an admin user. + */ + beforeEach( + async function () + { + adminLogin = new helpers.adminLogin(); + await adminLogin.login(); + } + ); + + it( + "Admin Full Election cycle", + async function () + { + var avConfig = await helpers.getAvConfig(); + var electionConfig = updateElectionConfig(simpleElection, avConfig); + + // create the election + CreateElectionPage.createElectionEditJson(electionConfig); + } + ); +}); +/* jshint ignore:end */ + diff --git a/test/helpers.js b/test/helpers.js index 4fab79ec..18674666 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -41,6 +41,7 @@ module.exports = { by.css('[av-login] form input[type=\"password\"]') ); var submitEl = element(by.css('[av-login] form button[type=\"submit\"')); + var adminUserEl = element(by.css('[av-admin-head] .profile-dropdown')); /** * Gets the login page and logins the admin user. @@ -55,15 +56,20 @@ module.exports = { await passwordEl.sendKeys(browser.params.login.password); // submit should be enabled -> then submit - expect(submitEl.getAttribute('disable')).toBeUndefined(); + expect(submitEl.getAttribute('disable')).toBeNull(); await submitEl.click(); - // wait for login to work + // wait for login to work and redirect to /admin/elections browser.wait( EC.urlIs('/admin/elections'), browser.params.timeout.ECstandards, "Login didn't redirect to /admin/elections" ); + + // check that it's logged in with the correct username shown in the top + // navbar + expect(await adminUserEl.getText()) + .toContain(browser.params.login.username); }; } }; From fdba261cc99ef4bbfa9a298b75878d1e2daf2956 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Mon, 31 Jan 2022 10:59:07 +0100 Subject: [PATCH 04/11] fix build --- test/create-election-page.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/create-election-page.js b/test/create-election-page.js index 8367f6a7..20ca538f 100644 --- a/test/create-election-page.js +++ b/test/create-election-page.js @@ -15,8 +15,6 @@ * along with agora-gui-admin. If not, see . **/ -const { Button } = require("bootstrap"); - /* jshint ignore:start */ var CreateElectionPage = function () { @@ -70,7 +68,7 @@ var CreateElectionPage = function () // Procceed to create the election var createButtonEl = element( - by.css('[av-admin-create] .form-group Button.btn.btn-block.btn-success') + by.css('[av-admin-create] .form-group button.btn.btn-block.btn-success') ); expect(createButtonEl.isPresent()).toBe(true); expect(createButtonEl.getAttribute('disabled')).toBe(null); From b0c712db1aed1f836d5ab9176ece6a21ce961afe Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Mon, 31 Jan 2022 11:09:10 +0100 Subject: [PATCH 05/11] adding some doc and removing use of angular.copy in tests --- test/create-election-page.js | 6 +++++- test/full-election-cycle-webspec.js | 8 +++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/test/create-election-page.js b/test/create-election-page.js index 20ca538f..53b29d69 100644 --- a/test/create-election-page.js +++ b/test/create-election-page.js @@ -54,7 +54,7 @@ var CreateElectionPage = function () var electionJsonEl = element(by.model('electionJson.model')); expect(electionJsonEl.isPresent()).toBe(true); await electionJsonEl.clear().sendKeys(electionData); - + // save the new json var saveEl = element( by.css('[modal-window] .modal-footer button.btn-success') @@ -87,10 +87,14 @@ var CreateElectionPage = function () browser.params.timeout.CreateElections, "Election creation timedout with no visible error" ); + + // We reached here because either we were redirected to the dashboard or + // there was an election creation error. Check that it's the first case. var currentUrl = await browser.getCurrentUrl(); expect(currentUrl) .toContain('/admin/dashboard/', 'Election creation error'); + // Success! Return the current election id var splitUrl = currentUrl.split('/admin/dashboard/'); return Number.parseInt(splitUrl[splitUrl.length - 1]); }; diff --git a/test/full-election-cycle-webspec.js b/test/full-election-cycle-webspec.js index a36bee8a..45f058ed 100644 --- a/test/full-election-cycle-webspec.js +++ b/test/full-election-cycle-webspec.js @@ -175,17 +175,15 @@ describe( * configuration: * - election authorities * - results config version - * @returns the updated elections */ function updateElectionConfig(elections, avConfig) { - var updatedElections = angular.copy(elections); _.each( - updatedElections, + elections, function (election) { election.director = avConfig.director; - election.authorities = angular.copy(avConfig.authorities); + election.authorities = avConfig.authorities; election.resultsConfig.version = avConfig.mainVersion; } ); @@ -208,7 +206,7 @@ describe( async function () { var avConfig = await helpers.getAvConfig(); - var electionConfig = updateElectionConfig(simpleElection, avConfig); + updateElectionConfig(simpleElection, avConfig); // create the election CreateElectionPage.createElectionEditJson(electionConfig); From 89af7abed2aa50dacc8d98b840509c65b12c482b Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Mon, 31 Jan 2022 11:11:14 +0100 Subject: [PATCH 06/11] removing usage of underscore --- test/full-election-cycle-webspec.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/test/full-election-cycle-webspec.js b/test/full-election-cycle-webspec.js index 45f058ed..f4c5431d 100644 --- a/test/full-election-cycle-webspec.js +++ b/test/full-election-cycle-webspec.js @@ -178,16 +178,13 @@ describe( */ function updateElectionConfig(elections, avConfig) { - _.each( - elections, - function (election) - { - election.director = avConfig.director; - election.authorities = avConfig.authorities; - election.resultsConfig.version = avConfig.mainVersion; - } - ); - return updatedElections; + for (var i = 0; i < elections.length; i++) + { + var election = elections[i]; + election.director = avConfig.director; + election.authorities = avConfig.authorities; + election.resultsConfig.version = avConfig.mainVersion; + } } /** From bccd201a59fbbb7e1ec0cdd6a859f7c60c211fd1 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Mon, 31 Jan 2022 11:11:48 +0100 Subject: [PATCH 07/11] fixing var ref --- test/full-election-cycle-webspec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/full-election-cycle-webspec.js b/test/full-election-cycle-webspec.js index f4c5431d..27fc10eb 100644 --- a/test/full-election-cycle-webspec.js +++ b/test/full-election-cycle-webspec.js @@ -206,7 +206,7 @@ describe( updateElectionConfig(simpleElection, avConfig); // create the election - CreateElectionPage.createElectionEditJson(electionConfig); + CreateElectionPage.createElectionEditJson(simpleElection); } ); }); From ad9153c31f06820ba8aecbaf0d78388a0504aa03 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Mon, 31 Jan 2022 11:13:07 +0100 Subject: [PATCH 08/11] await missing --- test/full-election-cycle-webspec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/full-election-cycle-webspec.js b/test/full-election-cycle-webspec.js index 27fc10eb..ab204be4 100644 --- a/test/full-election-cycle-webspec.js +++ b/test/full-election-cycle-webspec.js @@ -206,7 +206,7 @@ describe( updateElectionConfig(simpleElection, avConfig); // create the election - CreateElectionPage.createElectionEditJson(simpleElection); + await CreateElectionPage.createElectionEditJson(simpleElection); } ); }); From 94a5403c93b814e1b5c7d06b07ef5c6c8b4cf251 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Mon, 31 Jan 2022 17:41:18 +0100 Subject: [PATCH 09/11] improving colors of view-task-logs --- avAdmin/admin-directives/tasks/view-task-logs-modal.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/avAdmin/admin-directives/tasks/view-task-logs-modal.less b/avAdmin/admin-directives/tasks/view-task-logs-modal.less index 7877e42c..c6e1c30f 100644 --- a/avAdmin/admin-directives/tasks/view-task-logs-modal.less +++ b/avAdmin/admin-directives/tasks/view-task-logs-modal.less @@ -70,7 +70,7 @@ } .ansi-red-fg { - color: #DD948E; + color: #f00b0b; } .ansi-green-fg { @@ -134,7 +134,7 @@ } .ansi-red-bg { - background-color: #DD948E; + background-color: #f00b0b; } .ansi-green-bg { From 5714b5fb921ac1ee7aea939650d4c45399537c64 Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Mon, 31 Jan 2022 17:41:42 +0100 Subject: [PATCH 10/11] adding more debug info to create-election-page --- test/create-election-page.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/test/create-election-page.js b/test/create-election-page.js index 53b29d69..518301e7 100644 --- a/test/create-election-page.js +++ b/test/create-election-page.js @@ -28,7 +28,10 @@ var CreateElectionPage = function () */ this.createElectionEditJson = async function (electionData) { + var EC = protractor.ExpectedConditions; + // go to create the election + console.log("entering /admin/new/"); await browser.get('/admin/new/'); browser.wait( EC.urlIs('/admin/basic/'), @@ -41,18 +44,27 @@ var CreateElectionPage = function () by.css('[av-admin-sidebar] [href="/admin/create/"]') ); expect(createEl.isPresent()).toBe(true); + console.log("clicking /admin/create/"); await createEl.click(); + browser.wait( + EC.urlIs('/admin/create/'), + browser.params.timeout.ECstandards, + "/admin/basic/ didn't redirect to /admin/create/ as expected" + ); + console.log("entered /admin/create/"); // click on edit json to change it to our test-election json var editJsonEl = element( by.css('[av-admin-create] .fa-pencil') ); expect(editJsonEl.isPresent()).toBe(true); + console.log("entering edit json modal"); await editJsonEl.click(); // change textarea with election json var electionJsonEl = element(by.model('electionJson.model')); expect(electionJsonEl.isPresent()).toBe(true); + console.log("editing json election"); await electionJsonEl.clear().sendKeys(electionData); // save the new json @@ -60,6 +72,7 @@ var CreateElectionPage = function () by.css('[modal-window] .modal-footer button.btn-success') ); expect(saveEl.isPresent()).toBe(true); + console.log("saving election json election"); await saveEl.click(); // Expect no errors in the json @@ -72,6 +85,7 @@ var CreateElectionPage = function () ); expect(createButtonEl.isPresent()).toBe(true); expect(createButtonEl.getAttribute('disabled')).toBe(null); + console.log("clicking create election button"); await createButtonEl.click(); // Wait for either an error to appear or the redirect to the created @@ -82,6 +96,7 @@ var CreateElectionPage = function () by.css('[av-admin-create] [av-scroll-to-bottom] p.text-brand-danger') ) ); + console.log("waiting for election to be created and redirect to dashboard"); browser.wait( EC.or(dashboardUrl, creationError), browser.params.timeout.CreateElections, @@ -95,8 +110,12 @@ var CreateElectionPage = function () .toContain('/admin/dashboard/', 'Election creation error'); // Success! Return the current election id + console.log("waiting for election to be created and redirect to dashboard"); var splitUrl = currentUrl.split('/admin/dashboard/'); - return Number.parseInt(splitUrl[splitUrl.length - 1]); + var electionId = Number.parseInt(splitUrl[splitUrl.length - 1]); + console.log("returning election id = " + electionId); + + return electionId; }; }; module.exports = new CreateElectionPage(); From 3ef816cb4a7fd5dd737ae643b097056fdf045a2c Mon Sep 17 00:00:00 2001 From: Eduardo Robles Elvira Date: Tue, 1 Feb 2022 14:31:29 +0100 Subject: [PATCH 11/11] using interval instead of timeout to try to fix protractor tests --- avAdmin/admin-controller/admin-controller.js | 4 ++-- .../admin-directives/activity-log/activity-log.js | 6 +++--- avAdmin/admin-directives/ballot-box/ballot-box.js | 6 +++--- .../dashboard/send-auth-codes-modal-confirm.js | 4 ++-- avAdmin/admin-directives/elcensus/elcensus.js | 6 +++--- avAdmin/admin-directives/elections/elections.js | 10 ++++++++-- .../admin-directives/tasks/view-task-logs-modal.js | 12 ++++++------ avAdmin/csv-load-service.js | 6 +++--- avAdmin/draft-election.js | 8 ++++---- 9 files changed, 34 insertions(+), 28 deletions(-) diff --git a/avAdmin/admin-controller/admin-controller.js b/avAdmin/admin-controller/admin-controller.js index 6a90515c..68703a2c 100644 --- a/avAdmin/admin-controller/admin-controller.js +++ b/avAdmin/admin-controller/admin-controller.js @@ -29,7 +29,7 @@ angular $scope, $state, $stateParams, - $timeout, + $interval, $q, $window, $modal @@ -336,7 +336,7 @@ angular $scope.has_draft = false; function updateDraft(el) { - $timeout(function () { + $interval(function () { $scope.draft = el; $scope.has_draft = ("{}" !== JSON.stringify(el)); }); diff --git a/avAdmin/admin-directives/activity-log/activity-log.js b/avAdmin/admin-directives/activity-log/activity-log.js index d16acef6..637604f9 100644 --- a/avAdmin/admin-directives/activity-log/activity-log.js +++ b/avAdmin/admin-directives/activity-log/activity-log.js @@ -23,7 +23,7 @@ angular.module('avAdmin') ElectionsApi, ConfigService, NextButtonService, - $timeout, + $interval, $stateParams ) { // we use it as something similar to a controller here @@ -108,8 +108,8 @@ angular.module('avAdmin') // debounced reloading function reloadActivityDebounce() { - $timeout.cancel(scope.filterTimeout); - scope.filterTimeout = $timeout(function() { + $interval.cancel(scope.filterTimeout); + scope.filterTimeout = $interval(function() { scope.reloadActivity(); }, 500); } diff --git a/avAdmin/admin-directives/ballot-box/ballot-box.js b/avAdmin/admin-directives/ballot-box/ballot-box.js index d2170520..6679291f 100644 --- a/avAdmin/admin-directives/ballot-box/ballot-box.js +++ b/avAdmin/admin-directives/ballot-box/ballot-box.js @@ -22,7 +22,7 @@ angular.module('avAdmin') Authmethod, ConfigService, NextButtonService, - $timeout, + $interval, $i18next, $modal, $location, @@ -105,8 +105,8 @@ angular.module('avAdmin') // debounced reloading function reloadDebounce() { - $timeout.cancel(scope.filterTimeout); - scope.filterTimeout = $timeout(function() { + $interval.cancel(scope.filterTimeout); + scope.filterTimeout = $interval(function() { scope.reload(); }, 500); } diff --git a/avAdmin/admin-directives/dashboard/send-auth-codes-modal-confirm.js b/avAdmin/admin-directives/dashboard/send-auth-codes-modal-confirm.js index 8e22586f..90c3d333 100644 --- a/avAdmin/admin-directives/dashboard/send-auth-codes-modal-confirm.js +++ b/avAdmin/admin-directives/dashboard/send-auth-codes-modal-confirm.js @@ -23,7 +23,7 @@ angular.module('avAdmin') function( ConfigService, $location, - $timeout, + $interval, $scope, $modalInstance, $i18next, @@ -192,7 +192,7 @@ angular.module('avAdmin') }); // use a click to an element with a specific class to close the dialog - $timeout(function() { + $interval(function() { $(".av-plugin-modal-close").click(function() { var data = $(this).data("response"); diff --git a/avAdmin/admin-directives/elcensus/elcensus.js b/avAdmin/admin-directives/elcensus/elcensus.js index a685deee..afaeab93 100644 --- a/avAdmin/admin-directives/elcensus/elcensus.js +++ b/avAdmin/admin-directives/elcensus/elcensus.js @@ -33,7 +33,7 @@ angular.module('avAdmin') $filter, $stateParams, $state, - $timeout, + $interval, ConfigService, CsvLoad, NextButtonService) @@ -1116,8 +1116,8 @@ angular.module('avAdmin') } function reloadCensusDebounce() { - $timeout.cancel(scope.filterTimeout); - scope.filterTimeout = $timeout(function() { + $interval.cancel(scope.filterTimeout); + scope.filterTimeout = $interval(function() { scope.reloadCensus(); }, 500); } diff --git a/avAdmin/admin-directives/elections/elections.js b/avAdmin/admin-directives/elections/elections.js index dfb68f35..3999000c 100644 --- a/avAdmin/admin-directives/elections/elections.js +++ b/avAdmin/admin-directives/elections/elections.js @@ -18,8 +18,14 @@ angular.module('avAdmin') .directive( 'avAdminElections', - function(Authmethod, ElectionsApi, DraftElection, AdminProfile, OnboardingTourService, $state, Plugins, $modal, $timeout, $window) - { + function( + Authmethod, + ElectionsApi, + AdminProfile, + OnboardingTourService, + Plugins, + $window + ) { // we use it as something similar to a controller here function link(scope, element, attrs) { scope.page = 1; diff --git a/avAdmin/admin-directives/tasks/view-task-logs-modal.js b/avAdmin/admin-directives/tasks/view-task-logs-modal.js index 299fea1b..a2801004 100644 --- a/avAdmin/admin-directives/tasks/view-task-logs-modal.js +++ b/avAdmin/admin-directives/tasks/view-task-logs-modal.js @@ -22,7 +22,7 @@ angular function( $scope, $modalInstance, - $timeout, + $interval, Authmethod, AnsiUpService, task @@ -73,10 +73,10 @@ angular task.status )) { if ($scope.taskUpdateTimeout) { - $timeout.cancel($scope.taskUpdateTimeout); + $interval.cancel($scope.taskUpdateTimeout); } } else { - $scope.taskUpdateTimeout = $timeout( + $scope.taskUpdateTimeout = $interval( function () { $scope.taskUpdateFunc(); @@ -86,7 +86,7 @@ angular $scope.updateTask(); } }; - $scope.taskUpdateTimeout = $timeout( + $scope.taskUpdateTimeout = $interval( function () { $scope.taskUpdateFunc(); @@ -103,7 +103,7 @@ angular { return; } - $timeout( + $interval( function () { $('.modal-body.view-task-logs-modal .console .end-marker')[0] @@ -204,7 +204,7 @@ angular $scope.updateLogs(); // scroll into the bottom of the modal on start - $timeout( + $interval( function () { $('.modal-body.view-task-logs-modal .autoscroll-span')[0] diff --git a/avAdmin/csv-load-service.js b/avAdmin/csv-load-service.js index b6408d7e..d2004088 100644 --- a/avAdmin/csv-load-service.js +++ b/avAdmin/csv-load-service.js @@ -20,7 +20,7 @@ angular.module('avAdmin') 'CsvLoad', function ( $q, - $timeout, + $interval, ConfigService, Plugins, Authmethod) @@ -190,7 +190,7 @@ angular.module('avAdmin') if (_.isFunction(csvLoadService.scope.processBatchPlugin)) { csvLoadService.scope.processBatchPlugin(processed) .then(function (ret) { - $timeout(function () { + $interval(function () { csvLoadService.scope.percent = ret.percent; csvLoadService.scope.exportListIndex = ret.exportListIndex; @@ -205,7 +205,7 @@ angular.module('avAdmin') }); }); } else { - $timeout(function () { + $interval(function () { csvLoadService.scope.percent = processed.percent; csvLoadService.scope.exportListIndex = processed.exportListIndex; diff --git a/avAdmin/draft-election.js b/avAdmin/draft-election.js index c5e5db17..a7dd4c2d 100644 --- a/avAdmin/draft-election.js +++ b/avAdmin/draft-election.js @@ -26,7 +26,7 @@ angular.module('avAdmin') ElectionsApi, $i18next, $http, - $timeout, + $interval, $modal, $state, $stateParams, @@ -85,7 +85,7 @@ angular.module('avAdmin') if (!draft_election.isEditingDraft()) { election = undefined; if (!_.isUndefined(promise)) { - $timeout.cancel(promise); + $interval.cancel(promise); } return; } @@ -104,14 +104,14 @@ angular.module('avAdmin') console.log("error uploading draft: " + response.data); } ); - promise = $timeout(draft_election.updateDraft, 60000); + promise = $interval(draft_election.updateDraft, 60000); }; draft_election.eraseDraft = function () { var deferred = $q.defer(); election = undefined; if (!_.isUndefined(promise)) { - $timeout.cancel(promise); + $interval.cancel(promise); } Authmethod .uploadUserDraft({})