From 0bd2a72f6a2c49cc0b3eca8edf18286d025b1992 Mon Sep 17 00:00:00 2001 From: Roman Konovalov Date: Thu, 19 Mar 2015 11:51:14 +0300 Subject: [PATCH 01/10] Add DBPopulatorController --- .../eighty/service/DBPopulatorService.java | 2 + .../service/impl/DBPopulatorServiceImpl.java | 16 +++++++- .../eighty/web/api/DBPopulatorController.java | 39 +++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/epam/eighty/web/api/DBPopulatorController.java diff --git a/src/main/java/com/epam/eighty/service/DBPopulatorService.java b/src/main/java/com/epam/eighty/service/DBPopulatorService.java index a05501f..81d5830 100644 --- a/src/main/java/com/epam/eighty/service/DBPopulatorService.java +++ b/src/main/java/com/epam/eighty/service/DBPopulatorService.java @@ -5,4 +5,6 @@ public interface DBPopulatorService { void populate() throws IOException; + + void clean() throws IOException; } diff --git a/src/main/java/com/epam/eighty/service/impl/DBPopulatorServiceImpl.java b/src/main/java/com/epam/eighty/service/impl/DBPopulatorServiceImpl.java index e9bc224..9288d5d 100644 --- a/src/main/java/com/epam/eighty/service/impl/DBPopulatorServiceImpl.java +++ b/src/main/java/com/epam/eighty/service/impl/DBPopulatorServiceImpl.java @@ -1,12 +1,13 @@ package com.epam.eighty.service.impl; -import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.neo4j.cypher.javacompat.ExecutionEngine; import org.neo4j.graphdb.GraphDatabaseService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; import com.epam.eighty.service.DBPopulatorService; @@ -16,13 +17,24 @@ public class DBPopulatorServiceImpl implements DBPopulatorService { @Autowired private GraphDatabaseService graphDatabaseService; + + @Value("classpath:scripts/data.cypher") + private Resource createScriptResource; + + private static final String DELETE_SCRIPT = "START n=node(*) OPTIONAL MATCH (n)-[r]-() delete n,r;"; @Override public void populate() throws IOException { - String cypherScript = FileUtils.readFileToString(new File(getClass().getClassLoader().getResource("scripts/data.cypher").getFile())); + String cypherScript = FileUtils.readFileToString(createScriptResource.getFile()); ExecutionEngine engine = new ExecutionEngine(graphDatabaseService); engine.execute(cypherScript); } + @Override + public void clean() throws IOException { + ExecutionEngine engine = new ExecutionEngine(graphDatabaseService); + engine.execute(DELETE_SCRIPT); + } + } diff --git a/src/main/java/com/epam/eighty/web/api/DBPopulatorController.java b/src/main/java/com/epam/eighty/web/api/DBPopulatorController.java new file mode 100644 index 0000000..87666e1 --- /dev/null +++ b/src/main/java/com/epam/eighty/web/api/DBPopulatorController.java @@ -0,0 +1,39 @@ +package com.epam.eighty.web.api; + +import java.io.IOException; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import com.codahale.metrics.annotation.Timed; +import com.epam.eighty.service.DBPopulatorService; +import com.wordnik.swagger.annotations.Api; +import com.wordnik.swagger.annotations.ApiOperation; +import com.wordnik.swagger.annotations.ApiResponse; +import com.wordnik.swagger.annotations.ApiResponses; + +@Api(value = "/db", description = "All operations for database population") +@Controller +@RequestMapping("/db") +@Profile({"dev", "test"}) +public class DBPopulatorController { + + @Autowired + private DBPopulatorService dbPopulatorService; + + @ApiOperation(value = "Reload database", notes = "Reload database", httpMethod = "GET") + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 400, message = "Invalid ID") }) + @Timed + @RequestMapping(value = "/reload", method = RequestMethod.GET) + public void reloadDataBase(final HttpServletResponse response) throws IOException { + dbPopulatorService.clean(); + dbPopulatorService.populate(); + response.setStatus(HttpServletResponse.SC_OK); + } + +} From 2934caaf02acae72061bb69c09903592fb4461f5 Mon Sep 17 00:00:00 2001 From: Roman Konovalov Date: Thu, 19 Mar 2015 12:03:04 +0300 Subject: [PATCH 02/10] Add start embedded tomcat server task --- pom.xml | 42 +++++++++++++------ .../eighty/web/api/DBPopulatorController.java | 2 +- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index d63cac6..14889c4 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ target/lcov.info src/main/webapp/js/min/**/* target/site/cobertura/coverage.xml - 8282 + 8282 @@ -239,15 +239,6 @@ ${basedir}/src/main/webapp/WEB-INF/web.xml - - org.apache.tomcat.maven - tomcat7-maven-plugin - 2.2 - - tomcat - http://localhost:8080/manager/text - - org.codehaus.mojo exec-maven-plugin @@ -357,6 +348,16 @@ + + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.2 + + localhost + ${tomcat.port} + /eighty + + @@ -429,7 +430,7 @@ integration-test --no-color - p:test --p:port=${protractor.port} + p:test --p:port=${tomcat.port} @@ -444,7 +445,24 @@ - + + org.apache.tomcat.maven + tomcat7-maven-plugin + + /eightytest + true + + + + tomcat-run-war-only + pre-integration-test + + run-war-only + + + + + org.apache.maven.plugins maven-checkstyle-plugin ${maven.checkstyle.plugin} diff --git a/src/main/java/com/epam/eighty/web/api/DBPopulatorController.java b/src/main/java/com/epam/eighty/web/api/DBPopulatorController.java index 87666e1..c95fe08 100644 --- a/src/main/java/com/epam/eighty/web/api/DBPopulatorController.java +++ b/src/main/java/com/epam/eighty/web/api/DBPopulatorController.java @@ -27,7 +27,7 @@ public class DBPopulatorController { private DBPopulatorService dbPopulatorService; @ApiOperation(value = "Reload database", notes = "Reload database", httpMethod = "GET") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 400, message = "Invalid ID") }) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Request processing failed") }) @Timed @RequestMapping(value = "/reload", method = RequestMethod.GET) public void reloadDataBase(final HttpServletResponse response) throws IOException { From f1b55d2934d9b6b6c8fcd5a11bc06cdb44324d04 Mon Sep 17 00:00:00 2001 From: Roman Konovalov Date: Thu, 19 Mar 2015 12:10:19 +0300 Subject: [PATCH 03/10] Remove grunt connect task --- Gruntfile.js | 58 +++------------------------------------------------- package.json | 1 - 2 files changed, 3 insertions(+), 56 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index a91e0c6..bc03bd9 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,42 +1,8 @@ 'use strict'; -var mountFolder = function (connect, dir) { - return connect.static(require('path').resolve(dir)); -}; - -var fillTopics = function (data) { - if (data.topics) { - data.topics.forEach(function (entry) { - entry.id = entry.id || 9999; - entry.topics = entry.topics || []; - entry.questions = entry.questions || []; - }); - } -}; - -var restMiddleware = function (req, res, next) { - if (req.method === 'PUT') { - var body = {}; - req.on('data', function (chunk) { - body = JSON.parse(chunk.toString()); - fillTopics(body); - }); - req.on('end', function () { - res.writeHead(200, 'OK', {'Content-Type': 'application/json'}); - res.end(JSON.stringify(body)); - }); - } else if (req.method === 'DELETE') { - res.writeHead(200, 'OK'); - res.end(); - } else { - return next(); - } - -}; - module.exports = function (grunt) { - var protractorBrowserPort = grunt.option('p:port') || '8282'; + var tomcatPort = grunt.option('p:port') || '8282'; grunt.initConfig({ @@ -101,23 +67,6 @@ module.exports = function (grunt) { singleRun: true } }, - connect: { - livereload: { - options: { - //keepalive: true, - port: protractorBrowserPort, - base: ['src/main/webapp', 'src/test/resources/json/root', 'src/test/resources/json'], - middleware: function (connect, options) { - return [ - restMiddleware, - mountFolder(connect, options.base[0]), - mountFolder(connect, options.base[1]), - mountFolder(connect, options.base[2]) - ]; - } - } - } - }, copy: { lcov: { expand: true, @@ -167,7 +116,7 @@ module.exports = function (grunt) { options : { configFile : 'src/test/javascript/protractor.conf.js', args : { - baseUrl : 'http://localhost:' + protractorBrowserPort + baseUrl : 'http://localhost:' + tomcatPort } } }, @@ -177,7 +126,6 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-ngdocs'); grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-karma'); - grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-concat'); @@ -189,7 +137,7 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-protractor-runner'); grunt.registerTask('minify', ['clean:jsmin', 'removelogging', 'uglify', 'clean:cssmin', 'cssmin']); - grunt.registerTask('p:test', ['clean:e2etests','processhtml:e2eTests', 'connect', 'protractor', 'processhtml:production']); + grunt.registerTask('p:test', ['clean:e2etests','processhtml:e2eTests', 'protractor', 'processhtml:production']); grunt.registerTask('k:test', ['processhtml:development', 'karma', 'copy:lcov']); }; diff --git a/package.json b/package.json index 867a5d6..fac527f 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,6 @@ "grunt": "^0.4.5", "grunt-cli": "^0.1.13", "grunt-contrib-clean": "^0.5.0", - "grunt-contrib-connect": "^0.8.0", "grunt-contrib-copy": "~0.5.0", "grunt-contrib-jshint": "latest", "jshint-stylish": "latest", From 82ac8145863dff966457835909f056859bfa1c05 Mon Sep 17 00:00:00 2001 From: Roman Konovalov Date: Thu, 19 Mar 2015 12:18:57 +0300 Subject: [PATCH 04/10] Add reload DB functionality to e2e tests --- package.json | 3 ++- src/test/javascript/e2e/scenarios.js | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index fac527f..bd186d7 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "grunt-processhtml": "^0.3.3", "grunt-open": "0.2.3", "grunt-remove-logging": "latest", - "grunt-protractor-runner": "~1.2.1" + "grunt-protractor-runner": "~1.2.1", + "request": "~2.53.0" } } diff --git a/src/test/javascript/e2e/scenarios.js b/src/test/javascript/e2e/scenarios.js index 69ddf49..7c1ecbc 100644 --- a/src/test/javascript/e2e/scenarios.js +++ b/src/test/javascript/e2e/scenarios.js @@ -3,8 +3,14 @@ /* https://docs.angularjs.org/guide/e2e-testing */ describe('Eighty App', function() { + + var CONTEXT_PATH = '/eightytest'; + + var DB_RELOAD_PATH = browser.baseUrl + '/eightytest/db/reload'; var driver = browser.driver; + + var request = require('request'); var hasClass = function (element, cls) { return element.getAttribute('class').then(function (classes) { @@ -18,7 +24,7 @@ describe('Eighty App', function() { it('should redirect \ to \#\home', function() { driver.manage().window().maximize() - browser.get('/'); + browser.get(CONTEXT_PATH); browser.getLocationAbsUrl().then(function(url) { expect(url.split('#')[1]).toBe('/home'); }); @@ -27,7 +33,8 @@ describe('Eighty App', function() { describe('Epic A, Topics', function() { beforeEach(function() { - browser.get('/'); + request.get(DB_RELOAD_PATH); + browser.get(CONTEXT_PATH); }); it('User views real topics list', function() { @@ -163,7 +170,8 @@ describe('Eighty App', function() { describe('Epic B, Questions', function() { beforeEach(function() { - browser.get('/'); + request.get(DB_RELOAD_PATH); + browser.get(CONTEXT_PATH); }); it('View main page', function() { @@ -279,7 +287,8 @@ describe('Eighty App', function() { describe('Epic C, Export', function() { beforeEach(function() { - browser.get('/'); + request.get(DB_RELOAD_PATH); + browser.get(CONTEXT_PATH); }); it('User can add question to export list', function() { @@ -362,7 +371,8 @@ describe('Eighty App', function() { describe('Epic D, Tags', function() { beforeEach(function() { - browser.get('/'); + request.get(DB_RELOAD_PATH); + browser.get(CONTEXT_PATH); }); it('Topic tags displaying', function() { From 735f0d2d2c39ab026ddf06204cd10438f49ab2f7 Mon Sep 17 00:00:00 2001 From: Roman Konovalov Date: Thu, 19 Mar 2015 12:40:51 +0300 Subject: [PATCH 05/10] Fix DBPopulatorController --- .../com/epam/eighty/web/api/DBPopulatorController.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/epam/eighty/web/api/DBPopulatorController.java b/src/main/java/com/epam/eighty/web/api/DBPopulatorController.java index c95fe08..0fcc59f 100644 --- a/src/main/java/com/epam/eighty/web/api/DBPopulatorController.java +++ b/src/main/java/com/epam/eighty/web/api/DBPopulatorController.java @@ -5,6 +5,8 @@ import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Caching; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @@ -30,6 +32,12 @@ public class DBPopulatorController { @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Request processing failed") }) @Timed @RequestMapping(value = "/reload", method = RequestMethod.GET) + @Caching(evict = { + @CacheEvict(value = "topic", allEntries = true), + @CacheEvict(value = "question", allEntries = true), + @CacheEvict(value = "tag", allEntries = true), + @CacheEvict(value = "customer", allEntries = true) + }) public void reloadDataBase(final HttpServletResponse response) throws IOException { dbPopulatorService.clean(); dbPopulatorService.populate(); From bfd2f30e376b52ae08652ebefd1f705e5e2a83ed Mon Sep 17 00:00:00 2001 From: Roman Konovalov Date: Fri, 20 Mar 2015 10:48:06 +0300 Subject: [PATCH 06/10] Fix e2e tests --- src/main/resources/scripts/data.cypher | 6 + src/test/javascript/e2e/scenarios.js | 308 ++++++++++++++----------- 2 files changed, 173 insertions(+), 141 deletions(-) diff --git a/src/main/resources/scripts/data.cypher b/src/main/resources/scripts/data.cypher index beb44fb..d975008 100644 --- a/src/main/resources/scripts/data.cypher +++ b/src/main/resources/scripts/data.cypher @@ -6,6 +6,7 @@ create (n4:Topic:_Topic {title:'SQL'}) create (n5:Topic:_Topic {title:'HQL'}) create (n6:Topic:_Topic {title:'Java'}) create (n7:Topic:_Topic {title:'Language basics'}) +create (n8:Topic:_Topic {title:'Empty topic'}) create (t1:Topic:_Topic {title:'Object, class packaging'}) create (t2:Topic:_Topic {title:'Keywords'}) @@ -21,6 +22,7 @@ create (q3:Question:_Question {question:'What is Singleton class?'}) create (q4:Question:_Question {question:'List the three steps for creating an object for a class?'}) create (q5:Question:_Question {question:'What is the default value of float and double datatype in Java?'}) create (q6:Question:_Question {question:'What is a static variable?'}) +create (q7:Question:_Question {question:'Fake question'}) create (tag1:Tag:_Tag {tag:'object'}) create (tag2:Tag:_Tag {tag:'variable'}) @@ -37,6 +39,7 @@ create (c2:Customer:_Customer {name:'Customer2'}) create (n0)-[:contains]->(n1) create (n0)-[:contains]->(n2) +create (n0)-[:contains]->(n8) create (n2)-[:contains]->(n3) create (n3)-[:contains]->(n4) create (n3)-[:contains]->(n5) @@ -57,6 +60,7 @@ create (t1)-[:contains]->(q3) create (t1)-[:contains]->(q4) create (t1)-[:contains]->(q5) create (t1)-[:contains]->(q6) +create (n2)-[:contains]->(q7) create (q1)-[:has]->(tag1) create (q2)-[:has]->(tag2) @@ -70,8 +74,10 @@ create (q5)-[:has]->(tag7) create (q5)-[:has]->(tag8) create (q6)-[:has]->(tag9) create (q6)-[:has]->(tag2) +create (q7)-[:has]->(tag1) create (q1)-[:has]->(c1) create (q2)-[:has]->(c1) create (q3)-[:has]->(c2) create (q3)-[:has]->(c2) +create (q7)-[:has]->(c2) diff --git a/src/test/javascript/e2e/scenarios.js b/src/test/javascript/e2e/scenarios.js index 7c1ecbc..c3a9cec 100644 --- a/src/test/javascript/e2e/scenarios.js +++ b/src/test/javascript/e2e/scenarios.js @@ -4,9 +4,9 @@ describe('Eighty App', function() { - var CONTEXT_PATH = '/eightytest'; + var CONTEXT_PATH = '/eighty'; - var DB_RELOAD_PATH = browser.baseUrl + '/eightytest/db/reload'; + var DB_RELOAD_PATH = browser.baseUrl + CONTEXT_PATH + '/db/reload'; var driver = browser.driver; @@ -39,13 +39,13 @@ describe('Eighty App', function() { it('User views real topics list', function() { var rootTopics = element.all(by.repeater('row in tree_rows | filter:{visible:true} track by row.branch.uid')); - expect(rootTopics.count()).toBe(2); + expect(rootTopics.count()).toBe(3); }); it('User can view topics page', function() { - element.all(by.css('.abn-tree .tree-icon')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).element(by.xpath('parent::div/span[contains(@class,"tree-icon")]')).click(); var rootTopics = element.all(by.repeater('row in tree_rows | filter:{visible:true} track by row.branch.uid')); - expect(rootTopics.count()).toBe(3); + expect(rootTopics.count()).toBe(4); expect(hasClass(element.all(by.css('.abn-tree .abn-tree-row')).first(),'active')).toBe(false); }); @@ -66,7 +66,7 @@ describe('Eighty App', function() { element(by.model('addTopicInstance.topic.title')).sendKeys('fakeTopic'); element(by.css('.add-topic')).click(); var rootTopics = element.all(by.repeater('row in tree_rows | filter:{visible:true} track by row.branch.uid')); - expect(rootTopics.count()).toBe(3); + expect(rootTopics.count()).toBe(4); }); it('User cancels creation new top level topic', function() { @@ -76,72 +76,73 @@ describe('Eighty App', function() { element(by.model('addTopicInstance.topic.title')).sendKeys('fakeTopic'); element(by.css('.cancel-add-topic')).click(); var rootTopics = element.all(by.repeater('row in tree_rows | filter:{visible:true} track by row.branch.uid')); - expect(rootTopics.count()).toBe(2); + expect(rootTopics.count()).toBe(3); }); it('User can create new sub-topic', function() { $('.edit-toggle').click(); - var firstTopic = element.all(by.css('.abn-tree .tree-label')).first(); - browser.actions().mouseMove(firstTopic).perform(); - element.all(by.css('.addFolder')).first().click(); + var firstTopic = element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')); + hover(firstTopic); + var addTopic = firstTopic.element(by.xpath('parent::div/span/i[contains(@class,"addFolder")]')).click(); + //browser.driver.wait(protractor.until.elementIsNotVisible(addTopic), 5000); driver.switchTo().activeElement(); element(by.model('addTopicInstance.topic.title')).sendKeys('fakeTopic'); element(by.css('.add-topic')).click(); var rootTopics = element.all(by.repeater('row in tree_rows | filter:{visible:true} track by row.branch.uid')); - expect(rootTopics.count()).toBe(4); + expect(rootTopics.count()).toBe(5); }); it('User cancels creation new sub-topic', function() { $('.edit-toggle').click(); - var firstTopic = element.all(by.css('.abn-tree .tree-label')).first(); - browser.actions().mouseMove(firstTopic).perform(); - element.all(by.css('.addFolder')).first().click(); + var firstTopic = element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')); + hover(firstTopic); + firstTopic.element(by.xpath('parent::div/span/i[contains(@class,"addFolder")]')).click(); driver.switchTo().activeElement(); element(by.model('addTopicInstance.topic.title')).sendKeys('fakeTopic'); element(by.css('.cancel-add-topic')).click(); var rootTopics = element.all(by.repeater('row in tree_rows | filter:{visible:true} track by row.branch.uid')); - expect(rootTopics.count()).toBe(2); + expect(rootTopics.count()).toBe(3); }); it('User can delete top level topic', function() { $('.edit-toggle').click(); - var firstTopic = element.all(by.css('.abn-tree .tree-label')).first(); - browser.actions().mouseMove(firstTopic).perform(); - element.all(by.css('.deleteFolder')).first().click(); + var firstTopic = element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')); + hover(firstTopic); + firstTopic.element(by.xpath('parent::div/span/i[contains(@class,"deleteFolder")]')).click(); driver.switchTo().activeElement(); element(by.css('.delete-topic')).click(); var rootTopics = element.all(by.repeater('row in tree_rows | filter:{visible:true} track by row.branch.uid')); - expect(rootTopics.count()).toBe(1); + expect(rootTopics.count()).toBe(2); }); it('User cancels delete top level topic', function() { $('.edit-toggle').click(); - var firstTopic = element.all(by.css('.abn-tree .tree-label')).first(); - browser.actions().mouseMove(firstTopic).perform(); - element.all(by.css('.deleteFolder')).first().click(); + var firstTopic = element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')); + hover(firstTopic); + firstTopic.element(by.xpath('parent::div/span/i[contains(@class,"deleteFolder")]')).click(); driver.switchTo().activeElement(); element(by.css('.cancel-delete-topic')).click(); var rootTopics = element.all(by.repeater('row in tree_rows | filter:{visible:true} track by row.branch.uid')); - expect(rootTopics.count()).toBe(2); + expect(rootTopics.count()).toBe(3); }); it('User can delete sub-topic', function() { $('.edit-toggle').click(); - element.all(by.css('.abn-tree .tree-icon')).first().click(); - var subTopic = element.all(by.css('.abn-tree .tree-label')).get(1); - browser.actions().mouseMove(subTopic).perform(); - element.all(by.css('.deleteFolder')).get(1).click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).element(by.xpath('parent::div/span[contains(@class,"tree-icon")]')).click(); + var subTopic = element(by.cssContainingText('.abn-tree .tree-label', 'Java')); + hover(subTopic); + subTopic.element(by.xpath('parent::div/span/i[contains(@class,"deleteFolder")]')).click(); driver.switchTo().activeElement(); element(by.css('.delete-topic')).click(); var rootTopics = element.all(by.repeater('row in tree_rows | filter:{visible:true} track by row.branch.uid')); - expect(rootTopics.count()).toBe(2); + expect(rootTopics.count()).toBe(3); }); it('User can edit topic', function() { $('.edit-toggle').click(); - var firstTopic = element.all(by.css('.abn-tree .tree-label')).first(); - browser.actions().mouseMove(firstTopic).perform(); - element.all(by.css('.editFolder')).first().click(); + var firstTopic = element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')); + hover(firstTopic); + firstTopic.element(by.xpath('parent::div/span/i[contains(@class,"editFolder")]')).click(); driver.switchTo().activeElement(); firstTopic.getText().then(function(text) { var initialTopicTitle = text; @@ -154,9 +155,9 @@ describe('Eighty App', function() { it('User cancels edit topic', function() { $('.edit-toggle').click(); - var firstTopic = element.all(by.css('.abn-tree .tree-label')).first(); - browser.actions().mouseMove(firstTopic).perform(); - element.all(by.css('.editFolder')).first().click(); + var firstTopic = element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')); + hover(firstTopic); + firstTopic.element(by.xpath('parent::div/span/i[contains(@class,"editFolder")]')).click(); driver.switchTo().activeElement(); firstTopic.getText().then(function(text) { var initialTopicTitle = text; @@ -180,17 +181,13 @@ describe('Eighty App', function() { }); it('User can view question list for selected list-level topic', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); - browser.sleep(10); - var topicTitle = element(by.css('.topic-title')).getText(); - var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); - expect(topicTitle).toBe('Programming Languages'); - expect(setQ.count()).toBe(3); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); + var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); + expect(setQ.count()).toBe(6); }); it('User can view no question message', function() { - element.all(by.css('.abn-tree .tree-label')).get(1).click(); - browser.sleep(10); + element(by.cssContainingText('.abn-tree .tree-label', 'Empty topic')).click(); var title = element(by.css('.div-error')).getText(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); expect(setQ.count()).toBe(0); @@ -198,7 +195,7 @@ describe('Eighty App', function() { }); it('User can rate question', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); hover(setQ.first()); element.all(by.css('.rate-up-question')).first().click(); @@ -207,28 +204,28 @@ describe('Eighty App', function() { }); it('User can create new question', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); - expect(setQ.count()).toBe(3); + expect(setQ.count()).toBe(6); element(by.id('button')).click(); element(by.model('addQuestion.question.question')).sendKeys('fakeQuestion'); element(by.css('.add-question')).click(); setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); - expect(setQ.count()).toBe(4); + expect(setQ.count()).toBe(7); }); it('User cancels creation new question', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); - expect(setQ.count()).toBe(3); + expect(setQ.count()).toBe(6); element(by.id('button')).click(); element(by.model('addQuestion.question.question')).sendKeys('fakeQuestion'); element(by.css('.cancel-add-question')).click(); - expect(setQ.count()).toBe(3); + expect(setQ.count()).toBe(6); }); it('User can edit a question', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); setQ.first().getText().then(function(initialQuestion) { hover(setQ.first()); @@ -241,7 +238,7 @@ describe('Eighty App', function() { }); it('User cancel edit a question', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); setQ.first().getText().then(function(initialQuestion) { hover(setQ.first()); @@ -254,7 +251,7 @@ describe('Eighty App', function() { }); it('User can delete a question', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); setQ.first().getText().then(function() { hover(setQ.first()); @@ -264,12 +261,12 @@ describe('Eighty App', function() { browser.sleep(10); element(by.css('.confirm-delete-question')).click(); browser.sleep(10); - expect(setQ.count()).toBe(2); + expect(setQ.count()).toBe(5); }); }); it('User cancel removal a question', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); setQ.first().getText().then(function() { hover(setQ.first()); @@ -279,7 +276,7 @@ describe('Eighty App', function() { browser.sleep(10); element(by.css('.cancel-delete-question')).click(); browser.sleep(10); - expect(setQ.count()).toBe(3); + expect(setQ.count()).toBe(6); }); }); }); @@ -290,9 +287,18 @@ describe('Eighty App', function() { request.get(DB_RELOAD_PATH); browser.get(CONTEXT_PATH); }); + + afterEach(function() { + var elem = element(by.id('clear-export-list')); + elem.isDisplayed().then(function (isVisible) { + if (isVisible) { + elem.click(); + } + }); + }); it('User can add question to export list', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); setQ.first().getText().then(function() { hover(setQ.first()); @@ -303,30 +309,51 @@ describe('Eighty App', function() { }); it('User see amount of questions to export at the navigation bar', function() { + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); + var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); + setQ.first().getText().then(function() { + hover(setQ.first()); + element.all(by.css('.export-question')).first().click(); + var elem = element(by.id('export')); + expect(elem.isDisplayed()).toBe(true); + }); + element.all(by.css('.abn-tree .tree-label')).first().click(); var text = element(by.id('export-link')).getText(); expect(text).toBe('selected for export: 1'); }); it('Selection to export persists between user visits', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); + var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); + setQ.first().getText().then(function() { + hover(setQ.first()); + element.all(by.css('.export-question')).first().click(); + var elem = element(by.id('export')); + expect(elem.isDisplayed()).toBe(true); + }); + + browser.get(CONTEXT_PATH); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var elem = element.all(by.css('.export-question')).first(); expect(elem.isDisplayed()).toBe(true); }); it('User can deselect individual questions', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); setQ.first().getText().then(function() { - hover(setQ.first()); - element.all(by.css('.export-question')).first().click(); + var question = setQ.first(); + hover(question); + question.element(by.css('.export-question')).click(); + question.element(by.css('.export-question')).click(); var elem = element(by.id('export')); expect(elem.isDisplayed()).toBe(false); }); }); - it('User can clear export list', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + it('User can clear export list', function() { + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); setQ.first().getText().then(function() { hover(setQ.first()); @@ -339,7 +366,7 @@ describe('Eighty App', function() { }); it('User can browse export list', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); setQ.first().getText().then(function() { hover(setQ.first()); @@ -352,12 +379,26 @@ describe('Eighty App', function() { }); it('User see all the questions selected for export on the Export page', function() { + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); + var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); + hover(setQ.first()); + element.all(by.css('.export-question')).first().click(); + var elem = element(by.id('export')); + expect(elem.isDisplayed()).toBe(true); + element(by.id('export-link')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questionsForExport')); - expect(setQ.count()).toBe(1); + expect(setQ.count()).toBe(1); }); it('User see print button', function() { + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); + var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); + hover(setQ.first()); + element.all(by.css('.export-question')).first().click(); + var elem = element(by.id('export')); + expect(elem.isDisplayed()).toBe(true); + element(by.id('export-link')).click(); var elem = element(by.id('printing')); expect(elem.isDisplayed()).toBe(true); @@ -376,145 +417,130 @@ describe('Eighty App', function() { }); it('Topic tags displaying', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var elem = element(by.id('div-tags-main')); expect(elem.isDisplayed()).toBe(true); }); it('User clicks any tag and sees only questions from selected topic with this tag', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); + var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); + expect(setQ.count()).toBe(6); var setTags = element.all(by.repeater('tagOrCustomer in questionsCtrl.tagsAndCustomers')); - browser.sleep(5000); - expect(setTags.count()).toBe(5); - var elem = element.all(by.css('.notSelected')).first(); - expect(elem.getAttribute('class')).toBe('badge alert-info ng-binding notSelected'); - elem.click(); - browser.sleep(1000); - elem = element.all(by.css('.selected')).first(); - expect(elem.getAttribute('class')).toBe('badge alert-info ng-binding selected'); + expect(setTags.count()).toBe(11); + var tag = element(by.id('tag_object')); + tag.click(); + expect(setQ.count()).toBe(2); }); it('When at least one tag is selected, then only questions with selected tag(s) displayed from selected topic', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); - expect(setQ.count()).toBe(3); - var elem = element.all(by.css('.notSelected')).first(); - expect(elem.getAttribute('class')).toBe('badge alert-info ng-binding notSelected'); - elem.click(); - browser.sleep(100); - setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); + expect(setQ.count()).toBe(6); + var setTags = element.all(by.repeater('tagOrCustomer in questionsCtrl.tagsAndCustomers')); + expect(setTags.count()).toBe(11); + var tag = element(by.id('tag_object')); + tag.click(); expect(setQ.count()).toBe(2); }); it('Popular tags displaying', function() { - var elem = element(by.id('tagTop_tag1')); + var elem = element(by.id('tagTop_class')); expect(elem.isDisplayed()).toBe(true); - elem = element(by.id('tagTop_tag2')); + elem = element(by.id('tagTop_variable')); expect(elem.isDisplayed()).toBe(true); }); it('When user clicks tag in popular tags, then questions with selected tag displayed', function() { - element(by.id('tagTop_tag2')).click(); - browser.sleep(100); + element(by.id('tagTop_class')).click(); var topicTitle = element(by.css('.topic-title')).getText(); - expect(topicTitle).toBe('Questions with tag: tag2'); + expect(topicTitle).toBe('Questions with tag: class'); var setQ = element.all(by.repeater('quest in filtered.questions | questionFilter : filtered.criteria track by $index')); expect(setQ.count()).toBe(2); }); it('When user clicks on tag in footer under questions and there are no more questions for this tag, then link to page questionsWithTag is disabled', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); - element.all(by.css('.notSelected')).first().click(); - var tag = element.all(by.repeater('selTag in questionsCtrl.selectedTags')).first(); - expect(tag.getAttribute('class')).toBe('ng-scope'); - var elems = element.all(by.css('.disabled')); - expect(elems.count()).toBe(1); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); + browser.sleep(10); + element(by.id('tag_class')).click(); + var link = element(by.id('tagSelected_class')); + expect(link.isDisplayed()).toBe(true); }); it('When user clicks on tag in footer under questions, then all questions with selected tag displayed', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); - element(by.id('tag_tag2')).click(); - var tag = element.all(by.repeater('selTag in questionsCtrl.selectedTags')).first(); - expect(tag.getAttribute('class')).toBe('ng-scope'); - var elems = element.all(by.css('.disabled')); - expect(elems.count()).toBe(0); - element(by.id('tagSelected_tag2')).click(); - browser.sleep(100); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); + browser.sleep(10); + element(by.id('tag_object')).click(); + browser.sleep(10); + element(by.id('tagSelected_object')).click(); + browser.sleep(10); var setQ = element.all(by.repeater('quest in filtered.questions | questionFilter : filtered.criteria track by $index')); - expect(setQ.count()).toBe(2); + expect(setQ.count()).toBe(3); }); it('When user clicks on customer in footer under questions and there are no more questions from this customer, then link to page questionsFromCustomer is disabled', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); - element.all(by.css('.notSelected')).get(1).click(); - browser.sleep(1000); - var customer = element.all(by.repeater('selTag in questionsCtrl.selectedTags')).first(); - expect(customer.getAttribute('class')).toBe('ng-scope'); - var elems = element.all(by.css('.disabled')); - expect(elems.count()).toBe(1); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); + browser.sleep(10); + element(by.id('tag_Customer1')).click(); + var link = element(by.id('tagSelected_Customer1')); + expect(link.isDisplayed()).toBe(true); }); it('When user clicks on customer in footer under questions, then all questions from selected customer displayed', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); - element(by.id('tag_customer2')).click(); - var tag = element.all(by.repeater('selTag in questionsCtrl.selectedTags')).first(); - expect(tag.getAttribute('class')).toBe('ng-scope'); - var elems = element.all(by.css('.disabled')); - expect(elems.count()).toBe(0); - element(by.id('tagSelected_customer2')).click(); - browser.sleep(1000); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); + browser.sleep(10); + element(by.id('tag_Customer2')).click(); + browser.sleep(10); + element(by.id('tagSelected_Customer2')).click(); + browser.sleep(10); var setQ = element.all(by.repeater('quest in filtered.questions | questionFilter : filtered.criteria track by $index')); - expect(setQ.count()).toBe(2); + expect(setQ.count()).toBe(3); }); it('Customers displaying', function() { - var elem = element(by.id('customer_customer1')); + var elem = element(by.id('customer_Customer1')); expect(elem.isDisplayed()).toBe(true); - elem = element(by.id('customer_customer2')); + elem = element(by.id('customer_Customer2')); expect(elem.isDisplayed()).toBe(true); }); it('When user clicks customer, then questions with selected customer displayed', function() { - element(by.id('customer_customer1')).click(); - browser.sleep(100); + element(by.id('customer_Customer1')).click(); + browser.sleep(10); var topicTitle = element(by.css('.topic-title')).getText(); - expect(topicTitle).toBe('Questions from customer: customer1'); + expect(topicTitle).toBe('Questions from customer: Customer1'); var setQ = element.all(by.repeater('quest in filtered.questions | questionFilter : filtered.criteria track by $index')); expect(setQ.count()).toBe(2); }); it('When user switches off all tags button, then all questions from selected topic (and subtopics) are displayed', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); + expect(setQ.count()).toBe(6); + element(by.id('tag_object')).click(); + element(by.id('tag_Customer1')).click(); + browser.sleep(10); expect(setQ.count()).toBe(3); - var elem = element.all(by.css('.notSelected')).first(); - expect(elem.getAttribute('class')).toBe('badge alert-info ng-binding notSelected'); - elem.click(); - browser.sleep(100); - setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); - expect(setQ.count()).toBe(2); - var clearElem = element(by.id('clear-tags')); - clearElem.click(); - browser.sleep(100); - setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); - expect(setQ.count()).toBe(3); + element(by.id('clear-tags')).click(); + browser.sleep(10); + expect(setQ.count()).toBe(6); }); it('Add tags when question is being created', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); - expect(setQ.count()).toBe(3); + expect(setQ.count()).toBe(6); element(by.id('button')).click(); driver.switchTo().activeElement(); element(by.model('addQuestion.question.question')).sendKeys('fakeQuestion'); $('#tags div input').sendKeys('newTag1,newTag2,newTag3,'); element(by.css('.add-question')).click(); setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); - expect(setQ.count()).toBe(4); + expect(setQ.count()).toBe(7); }); it('When question is being edited, then user can add/remove/edit both customers and tags', function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); setQ.first().getText().then(function(initialQuestion) { hover(setQ.first()); @@ -522,16 +548,16 @@ describe('Eighty App', function() { element(by.model('editQuestion.question.question')).sendKeys('fakeQuestion'); $('#tags div input').sendKeys('newTag1,newTag2,newTag3,'); var tags = element.all(by.repeater('tag in tagList.items track by track(tag)')); - expect(tags.count()).toBe(5); + expect(tags.count()).toBe(6); element(by.css('.save-question')).click(); browser.sleep(10); expect(setQ.first().getText()).toBe(initialQuestion + 'fakeQuestion'); - expect(setQ.count()).toBe(3); + expect(setQ.count()).toBe(6); }); }); it('Should show/hide "Clear Tag/Tags" button when user selects any tag' , function() { - element.all(by.css('.abn-tree .tree-label')).first().click(); + element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')).click(); var clearTagsBtn = element(by.id('clear-tags')); expect(clearTagsBtn.isDisplayed()).toBeFalsy(); var tagsList = element.all(by.css('.notSelected')); //unselected tags From a67b2129b4069df80df19ff1914e93b83ecb9748 Mon Sep 17 00:00:00 2001 From: Roman Konovalov Date: Fri, 20 Mar 2015 11:15:19 +0300 Subject: [PATCH 07/10] Fix e2e tests --- src/test/javascript/e2e/scenarios.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/test/javascript/e2e/scenarios.js b/src/test/javascript/e2e/scenarios.js index c3a9cec..e7dfd1d 100644 --- a/src/test/javascript/e2e/scenarios.js +++ b/src/test/javascript/e2e/scenarios.js @@ -4,7 +4,7 @@ describe('Eighty App', function() { - var CONTEXT_PATH = '/eighty'; + var CONTEXT_PATH = '/eightytest'; var DB_RELOAD_PATH = browser.baseUrl + CONTEXT_PATH + '/db/reload'; @@ -21,6 +21,16 @@ describe('Eighty App', function() { var hover = function (element) { browser.actions().mouseMove(element).perform(); }; + + var clickWhenVisible = function(elem) { + browser.driver.wait(function() { + return elem.isDisplayed().then(function(isVisible) { + return isVisible ? 1 : 0; + }); + }, 3000); + + elem.click(); + }; it('should redirect \ to \#\home', function() { driver.manage().window().maximize() @@ -157,7 +167,8 @@ describe('Eighty App', function() { $('.edit-toggle').click(); var firstTopic = element(by.cssContainingText('.abn-tree .tree-label', 'Programming Languages')); hover(firstTopic); - firstTopic.element(by.xpath('parent::div/span/i[contains(@class,"editFolder")]')).click(); + clickWhenVisible(firstTopic.element(by.xpath('parent::div/span/i[contains(@class,"editFolder")]'))); + driver.switchTo().activeElement(); firstTopic.getText().then(function(text) { var initialTopicTitle = text; @@ -229,10 +240,9 @@ describe('Eighty App', function() { var setQ = element.all(by.repeater('quest in questionsCtrl.questions| questionFilter : questionsCtrl.criteria | tagFilter : questionsCtrl.selectedTags track by $index')); setQ.first().getText().then(function(initialQuestion) { hover(setQ.first()); - element.all(by.css('.edit-question')).first().click(); + clickWhenVisible(element.all(by.css('.edit-question')).first()); element(by.model('editQuestion.question.question')).sendKeys('fakeQuestion'); element(by.css('.save-question')).click(); - browser.sleep(10); expect(setQ.first().getText()).toBe(initialQuestion + 'fakeQuestion'); }); }); @@ -245,7 +255,6 @@ describe('Eighty App', function() { element.all(by.css('.edit-question')).first().click(); element(by.model('editQuestion.question.question')).sendKeys('fakeQuestion'); element(by.css('.cancel-save-question')).click(); - browser.sleep(10); expect(setQ.first().getText()).toBe(initialQuestion); }); }); From ea5fb048b349f35476a4d0f4a9a94c5124d7f688 Mon Sep 17 00:00:00 2001 From: Roman Konovalov Date: Fri, 20 Mar 2015 11:20:35 +0300 Subject: [PATCH 08/10] Fix build scripts --- commit_build.bat | 4 ++-- dirty_deploy.bat | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/commit_build.bat b/commit_build.bat index d3da0f1..41ee0c1 100644 --- a/commit_build.bat +++ b/commit_build.bat @@ -3,6 +3,6 @@ rem code quality checks: yes (findbugs, pmd, checkstyle) rem deploy: no deploy rem intent of using: production rem minification: yes -rem we can modify server port for protractor e2e tests by passing argument "-Dprotractor.port=_port_number_" +rem we can modify port for embedded tomcat 7 server by passing argument "-Dtomcat.port=_port_number_" rem this can be useful to suppress port conflict during executing 2 synchronous Jenkins jobs -mvn clean verify -Pprod %1 +mvn clean verify -Pprod -Dspring.profiles.active=test %1 diff --git a/dirty_deploy.bat b/dirty_deploy.bat index 7c1487c..5228a39 100644 --- a/dirty_deploy.bat +++ b/dirty_deploy.bat @@ -1,6 +1,7 @@ rem test: no rem code quality checks: no -rem deploy: deploy on local server tomcat 7 -rem intent of using: development with deploy on local server tomcat 7 that should be started before deploy +rem deploy: deploy on embedded server tomcat 7 +rem intent of using: development with starting embedded tomcat 7 server rem minification: no -mvn clean package tomcat7:deploy -DskipTests -DskipITs -Dfindbugs.skip=true -Dpmd.skip=true -Dcheckstyle.skip=true +rem we can modify port for embedded tomcat 7 server by passing argument "-Dtomcat.port=_port_number_" +mvn clean tomcat7:run-war -Pdev -DskipTests -Dspring.profiles.active=dev %1 From 638f675c7f61941c2f487fe5b8eb27bdad9a6914 Mon Sep 17 00:00:00 2001 From: Roman Konovalov Date: Fri, 20 Mar 2015 11:32:01 +0300 Subject: [PATCH 09/10] Fix build scripts --- commit_build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commit_build b/commit_build index 35d1817..b7e7e71 100755 --- a/commit_build +++ b/commit_build @@ -4,6 +4,6 @@ # "deploy: no deploy" # "intent of using: production" # "minification: yes" -# "we can modify server port for protractor e2e tests by passing argument "-Dprotractor.port=_port_number_" +# "we can modify port for embedded tomcat 7 server by passing argument "-Dtomcat.port=_port_number_" # "this can be useful to suppress port conflict during executing 2 synchronous Jenkins jobs" -mvn clean verify -Pprod $1 +mvn clean verify -Pprod -Dspring.profiles.active=test $1 From 7b67d482ec9ff5d934763522c153eb23216d8996 Mon Sep 17 00:00:00 2001 From: Roman Konovalov Date: Fri, 20 Mar 2015 11:45:45 +0300 Subject: [PATCH 10/10] Remove redundant json files --- src/test/resources/json/customers/1 | 0 src/test/resources/json/customers/all | 0 src/test/resources/json/customers/topic/0 | 0 src/test/resources/json/customers/topic/1 | 0 src/test/resources/json/question/1 | 1 - src/test/resources/json/questions/1 | 1 - src/test/resources/json/questions/17 | 7 ------- src/test/resources/json/questions/2 | 0 src/test/resources/json/questions/6 | 5 ----- src/test/resources/json/questions/all/1 | 5 ----- src/test/resources/json/questions/all/2 | 0 src/test/resources/json/questions/all/6 | 5 ----- src/test/resources/json/questions/all/customer/customer1 | 4 ---- src/test/resources/json/questions/all/customer/customer2 | 4 ---- src/test/resources/json/questions/all/tag/tag2 | 4 ---- src/test/resources/json/root/topics | 1 - src/test/resources/json/tags/tag/test | 0 src/test/resources/json/tags/tags | 0 src/test/resources/json/tags/top/10 | 4 ---- src/test/resources/json/tags/topic/0 | 1 - src/test/resources/json/tags/topic/1 | 7 ------- src/test/resources/json/tags/topic/2 | 4 ---- src/test/resources/json/tags/topic/6 | 0 src/test/resources/json/tags/topic/tags | 0 src/test/resources/json/topics/1 | 1 - src/test/resources/json/topics/2 | 5 ----- src/test/resources/json/topics/6 | 7 ------- 27 files changed, 66 deletions(-) delete mode 100644 src/test/resources/json/customers/1 delete mode 100644 src/test/resources/json/customers/all delete mode 100644 src/test/resources/json/customers/topic/0 delete mode 100644 src/test/resources/json/customers/topic/1 delete mode 100644 src/test/resources/json/question/1 delete mode 100644 src/test/resources/json/questions/1 delete mode 100644 src/test/resources/json/questions/17 delete mode 100644 src/test/resources/json/questions/2 delete mode 100644 src/test/resources/json/questions/6 delete mode 100644 src/test/resources/json/questions/all/1 delete mode 100644 src/test/resources/json/questions/all/2 delete mode 100644 src/test/resources/json/questions/all/6 delete mode 100644 src/test/resources/json/questions/all/customer/customer1 delete mode 100644 src/test/resources/json/questions/all/customer/customer2 delete mode 100644 src/test/resources/json/questions/all/tag/tag2 delete mode 100644 src/test/resources/json/root/topics delete mode 100644 src/test/resources/json/tags/tag/test delete mode 100644 src/test/resources/json/tags/tags delete mode 100644 src/test/resources/json/tags/top/10 delete mode 100644 src/test/resources/json/tags/topic/0 delete mode 100644 src/test/resources/json/tags/topic/1 delete mode 100644 src/test/resources/json/tags/topic/2 delete mode 100644 src/test/resources/json/tags/topic/6 delete mode 100644 src/test/resources/json/tags/topic/tags delete mode 100644 src/test/resources/json/topics/1 delete mode 100644 src/test/resources/json/topics/2 delete mode 100644 src/test/resources/json/topics/6 diff --git a/src/test/resources/json/customers/1 b/src/test/resources/json/customers/1 deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/resources/json/customers/all b/src/test/resources/json/customers/all deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/resources/json/customers/topic/0 b/src/test/resources/json/customers/topic/0 deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/resources/json/customers/topic/1 b/src/test/resources/json/customers/topic/1 deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/resources/json/question/1 b/src/test/resources/json/question/1 deleted file mode 100644 index 11b396e..0000000 --- a/src/test/resources/json/question/1 +++ /dev/null @@ -1 +0,0 @@ -{id: 20, question: 'fakeQuestion', answer: '', tags: [], customers: []} \ No newline at end of file diff --git a/src/test/resources/json/questions/1 b/src/test/resources/json/questions/1 deleted file mode 100644 index 4b04b47..0000000 --- a/src/test/resources/json/questions/1 +++ /dev/null @@ -1 +0,0 @@ -{"id": 20, "question": "fakeQuestion", "answer": "", "tags": [], "customers": []} \ No newline at end of file diff --git a/src/test/resources/json/questions/17 b/src/test/resources/json/questions/17 deleted file mode 100644 index fbe1aed..0000000 --- a/src/test/resources/json/questions/17 +++ /dev/null @@ -1,7 +0,0 @@ -{ - "id":17, - "question":"q1", - "answer":"a1", - "like":0, - "tags":{"id":"20", "tag":"tag1"} -} \ No newline at end of file diff --git a/src/test/resources/json/questions/2 b/src/test/resources/json/questions/2 deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/resources/json/questions/6 b/src/test/resources/json/questions/6 deleted file mode 100644 index 5156868..0000000 --- a/src/test/resources/json/questions/6 +++ /dev/null @@ -1,5 +0,0 @@ -[ - {"id":17,"question":"q1","answer":"a1","tags":{"id":"20", "tag":"tag1"}}, - {"id":18,"question":"q2","answer":"a2","tags":{"id":"21", "tag":"tag2"}}, - {"id":19,"question":"q3","answer":"a3","like":2,"tags":{"id":"20", "tag":"tag1"}} -] \ No newline at end of file diff --git a/src/test/resources/json/questions/all/1 b/src/test/resources/json/questions/all/1 deleted file mode 100644 index 8674ffc..0000000 --- a/src/test/resources/json/questions/all/1 +++ /dev/null @@ -1,5 +0,0 @@ -[ - {"id":17,"question":"q1","answer":"a1","like":0,"tags":[{"id":31,"tag":"tag1"}],"customers":[{"id":51,"name":"customer1"}]}, - {"id":18,"question":"q2","answer":"a2","like":0,"tags":[{"id":32,"tag":"tag2"}],"customers":[{"id":52,"name":"customer2"}]}, - {"id":19,"question":"q3","answer":"a3","like":2,"tags":[{"id":31,"tag":"tag1"}],"customers":[{"id":51,"name":"customer1"}]} -] \ No newline at end of file diff --git a/src/test/resources/json/questions/all/2 b/src/test/resources/json/questions/all/2 deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/resources/json/questions/all/6 b/src/test/resources/json/questions/all/6 deleted file mode 100644 index 5156868..0000000 --- a/src/test/resources/json/questions/all/6 +++ /dev/null @@ -1,5 +0,0 @@ -[ - {"id":17,"question":"q1","answer":"a1","tags":{"id":"20", "tag":"tag1"}}, - {"id":18,"question":"q2","answer":"a2","tags":{"id":"21", "tag":"tag2"}}, - {"id":19,"question":"q3","answer":"a3","like":2,"tags":{"id":"20", "tag":"tag1"}} -] \ No newline at end of file diff --git a/src/test/resources/json/questions/all/customer/customer1 b/src/test/resources/json/questions/all/customer/customer1 deleted file mode 100644 index 3186c40..0000000 --- a/src/test/resources/json/questions/all/customer/customer1 +++ /dev/null @@ -1,4 +0,0 @@ -[ - {"id":33,"question":"q1","answer":"a1","like":0,"tags":[],"customers":[{"id":41,"name":"customer1"}]}, - {"id":34,"question":"q2","answer":"a2","like":0,"tags":[],"customers":[{"id":42,"name":"customer2"}]} -] \ No newline at end of file diff --git a/src/test/resources/json/questions/all/customer/customer2 b/src/test/resources/json/questions/all/customer/customer2 deleted file mode 100644 index a41b15d..0000000 --- a/src/test/resources/json/questions/all/customer/customer2 +++ /dev/null @@ -1,4 +0,0 @@ -[ - {"id":18,"question":"q2","answer":"a2","like":0,"tags":[{"id":32,"tag":"tag2"}],"customers":[{"id":42,"name":"customer2"}]}, - {"id":45,"question":"q4","answer":"a4","like":0,"tags":[{"id":32,"tag":"tag2"}],"customers":[{"id":42,"name":"customer2"}]} -] \ No newline at end of file diff --git a/src/test/resources/json/questions/all/tag/tag2 b/src/test/resources/json/questions/all/tag/tag2 deleted file mode 100644 index 420fb97..0000000 --- a/src/test/resources/json/questions/all/tag/tag2 +++ /dev/null @@ -1,4 +0,0 @@ -[ - {"id":18,"question":"q2","answer":"a2","like":0,"tags":[{"id":32,"tag":"tag2"}],"customers":[{"id":52,"name":"customer2"}]}, - {"id":45,"question":"q4","answer":"a4","like":0,"tags":[{"id":32,"tag":"tag2"}],"customers":[{"id":52,"name":"customer2"}]} -] \ No newline at end of file diff --git a/src/test/resources/json/root/topics b/src/test/resources/json/root/topics deleted file mode 100644 index 3bc336a..0000000 --- a/src/test/resources/json/root/topics +++ /dev/null @@ -1 +0,0 @@ -{"id":0,"title":"root","topics":[{"id":1,"title":"Programming Languages","topics":[{"id":6,"title":"Java","topics":[{"id":7,"title":null,"topics":[],"questions":[]}],"questions":[]}],"questions":[]},{"id":2,"title":"Persistence","topics":[{"id":3,"title":"Query Lanquages","topics":[{"id":4,"title":null,"topics":[],"questions":[]},{"id":5,"title":null,"topics":[],"questions":[]}],"questions":[]}],"questions":[]}],"questions":[]} \ No newline at end of file diff --git a/src/test/resources/json/tags/tag/test b/src/test/resources/json/tags/tag/test deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/resources/json/tags/tags b/src/test/resources/json/tags/tags deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/resources/json/tags/top/10 b/src/test/resources/json/tags/top/10 deleted file mode 100644 index 6ef499f..0000000 --- a/src/test/resources/json/tags/top/10 +++ /dev/null @@ -1,4 +0,0 @@ -[ - {"id":31,"tag":"tag1","count":2}, - {"id":32,"tag":"tag2","count":2} -] \ No newline at end of file diff --git a/src/test/resources/json/tags/topic/0 b/src/test/resources/json/tags/topic/0 deleted file mode 100644 index 0637a08..0000000 --- a/src/test/resources/json/tags/topic/0 +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/src/test/resources/json/tags/topic/1 b/src/test/resources/json/tags/topic/1 deleted file mode 100644 index b9fee5f..0000000 --- a/src/test/resources/json/tags/topic/1 +++ /dev/null @@ -1,7 +0,0 @@ -[ - {"id":31,"tag":"tag1","count":2,"countInTopic":2}, - {"id":32,"tag":"tag2","count":2,"countInTopic":1}, - {"id":33,"tag":"tag3","count":0,"countInTopic":0}, - {"id":41,"name":"customer1","count":2,"countInTopic":2}, - {"id":42,"name":"customer2","count":2,"countInTopic":1} -] \ No newline at end of file diff --git a/src/test/resources/json/tags/topic/2 b/src/test/resources/json/tags/topic/2 deleted file mode 100644 index c804bbd..0000000 --- a/src/test/resources/json/tags/topic/2 +++ /dev/null @@ -1,4 +0,0 @@ -[ - {"id":32,"tag":"tag2","count":1,"countInTopic":1}, - {"id":42,"name":"customer2","count":2,"countInTopic":1} -] \ No newline at end of file diff --git a/src/test/resources/json/tags/topic/6 b/src/test/resources/json/tags/topic/6 deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/resources/json/tags/topic/tags b/src/test/resources/json/tags/topic/tags deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/resources/json/topics/1 b/src/test/resources/json/topics/1 deleted file mode 100644 index 31b9c1e..0000000 --- a/src/test/resources/json/topics/1 +++ /dev/null @@ -1 +0,0 @@ -{"id":1,"title":"Programming Languages","topics":[{"id":6,"title":"Java","topics":[{"id":7,"title":null,"topics":[],"questions":[]}],"questions":[]}],"questions":[]} \ No newline at end of file diff --git a/src/test/resources/json/topics/2 b/src/test/resources/json/topics/2 deleted file mode 100644 index 0895b0a..0000000 --- a/src/test/resources/json/topics/2 +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id":6, - "title":"Persistence", - "topics":[] -} \ No newline at end of file diff --git a/src/test/resources/json/topics/6 b/src/test/resources/json/topics/6 deleted file mode 100644 index f7dcc69..0000000 --- a/src/test/resources/json/topics/6 +++ /dev/null @@ -1,7 +0,0 @@ -{ - "id":6, - "title":"Java", - "topics":[ - {"id":7,"title":null,"topics":[],"questions":[]} - ] -} \ No newline at end of file