===== Protractor ===== Is an **end-to-end testing** JavaScript solution. * Executes the real application using selenium * Run the tests against it Protractor is nothing but a wrapper over the Selenium WebDriverJS Api that translates its succinct code and methods to WebDriver JS methods. That said, you can use WebDriverJS methods too inside your e2e script. https://medium.com/paramsingh-66174/automate-e2e-testing-of-angular-4-apps-with-protractorjs-jasmine-fcf1dd9524d5 {{https://lh6.googleusercontent.com/-57e_I3NlcRQ/VTLHygh_5_I/AAAAAAAACKo/kLsPoEw5CPI/w1024-h768-no/Protractor.jpg}} ===== UI Tests ===== ====== package.json ====== NPM dependency configs. { "name": "ui", "version": "1.0.0", "description": "This is a reference implementation of the Selenium test using javascript.", "main": "conf.js", "directories": { "test": "test" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "axios": "0.19.0", "dotenv": "8.1.0", "jasmine-allure-reporter": "^0.2.3", "protractor": "^5.4.4", "protractor-jasmine2-html-reporter": "0.0.7", "proxy-agent": "3.1.0", "request": "2.88.0", "request-promise": "^4.2.4" }, "devDependencies": { "jasmine-reporters": "^2.0.0" } } ====== Execution script ====== This script sets the environment variables, which then are passed into the config files and then may be used in the tests. if [ $# -eq 0 ] then echo "Please provide the environment: dev or stage" exit 1 fi #update IDs prior to processing Spec if [ $1 == 'stage' ] then export APIURL=my.api.com export SPACE_NAME="1.001" export BUILDINGIDB=03fjvA5B1CWOG33uprLUQT export SPACE_ISPARTOF=b5c703a7-627d-4562-ba2c-6399557c670d export DEVICE_NAME="Sensor_block:T&LQ:1138260" export DEVICE_SOURCE="3TYhTs\$S924vrYvWDC_1_z" export DEVICE_TAG=air export DEVICE_ISLOCATEDIN=233ffa56-c569-4ece-8781-23e021a8d990 export EQUIPMENT_NAME="Sensor_block:T&LQ:1138260" export EQUIPMENT_SOURCE="3TYhTs\$S924vrYvWDC_1_z" export EQUIPMENT_TAG=air export EQUIPMENT_ISLOCATEDIN=233ffa56-c569-4ece-8781-23e021a8d990 export TEST_ID=7890 export FILE_ID=42be5ad2-fb95-4a3b-b4b9-c1a87699b711 elif [ $1 == 'dev' ] then export APIURL=my.api.com export FLOOR_NAME=1OG export SPACE_NAME="1.001" export BUILDINGIDB=03fjvA5B1CWOG33uprLUQT export SPACE_ISPARTOF=6bfed7de-ccbc-4780-b834-5d8cbf73560f export DEVICE_NAME="Sensor_block:T&LQ:1138260" export DEVICE_SOURCE="3TYhTs\$S924vrYvWDC_1_z" export DEVICE_TAG=air export DEVICE_ISLOCATEDIN=37124033-c860-43d0-b468-92b58198fbcb export EQUIPMENT_NAME="Sensor_block:T&LQ:1138260" export EQUIPMENT_SOURCE="3TYhTs\$S924vrYvWDC_1_z" export EQUIPMENT_TAG=air export EQUIPMENT_ISLOCATEDIN=37124033-c860-43d0-b468-92b58198fbcb export TEST_ID=1234 export FILE_ID=2f6a1ae7-6a88-41a8-b2ba-bbf6f06ccf63 fi export TARGETAWSACCOUNT=$1 export TOKEN_ENDPOINT=https://myoauthserver.com/oauth/token export TOKEN_AUDIENCE=https://api.myapplication.com/ export TOKEN_DEFAULT=$(node createToken.js clientDefault) echo $TOKEN_DEFAULT export TOKEN_ALICE=$(node createToken.js clientAlice) echo $TOKEN_ALICE export TOKEN_BOB=$(node createToken.js clientBob) echo $TOKEN_BOB export TOKEN_AUTH=$(node createTokenAuth.js) echo $TOKEN_AUTH echo $API_URL export LOG_REQUESTS=true protractor test_config.js --suite $TARGETAWSACCOUNT ##protractor test_config.js ====== Configs ====== To configure the protractor you will need the configs === config.js === The file where the environment variables are injected into the JS require('dotenv').config(); module.exports = { seleniumAddress: process.env.SELENIUM_ADDRESS, issuer:{ endpoint: process.env.TOKEN_ENDPOINT, audience: process.env.TOKEN_AUDIENCE, audience_auth: process.env.AUDIENCE_AUTH }, params: { apiUrl: process.env.APIURL, buildingIdB: process.env.BUILDINGIDB, floorName: process.env.FLOOR_NAME, spaceName: process.env.SPACE_NAME, spaceSource: process.env.SPACE_SOURCE, spaceIsPartOf: process.env.SPACE_ISPARTOF, deviceName: process.env.DEVICE_NAME, deviceSource: process.env.DEVICE_SOURCE, deviceTag: process.env.DEVICE_TAG, deviceIsLocatedIn: process.env.DEVICE_ISLOCATEDIN, equipName: process.env.EQUIPMENT_NAME, equipSource: process.env.EQUIPMENT_SOURCE, equipTag: process.env.EQUIPMENT_TAG, equipIsLocatedIn: process.env.EQUIPMENT_ISLOCATEDIN, testID: process.env.TEST_ID, fileID: process.env.FILE_ID }, clientDefault: { clientId: process.env.CLIENT_ID, clientSecret: process.env.CLIENT_SECRET }, clientAlice: { clientId: process.env.ALICE_CLIENT_ID, clientSecret: process.env.ALICE_CLIENT_SECRET }, clientBob: { clientId: process.env.BOB_CLIENT_ID, clientSecret: process.env.BOB_CLIENT_SECRET }, clientAuth: { clientId: process.env.CLIENT_ID_AUTH, clientSecret: process.env.CLIENT_SECRET_AUTH }, token:{ default: process.env.TOKEN_DEFAULT, alice: process.env.TOKEN_ALICE, bob: process.env.TOKEN_BOB, auth: process.env.TOKEN_AUTH }, target:{ url: process.env.URL, auth_url: process.env.API_AUTH_URL } } ====== test_config.js ====== This is the configuration file used by protractor for managing any config parameter used globally within the web application. Uses the config.js file require('dotenv').config(); let options = require("./config"); var Jasmine2HtmlReporter = require('protractor-jasmine2-html-reporter'); exports.config = { framework: 'jasmine', seleniumAddress: options.seleniumAddress, //specs is used for when calling protractor without passing suites to run specs: ['spec/API_Widgets_tests.js', 'spec/Functional_tests.js', 'spec/API_CRUD_tests.js', 'spec/Negative_tests.js', 'spec/Filters_tests.js', 'spec/Negative_Filters_tests.js', 'spec/UI_tests_Main.js', 'spec/UI_tests.js', 'spec/UI_tests_files.js', 'spec/UI_tests_NavVis', 'spec/Auth_UI_tests.js'], //'spec/UI_tests_NavVis.js'], // //'spec/UI_tests_api_reference.js'], //specs: ['spec/API_CRUD_tests.js'], //Suites defined to run tests on Dev or Stage suites: { //dev: 'spec/*.js', // dev: ['spec/Functional_tests.js', // 'spec/Negative_tests.js', // 'spec/Filters_tests.js', // 'spec/Negative_Filters_tests.js', // // 'spec/UI_tests.js', // // 'spec/UI_tests_files.js', // // 'spec/UI_tests_Main.js', // // 'spec/UI_tests_template.js', // 'spec/API_Widgets_tests.js', // 'spec/API_CRUD_tests.js', // 'spec/Auth_UI_tests.js'], dev: ['spec/Auth_UI_tests.js'], // stage: ['spec/API_CRUD_tests.js', // 'spec/Negative_tests.js', // 'spec/Filters_tests.js', // 'spec/Negative_Filters_tests.js', // 'spec/API_Widgets_tests.js', // 'spec/UI_tests.js', // 'spec/UI_tests_files.js', // 'spec/API_CRUD_tests.js', // 'spec/UI_tests_Main.js', // 'spec/Auth_UI_tests.js'] stage: ['spec/Auth_UI_tests.js'] }, onPrepare: function () { browser.driver.manage().window().maximize(); jasmine.getEnv().addReporter(new Jasmine2HtmlReporter({ savePath: './test/reports/', screenshotsFolder: 'images', takeScreenshots: true, takeScreenshotsOnlyOnFailures: true, fixedScreenshotName: true, showPassed: false, filePrefix: 'SeleniumReport' // consolidate: false, // consolidateAll: false })); var AllureReporter = require('./node_modules/jasmine-allure-reporter'); jasmine.getEnv().addReporter(new AllureReporter({ resultsDir: 'test/allure-results/' })); var jasmineReporters = require('./node_modules/jasmine-reporters'); jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({ consolidateAll: true, savePath: 'test/reports', filePrefix: 'xmloutput' }) ) }, ignoreUncaughtExceptions: true, capabilities: { browserName: 'chrome', noGlobals: false, binary: 'C:/Program Files/ChromePortable/App/Chrome-bin/chrome.exe', //shardTestFiles: true, //maxInstances:7, chromeOptions: { useAutomationExtension: false, args: ["--headless", "--disable-gpu", "--disable-browser-side-navigation", "--disable-infobars", "--no-sandbox", "--window-size=1200,900"] // args: [ "--window-size=1400,900" ] } }, // capabilities: { // browserName: 'firefox', // 'moz:firefoxOptions': { // args: ['--verbose'], // binary: 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe' // //Provide binary location to avoid potential binary not found errors // //Need to start cmd via admin mode to avoid permission error // } // }, // capabilities: { // browserName: 'chrome', // noGlobals: false, // //shardTestFiles: true, // //maxInstances:7, // chromeOptions: { // useAutomationExtension: false, // args: ["--headless", // "--disable-gpu", // "--disable-browser-side-navigation", // "--disable-infobars", // "--no-sandbox", // "--window-size=1200,900"] // // args: [ "--window-size=1400,900" ] // } // }, // TODO: Initial work proves multi browser testing works. // multiCapabilities: [ // {'browserName': 'chrome', // 'chromeOptions': { // 'args': ['disable-infobars'] // } // }, // {'browserName': 'firefox', // 'moz:firefoxOptions': { // 'args': ['--safe-mode'] // } // } // ], // Options to be passed to Jasmine. jasmineNodeOpts: { defaultTimeoutInterval: 90000, //increased to 30 seconds }, params: { gWidgetID: 'empty', gCampusID: 'empty' } } ====== Example test ====== In the test the injected environment variables can be retireved via **config.params** Example: config.params.apiUrl require('dotenv').config(); var config = require('../lib/config'); var common = require('../lib/common'); const { element, browser } = require('protractor'); var EC = protractor.ExpectedConditions; describe('UI Tests - Files', function() { //Initialization of test case common.SetupInitialize("UI_tests_files.js"); //Login, Navigate to Building B files, validate that it loads it('TCER_ID-195611: Building B - Loads files', function () { apiUrl = config.params.apiUrl; var fPlans = element.all(by.cssContainingText('span', '2D Plans')).first(); var fsvg = element.all(by.cssContainingText('td', '.svg')).first(); var fThisIs = element.all(by.cssContainingText('td', 'This is a')).first(); browser.get(apiUrl + 'app/building/' + config.params.buildingIdB + '/files'); browser.wait(EC.visibilityOf(fPlans, 10000)); fPlans.click(); browser.wait(EC.visibilityOf(fsvg, 9000)); expect(fsvg).not.toBe(null); browser.wait(EC.visibilityOf(fThisIs, 15000)); expect(fThisIs).not.toBe(null); }); /* * Confirm details content is present and viable for ifc file * */ it('Building B - Details content is present',() => { element.all(by.cssContainingText('td', '.svg')).first().click(); browser.sleep(1000); browser.wait(EC.visibilityOf(element.all(by.css('.marengo-double-left')).first(), 15000)); element.all(by.css('.marengo-double-left')).first().click(); var detailsDrawer = element(by.css('.right-drawer-border.float-left')); expect(detailsDrawer.isPresent()).toBe(true); browser.sleep(1000); var filterBox = element(by.css('.filter-box')); browser.wait(EC.visibilityOf(filterBox),15000); expect(filterBox.isPresent()).toBe(true); expect(filterBox.getText()).toBe('System generated floorplan'); expect(element(by.css('.img-thumbnail')).isPresent()).toBe(true); var labels = element.all(by.css('.col-form-label')); var texts = element.all(by.css('.form-text')); expect(labels.get(2).getText()).toBe('Last update'); expect(labels.get(3).getText()).toBe('Updated By'); expect(labels.get(4).getText()).toBe('Size'); expect(labels.get(5).getText()).toBe('Version'); expect(labels.get(6).getText()).toBe('Source IFC:'); //expect(texts.get(5).getText()).toContain('buildingB.ifc'); <- issues on dev with name of file element(by.css('.marengo-double-right')).click(); browser.sleep(1000); element(by.cssContainingText('.files-breadcrumb', 'Building Files')).click(); browser.sleep(3000); var columns = element.all(by.css('.ui-sortable-column')); browser.wait(EC.visibilityOf(columns.get(0)),9000); columns.get(0).click(); expect(columns.get(0).isPresent()).toBe(true); }); /* * IFC that is source for should not be able to be deleted. * */ it('Building B - check ifc delete option', function() { browser.sleep(3000); var ifcFile = element(by.cssContainingText('td', '.ifc')); browser.wait(EC.visibilityOf(ifcFile),15000); ifcFile.click(); browser.sleep(4000); element(by.cssContainingText('.nav-item-title', 'More')).click(); browser.wait(EC.presenceOf(element(by.css('.navigator-delete')) ),17000); //dropdown-item-icon navigator-delete ng-star-inserted browser.sleep(3500); expect(element(by.cssContainingText('.dropdown-item.disabled', 'Delete')).isPresent()).toBe(true); }); /* * Renaming of building files * Ensure that file name changes are propogated through both rename option and edit option * */ describe('Building B - Rename functions', function(){ it ('Building B - rename file via More Rename button', function(){ var ifcFile = element(by.cssContainingText('td', '.ifc')); browser.wait(EC.visibilityOf(ifcFile),15000); ifcFile.click(); element(by.cssContainingText('.nav-item-title', 'More')).click(); element(by.cssContainingText('.dropdown-item-text', 'Rename')).click(); var displayName = element.all(by.css('input[name="displayName"]')).first(); var btnPrimary = element(by.css('.btn-primary')); browser.wait(EC.visibilityOf(displayName, 10000)); displayName.clear(); displayName.sendKeys('buildingB1'); btnPrimary.click(); browser.sleep(1000); browser.wait(EC.visibilityOf(element(by.cssContainingText('.toast-message', 'Rename successful')), 15000)); browser.wait(EC.visibilityOf(element(by.cssContainingText('td', 'buildingB1.ifc')), 15000)); expect(ifcFile.getText()).toBe('buildingB1.ifc'); }); it ('Building B - rename file back via More Rename button', function(){ browser.sleep(1000); var displayName = element.all(by.css('input[name="displayName"]')).first(); var btnPrimary = element(by.css('.btn-primary')); var ifcFile = element(by.cssContainingText('td', '.ifc')); element(by.cssContainingText('.nav-item-title', 'More')).click(); element(by.cssContainingText('.dropdown-item-text', 'Rename')).click(); browser.wait(EC.visibilityOf(displayName, 3000)); displayName.clear(); displayName.sendKeys('buildingB'); //browser.wait(EC.invisibilityOf(element.all(by.css('.toast-message.ng-star-inserted')).first()),15000); browser.wait(EC.visibilityOf(element(by.cssContainingText('.toast-message', 'Rename successful')), 15000)); btnPrimary.click(); browser.wait(EC.visibilityOf(element(by.cssContainingText('td', 'buildingB.ifc')), 15000)); expect(ifcFile.getText()).toBe('buildingB.ifc'); browser.sleep(1000); }); it ('Building B - rename file via More Edit button', function(){ browser.sleep(1000); var displayName = element.all(by.css('input[name="displayName"]')).first(); var btnPrimary = element(by.css('.btn-primary')); var ifcFile = element(by.cssContainingText('td', '.ifc')); browser.wait(EC.visibilityOf(element(by.cssContainingText('.nav-item-title', 'More')), 15000)); element(by.cssContainingText('.nav-item-title', 'More')).click(); element(by.cssContainingText('.dropdown-item-text', 'Edit')).click(); browser.wait(EC.visibilityOf(displayName, 3000)); displayName.clear(); displayName.sendKeys('buildingB1'); displayName.click(); browser.sleep(5000); browser.wait(EC.visibilityOf(btnPrimary),14000); btnPrimary.click(); browser.wait(EC.visibilityOf(element.all(by.cssContainingText('.col', 'buildingB1.ifc')).first()),25000); var arrowRight = element(by.css(".marengo-double-right")); expect(ifcFile.getText()).toBe('buildingB1.ifc'); }); it ('Building B - rename file back from More Edit button', function(){ browser.sleep(2000); var displayName = element.all(by.css('input[name="displayName"]')).first(); var btnPrimary = element(by.css('.btn-primary')); var ifcFile = element(by.cssContainingText('td', '.ifc')); element(by.cssContainingText('.nav-item-title', 'More')).click(); browser.wait(EC.visibilityOf(element(by.cssContainingText('.dropdown-item-text', 'Edit'))),15000); element(by.cssContainingText('.dropdown-item-text', 'Edit')).click(); browser.sleep(1000); browser.wait(EC.visibilityOf(displayName, 7000)); displayName.clear(); displayName.sendKeys('buildingB'); browser.sleep(1000); expect(btnPrimary.isEnabled()).toBe(true); btnPrimary.click(); browser.wait(EC.visibilityOf(element.all(by.cssContainingText('.col', 'buildingB.ifc')).first()),25000); //var arrowRight = element(by.css(".marengo-double-right")); //arrowRight.click(); }); it ('Building B - check file name is back to default text', function(){ var ifcFile = element(by.cssContainingText('td', '.ifc')); var arrowRight = element(by.css(".marengo-double-right")); arrowRight.isPresent().then(function(result) { if (result) { browser.wait(EC.visibilityOf(arrowRight),25000); arrowRight.click(); browser.wait(EC.visibilityOf(element(by.cssContainingText('td', 'buildingB.ifc')), 15000)); expect(ifcFile.getText()).toBe('buildingB.ifc'); browser.sleep(1000); } }); }); /* Neg case - Long building names * Ensure that building names past api allowable length result in an error * */ it('Building B - negative - rename file - check toast message', function() { console.log('Building B - negative - rename file - check toast message'); var ifcFile = element(by.cssContainingText('td', '.ifc')); var toastMessage = element(by.cssContainingText('.toast-message', 'Unable to update file information')); browser.wait(EC.visibilityOf(ifcFile),10000); ifcFile.click(); element(by.cssContainingText('.nav-item-title', 'More')).click(); element(by.cssContainingText('.dropdown-item-text', 'Edit')).click(); browser.sleep(1500); var displayName = element.all(by.css('input[name="displayName"]')).first(); browser.wait(EC.visibilityOf(displayName, 9000)); displayName.sendKeys('MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMHMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM'); //change file name to a value we know will fail browser.wait(EC.visibilityOf(element(by.css('.btn-primary'))),25000); element(by.css('.btn-primary')).click(); //TODO:forced to add .sleep method below due to high delay in response from application browser.sleep(4000); browser.wait(EC.visibilityOf(toastMessage, 35000)); expect(toastMessage.getText()).toBe('Unable to update file information'); toastMessage.click(); //close toast message }); it('Building B - negative - rename file - verify default name', function() { var ifcFile = element(by.cssContainingText('td', '.ifc')); var arrowRight = element(by.css(".marengo-double-right")); browser.wait(EC.visibilityOf(arrowRight),5000); arrowRight.click(); // close side menu browser.wait(EC.visibilityOf(ifcFile),20000); expect(ifcFile.getText()).toBe('buildingB.ifc'); }); it('Building B - add file description', function() { element(by.cssContainingText('.nav-item-title', 'More')).click(); element(by.cssContainingText('.dropdown-item-text', 'Edit')).click(); browser.sleep(1500); var txtDescription = element(by.name('description')); browser.wait(EC.visibilityOf(txtDescription),7000); txtDescription.clear(); txtDescription.sendKeys('description text'); element(by.cssContainingText('.btn-primary', 'Save')).click(); browser.wait(EC.visibilityOf(element(by.linkText('History'))), 69000); expect(element(by.id('description')).getText()).toBe('description text'); browser.sleep(3000); }); it('Building B - remove file description', function() { element(by.cssContainingText('.nav-item-title', 'More')).click(); element(by.cssContainingText('.dropdown-item-text', 'Edit')).click(); browser.sleep(1500); var txtDescription = element(by.name('description')); browser.wait(EC.visibilityOf(txtDescription),7000); txtDescription.clear(); txtDescription.sendKeys('a'); txtDescription.sendKeys(protractor.Key.BACK_SPACE); txtDescription.clear(); element(by.cssContainingText('.btn-primary', 'Save')).click(); browser.wait(EC.visibilityOf(element(by.linkText('History'))), 39000); expect(element(by.id('description')).getText()).toBe(''); expect(element(by.css('.form-text.text-muted')).getText()).toBe('No description yet'); }); }); /* * Create Folders * From Root directory * Create folder 1 and folder 2 , via the folder creation menu * assert that folders exist in table and in side bar * */ describe('Building B - Create functions', function(){ it ('Building B - create folders', function(){ browser.sleep(3000); var folder1 = element(by.cssContainingText('td', 'folder1')); var folder2 = element(by.cssContainingText('td', 'folder2')); var btnNew = element(by.cssContainingText('.nav-item-title', 'New')); browser.wait(EC.visibilityOf(btnNew),20000); btnNew.click(); element(by.cssContainingText('.dropdown-item-text', 'Create New Folder')).click(); browser.wait(EC.visibilityOf(element(by.css('input[name="folderName"]'))),6500); element(by.css('input[name="folderName"]')).sendKeys('folder1'); element(by.cssContainingText('.btn-primary', 'Create')).click(); browser.sleep(2000); browser.wait(EC.visibilityOf(folder1) ,20000); expect(folder1.isPresent()).toBe(true); element(by.cssContainingText('.nav-item-title', 'New')).click(); element(by.cssContainingText('.dropdown-item-text', 'Create New Folder')).click(); browser.wait(EC.visibilityOf(element(by.css('input[name="folderName"]'))),4000); element(by.css('input[name="folderName"]')).sendKeys('folder2'); browser.wait(EC.visibilityOf(element.all(by.cssContainingText('.btn-primary', 'Create')).first(), 6000)); element(by.cssContainingText('.btn-primary', 'Create')).click(); browser.sleep(2000); browser.wait(EC.visibilityOf(folder2), 20000); //check folder is in table expect(folder2.isPresent()).toBe(true); // check folder is in sidebar expect(element(by.cssContainingText('span', 'folder2')).isPresent()).toBe(true); }); /* * Trigger navigation via folder icon click * get list of folders * click first folder ( should be 2D Floorplans) * confirm we were navigated by folder contents * */ it('Building B - navigate through table folder icon click', function() { var folders = $$('a.table-folder-icon'); var fPlans = element.all(by.cssContainingText('span', '2D Plans')).first(); // There should be three folders currently in the table expect(folders.count()).toBe(3); // navigate to 2D Floorplans folder through click on the folder icon fPlans.click(); //folders.get(0).click(); browser.wait(EC.visibilityOf(element.all(by.cssContainingText('td', '.svg')).first(), 10000)); // expect we have loaded the contents of the folder expect(element.all(by.cssContainingText('td', '.svg'))).not.toBe(null); }); /* * Trigger navigation via breadcrumb * Analyze bread crumbs in current path ( should be started in 2d floor plans folder) * click breadcrumb to go to building files * confirm we were navigated by folder contents * confirm breadcrumbs were rebuilt properly. * */ it ('Building B - navigate through breadcrumbs', function() { // get list of breadcrumbs, in the current state there should be 2 var crumbs = $$('.files-breadcrumb'); expect(crumbs.count()).toBe(2); expect(crumbs.get(0).getText()).toBe('Building Files'); expect(crumbs.get(1).getText()).toContain('\/\n' + 'Generated 2D Plans'); element(by.cssContainingText('.files-breadcrumb', 'Building Files')).click(); //Expect navigation back to root folder - Table browser.wait(EC.visibilityOf(element.all(by.cssContainingText('td', '.ifc')).first(), 10000)); expect(element(by.cssContainingText('td', '.ifc')).isPresent()).toBe(true); // Expect crumbs to be 1 long after navigation var newCrumbs = $$('.files-breadcrumb'); expect(newCrumbs.count()).toBe(1); expect(newCrumbs.get(0).getText()).toBe('Building Files'); }); /** * Creation of a sub-folder * select folder 1, choose create new folder * interact with folder modal , provide name and confirmation * after- confirm that the folder exists **/ it('Building B - Create Folder inside folder - from within folder', function() { // select folder 1 and click element.all(by.cssContainingText('span', 'folder1')).first().click(); browser.sleep(1000); // select create new folder element(by.cssContainingText('.nav-item-title', 'New')).click(); element(by.cssContainingText('.dropdown-item-text', 'Create New Folder')).click(); browser.sleep(1000); element(by.css('input[name="folderName"]')).sendKeys('folderInsideFolder'); browser.sleep(1000); element(by.cssContainingText('.btn-primary', 'Create')).click(); browser.sleep(2000); // Folder should be created check for folder presence in folder 1 var folderInsideFolder = element.all(by.css('td.table-text-truncate')).first(); browser.wait(EC.visibilityOf(folderInsideFolder, 10000)); expect(folderInsideFolder.getText()).toBe('folderInsideFolder'); element.all(by.cssContainingText('span', 'Building Files')).first().click(); }); }); describe('Building B - Upload/Copy/Move functions',function(){ /** * disabling this test until we solve the challenge of uploading files in the pipeline * Navigate to folder 1 clicks 'upload' option, select ifc file, checks if 'upload' button is enabled after * selecting a file, clicks 'upload', then uploads another file (text file) * Check for file presence * */ if(config.params.targetAwsAccount =="dev" ){ xit('upload ifc file to folder', function() { var path = require('path'); var remote = require('selenium-webdriver/remote'); browser.setFileDetector(new remote.FileDetector()); element.all(by.cssContainingText('span', 'folder1')).first().click(); browser.sleep(2000); var textFileToUpload = './extras/testinput.txt'; var ifcFileToUpload = './extras/working.ifc'; absolutePath = path.resolve(__dirname, textFileToUpload); absolutePath2 = path.resolve(__dirname, ifcFileToUpload); element(by.cssContainingText('.nav-item-title', 'New')).click(); element(by.cssContainingText('.dropdown-item-text', 'Upload')).click(); browser.sleep(1000); browser.wait(EC.visibilityOf(element(by.css('input[type="file"]'))) ,5000); element(by.css('input[type="file"]')).sendKeys(absolutePath2); browser.sleep(1000); var uploadButton = element(by.css('.btn-primary')); expect(uploadButton.isEnabled()).toBe(true); uploadButton.click(); browser.wait(EC.visibilityOf($('.toast-message')),10000); expect($('.toast-message').getText()).toBe('File working.ifc uploaded'); browser.wait(EC.invisibilityOf($('.toast-message')),10000); //browser.wait(EC.visibilityOf(element(by.cssContainingText('.toast-message', 'File working.ifc uploaded')), 10000)); //browser.wait(EC.invisibilityOf(element(by.cssContainingText('.toast-message', 'File working.ifc uploaded')), 10000)); }); xit('upload txt file to folder', function() { var path = require('path'); var remote = require('selenium-webdriver/remote'); browser.setFileDetector(new remote.FileDetector()); var uploadButton = element(by.css('.btn-primary')); var textFileToUpload = './extras/testinput.txt'; var ifcFileToUpload = './extras/working.ifc'; absolutePath = path.resolve(__dirname, textFileToUpload); absolutePath2 = path.resolve(__dirname, ifcFileToUpload); element(by.cssContainingText('.nav-item-title', 'New')).click(); element(by.cssContainingText('.dropdown-item-text', 'Upload')).click(); browser.sleep(1000); browser.wait(EC.visibilityOf(element(by.css('input[type="file"]'))) ,5000); element(by.css('input[type="file"]')).sendKeys(absolutePath); browser.sleep(1000); uploadButton.click(); browser.wait(EC.visibilityOf($('.toast-message')),10000); expect($('.toast-message').getText()).toBe('File testinput.txt uploaded'); browser.wait(EC.invisibilityOf($('.toast-message')),10000); //expect($('.toast-message').getText()).toBe('File textinput.txt uploaded'); //browser.wait(EC.visibilityOf(element(by.cssContainingText('.toast-message', 'File testinput.txt uploaded')), 10000)); console.log("files were uploaded"); }); }; /* * Currently working test disabled until clean up implemented in next test * */ it('Building B - copy file', function() { element.all(by.cssContainingText('span', 'Building Files')).first().click(); browser.sleep(1000); var ifcFile = element.all(by.cssContainingText('td', '.ifc')).first(); browser.wait(EC.visibilityOf(ifcFile, 10000)); ifcFile.click(); browser.wait(EC.visibilityOf(element.all(by.cssContainingText('.nav-item-title', 'More')).first(), 1000)); element(by.cssContainingText('.nav-item-title', 'More')).click(); //note: using a browser.wait here instead of .sleep causes timeout. browser.sleep(1000); var cutButton = element(by.css('.marengo-copy')); cutButton.click(); browser.wait(EC.visibilityOf(element.all(by.cssContainingText('td', 'Copy of buildingB.ifc')).first(), 1000)); browser.wait(EC.visibilityOf(element.all(by.cssContainingText('td', '.ifc')).first(), 1000)); let ifcFiles = element.all(by.cssContainingText('td', '.ifc')); expect(ifcFiles.count()).toBe(2); browser.sleep(1000); }); /* * Inprogress soec * */ it('Building B - move file', function() { apiUrl = config.params.apiUrl; browser.get(apiUrl + 'app/building/' + config.params.buildingIdB +'/files'); browser.sleep(5000); let ifcFile = element(by.cssContainingText('td', 'Copy of')); expect(ifcFile).not.toBe(null); browser.wait(EC.visibilityOf(ifcFile, 14000)); ifcFile.click(); browser.wait(EC.visibilityOf(element(by.cssContainingText('.nav-item-title', 'More')), 14000)); element(by.cssContainingText('.nav-item-title', 'More')).click(); //note: using a browser.wait here instead of .sleep causes timeout. var moveButton = element(by.cssContainingText('.dropdown-item-text', 'Move to')); expect(moveButton).not.toBe(null); moveButton.click(); // Wait for modal here. browser.wait(EC.visibilityOf(element.all(by.cssContainingText('div', 'Move Files to')).first(), 15000)); browser.wait(EC.visibilityOf(element(by.cssContainingText('.modal-tree', 'folder1')), 15000)); // wait for tree content to load - need a better check let target = element.all(by.cssContainingText('.modal-tree', 'folder1')).last(); target.click(); let moveBtn = element.all(by.cssContainingText('button', 'Move')); moveBtn.click(); //browser.sleep(10000); browser.wait(EC.visibilityOf(element(by.cssContainingText('.toast-message', 'Move successful')), 15000)); browser.wait(EC.invisibilityOf(element(by.cssContainingText('td', 'Copy of')), 15000)); browser.sleep(2000); //Verify that item is not in current folder var detailsDrawer = element(by.cssContainingText('td', 'Copy of')); expect(detailsDrawer.isPresent()).toBe(false); }); it('Building B - move file - verify move', function() { let ifcFile = element(by.cssContainingText('td', 'Copy of')); let folder1 = element.all(by.cssContainingText('span', 'folder1')).first(); //navigate to folder 1 and validate it is there. browser.wait(EC.invisibilityOf(ifcFile),9000); browser.wait(EC.visibilityOf(folder1, 10000)); folder1.click(); browser.wait(EC.visibilityOf(ifcFile, 10000)); expect(ifcFile.isPresent()).toBe(true); //go back to root for next test element.all(by.cssContainingText('span', 'Building Files')).first().click(); }); /* * delete of Folders * clicks folder 2, and deletes. * Clicks folders 1 and deletes * * */ it('Building B - delete folder', function() { browser.sleep(1000); browser.wait(EC.visibilityOf(element(by.cssContainingText('td', 'folder2')), 5000)); var folder = element(by.cssContainingText('td', 'folder2')); folder.click(); element(by.cssContainingText('.nav-item-title', 'More')).click(); var deleteButton = element(by.css('.navigator-delete')); deleteButton.click(); browser.sleep(1000); element(by.css('.btn-danger')).click(); browser.wait(EC.visibilityOf(element(by.cssContainingText('.toast-message', 'Item deleted')), 5000)); browser.wait(EC.invisibilityOf(element(by.cssContainingText('.toast-message', 'Item deleted')), 5000)); browser.sleep(2000); expect(folder.isPresent()).toBe(false); browser.wait(EC.visibilityOf(element(by.cssContainingText('td', 'folder1')), 5000)); folder = element(by.cssContainingText('td', 'folder1')); folder.click(); element(by.cssContainingText('.nav-item-title', 'More')).click(); deleteButton = element(by.css('.navigator-delete')); deleteButton.click(); browser.sleep(1000); element(by.css('.btn-danger')).click(); browser.wait(EC.visibilityOf(element(by.cssContainingText('.toast-message', 'Item deleted')), 5000)); browser.wait(EC.visibilityOf(element(by.css('.ui-table-loading')), 5000)); let loader = element(by.css('.ui-table-loading')); browser.wait(EC.not(EC.presenceOf(loader))); browser.sleep(1000); expect(folder.isPresent()).toBe(false); }); /* * upload without file path provided - * clicks 'files' button, clicks 'upload' option, opens new window, checks if 'upload' button is disabled * when no file is selected and then clicks 'cancel' button * */ it ('wont allow upload without file path provided', function() { element(by.cssContainingText('.nav-item-title', 'New')).click(); element(by.cssContainingText('.dropdown-item-text', 'Upload')).click(); //browser.sleep(1000); var cancelButton = element(by.css('.btn-link')); var uploadButton = element(by.css('.btn-primary')); browser.wait(EC.visibilityOf(cancelButton),5000); expect(uploadButton.isEnabled()).toBe(false); expect(cancelButton.isPresent()).toBe(true); cancelButton.click(); browser.sleep(1000); expect(cancelButton.isPresent()).toBe(false); }); }); /* * Check files details - **Currently disabled as uploads not working on pipeline. * first clicks ifc file, checks if drawer shows up, changes description of file, downloads file, clicks * 'history' option, 'creation' option, then clicks 'create' option and waits until * message banner shows up at the bottom of the page, then clicks text file, again checks if drawer is present, * clicks 'history' option and since it is not an ifc file, * 'creation' option should not be there, so it checks its presence * */ if(config.params.targetAwsAccount =="dev" ){ xit('check file details', function() { browser.sleep(2000); browser.wait(EC.visibilityOf(element(by.cssContainingText('td', '.ifc'))),5000); element(by.cssContainingText('td', '.ifc')).click(); browser.sleep(1000); element.all(by.css('.marengo-double-left')).first().click(); var detailsDrawer = element(by.css('.right-drawer-border')); expect(detailsDrawer.isPresent()).toBe(true); browser.sleep(1000); var downloadButton = element(by.css('i[title="Download File"]')); browser.wait(EC.visibilityOf(downloadButton),5000); expect(downloadButton.isEnabled()).toBe(true); downloadButton.click(); browser.sleep(1000); element(by.css('i[title="Edit file information"]')).click(); browser.sleep(1000); var labels = element.all(by.css('.col-form-label')); expect(labels.get(1).getText()).toBe('Description'); expect(labels.get(2).getText()).toBe('Last update'); expect(labels.get(3).getText()).toBe('Updated By'); expect(labels.get(4).getText()).toBe('Size'); expect(labels.get(5).getText()).toBe('Version'); expect(labels.get(6).getText()).toBe('Created'); var txtDescription = element(by.name('description')); txtDescription.clear(); txtDescription.sendKeys('ifc file'); element(by.cssContainingText('.btn-primary', 'Save')).click(); browser.wait(EC.visibilityOf(element(by.linkText('History'))), 5000); var historyButton = element(by.linkText('History')); var createButton = element(by.linkText('Creation')); expect(element(by.id('description')).getText()).toBe('ifc file'); expect(createButton.isPresent()).toBe(true); historyButton.click(); createButton.click(); element(by.cssContainingText('.nav-item-title', 'Title')).click(); browser.sleep(1500); var fileName = element(by.cssContainingText('.margin-top-offset', 'Selected IFC')); expect(fileName.getText()).toBe('Selected IFC: buildingB.ifc'); //click cancel button element(by.css('.btn.btn-link')).click(); browser.sleep(1500); element.all(by.css('.marengo-double-right')).first().click(); browser.sleep(3000); element(by.cssContainingText('.breadcrumb-item', 'Buildings')).click(); }); }; });