Skip to content

Commit

Permalink
FOGL-8062: Fledge e2e tests migrated to cypress from protractor (#323)
Browse files Browse the repository at this point in the history
* e2e tests migrated from protractor to cypress

Signed-off-by: Praveen Garg <[email protected]>
Signed-off-by: hemant <[email protected]>
Co-authored-by: Praveen Garg <[email protected]>
  • Loading branch information
hemantgarg923 and praveen-garg authored Sep 21, 2023
1 parent bfd556a commit 7e82423
Show file tree
Hide file tree
Showing 20 changed files with 1,216 additions and 1,046 deletions.
34 changes: 11 additions & 23 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,36 +128,24 @@
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
"src/tsconfig.spec.json",
"cypress/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"fledge-e2e": {
"root": "",
"sourceRoot": "",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "./protractor.conf.js",
"devServerTarget": "fledge:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"e2e": {
"builder": "@cypress/schematic:cypress",
"options": {
"tsConfig": [
"e2e/tsconfig.e2e.json"
],
"exclude": [
"**/node_modules/**"
]
"devServerTarget": "fledge:serve",
"headless": true
},
"configurations": {
"production": {
"devServerTarget": "fledge:serve:production"
}
}
}
}
Expand Down
22 changes: 22 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { defineConfig } from 'cypress'

export default defineConfig({
reporter: 'cypress-multi-reporters',
reporterOptions: {
configFile: 'reporter-config.json',
},
e2e: {
'baseUrl': 'http://localhost:4200',
supportFile: false,
specPattern: [
'./e2e/**/*.e2e-*.ts'
],
setupNodeEvents(on) {
require('cypress-mochawesome-reporter/plugin')(on);
},
},

viewportWidth: 1600,
viewportHeight: 900,
defaultCommandTimeout: 11000,
})
8 changes: 8 additions & 0 deletions cypress/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "../tsconfig.json",
"include": ["**/*.ts"],
"compilerOptions": {
"sourceMap": false,
"types": ["cypress"]
}
}
4 changes: 2 additions & 2 deletions deploy
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ CWARN="${CPFX}0;33m"

echo -e "${CWARN}This script is partially done, please track https://github.com/fledge/fledge-gui/issues/73 ${CRESET}"

compat_msg="This script is compatible with Linux (Ubuntu and Raspbian) Only!"
compat_msg="This script is compatible with Linux (Debian, Ubuntu and Raspberry Pi OS) Only!"

os=$(uname)
if [[ $os != "Linux" ]]; then
Expand All @@ -49,7 +49,7 @@ fi

if [ -f /etc/os-release ]; then
n=$(cat /etc/os-release | grep -w PRETTY_NAME | cut -d= -f2- | tr -d '"')
if [[ $n == *"Raspbian"* ]] || [[ $n == *"Ubuntu"* ]]; then
if [[ $n == *"Raspbian"* ]] || [[ $n == *"Debian"* ]] || [[ $n == *"Ubuntu"* ]] ; then
echo -e "${CINFO}${n} ${CRESET}"
else
echo -e "${CWARN}${n} ${CRESET}"
Expand Down
4 changes: 2 additions & 2 deletions docs/prerequisite-redhat.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@

## Prerequisite to setup Fledge UI Client on CentOS/RHEL 7
## Prerequisite to setup Fledge UI Client on CentOS Stream/RHEL

### Node

Install nodejs (LTS version)

```
$ yum install -y gcc-c++ make
$ curl -sL https://rpm.nodesource.com/setup_14.x | sudo -E bash -
$ curl -sL https://rpm.nodesource.com/setup_16.x | sudo -E bash -
$ sudo yum install nodejs
```

Expand Down
2 changes: 1 addition & 1 deletion docs/prerequisite-ubuntu.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Install nodejs (LTS version)

```
$ curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
$ curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
$ sudo apt-get install nodejs
```

Expand Down
94 changes: 38 additions & 56 deletions e2e/po/app.admin.ts
Original file line number Diff line number Diff line change
@@ -1,119 +1,101 @@
import { browser, by, element } from 'protractor';

export class AdminLogin {
EC = browser.ExpectedConditions;

login() {
browser.ignoreSynchronization = true;
element(by.css('app-login form div:nth-child(1) div input[name="username"]')).sendKeys('admin');
element(by.css('app-login form input[name="password"]')).sendKeys('fledge');
browser.sleep(1000);
element(by.css('app-login form button.is-info')).click();
cy.get('app-login form div:nth-child(1) div input[name="username"]').type('admin')
cy.get('app-login form input[name="password"]').type('fledge')
cy.wait(1000)
cy.get('app-login form button.is-info').click()
}

isUserManagementPresent() {
browser.sleep(2000);
return element(by.id('user-management')).isPresent();
cy.wait(2000)
cy.get('#user-management').should('be.visible')
}

navToUserManagement() {
browser.ignoreSynchronization = true;
return browser.get('/#/user-management');
return cy.visit('/#/user-management')
}

getUserManagementTabName() {
return cy.get('app-user-management header .tabs ul li:nth-child(1)').invoke('text')
}

getAllTabs() {
browser.ignoreSynchronization = true;
return element(by.css('app-user-management header .tabs ul')).getText();
getRoleTabName() {
return cy.get('app-user-management header .tabs ul li:nth-child(2)').invoke('text')
}

isAddUserPresent() {
browser.ignoreSynchronization = true;
return element(by.css('app-user-management header .tabs div')).getText();
return cy.get('app-user-management .add-btn').invoke('text')
}

getUserManagementColNames() {
browser.ignoreSynchronization = true;
return element(by.id('head')).getText();
return cy.get('#head').invoke('text')
}

gotoRoles() {
browser.ignoreSynchronization = true;
element(by.css('app-user-management header .tabs li:nth-child(2) a')).getText();
cy.get('app-user-management header .tabs ul li:nth-child(2)').click()
}

getRolesColNames() {
browser.ignoreSynchronization = true;
return element(by.css('app-user-management table thead')).getText();
return cy.get('app-user-management table thead').invoke('text')
}

navToProfile() {
browser.ignoreSynchronization = true;
element(by.css('#dropdown-box > div.dropdown-trigger > a')).click();
element(by.css('#dropdown-menu > div > a:nth-child(1)')).click();
browser.sleep(2000);
cy.get('#dropdown-box').invoke('mouseenter')
cy.get('#dropdown-menu').invoke('show')
cy.get('#dropdown-menu > div > a.user-content:nth-child(1)').click({ force: true })
cy.wait(2000)
}

profileTitle() {
browser.ignoreSynchronization = true;
return element(by.css('.card .card-header-title')).getText();
return cy.get('.card .card-header-title').invoke('text')
}

labelUsername() {
browser.ignoreSynchronization = true;
return element(by.css('#edit_profile > div:nth-child(1) > div > label')).getText();
return cy.get('#edit_profile > div:nth-child(2) > div > label').invoke('text')
}

labelRole() {
browser.ignoreSynchronization = true;
return element(by.css('#edit_profile > div:nth-child(2) > div > label')).getText();
return cy.get('#edit_profile > div:nth-child(3) > div > label').invoke('text')
}

isChangePassword() {
browser.ignoreSynchronization = true;
return element(by.css('#edit_profile > div:nth-child(3) > div > a')).getText();
return cy.get('#edit_profile > div:nth-child(5) > div > a:nth-child(1)').invoke('text')
}

isLogoutActiveSessionButton() {
browser.ignoreSynchronization = true;
return element(by.css('#edit_profile .button.is-warning')).getText();
return cy.get('#edit_profile > div:nth-child(5) > div > a:nth-child(2)').invoke('text')
}

changePassword() {
browser.ignoreSynchronization = true;
element(by.css('#edit_profile > div:nth-child(3) > div > a')).click();
cy.get('#edit_profile > div:nth-child(5) > div > a:nth-child(1)').click()
}

getInputTagCount() {
browser.ignoreSynchronization = true;
return element.all(by.css('#ngForm input')).count();
isInputTag() {
return cy.get('#ngForm input').should('be.visible')
}

isSaveButton() {
browser.ignoreSynchronization = true;
return element(by.id('update')).isDisplayed();
return cy.get('#update').should('be.visible')
}

closeModal() {
browser.ignoreSynchronization = true;
element(by.css('#user_profile_modal .delete')).click();
cy.get('#user_profile_modal .delete').click()
}

logout() {
browser.ignoreSynchronization = true;
element(by.css('#dropdown-box > div.dropdown-trigger > a')).click();
// wait
browser.wait(this.EC.visibilityOf(element(by.css('#dropdown-menu > div > a:nth-child(2)'))), 2000);
element(by.css('#dropdown-menu > div > a:nth-child(2)')).click();
browser.sleep(1000);
cy.wait(2000)
cy.get('#dropdown-box').invoke('mouseenter')
cy.get('#dropdown-menu').invoke('show')
cy.get('#dropdown-menu > div > a.user-content:nth-child(2)').click({ force: true })
cy.wait(1000)
}

loginPageInputTag() {
browser.ignoreSynchronization = true;
return element.all(by.css('app-login form input')).count();
cy.get('app-login form input').should('be.visible')
}

getLoginButton() {
browser.ignoreSynchronization = true;
return element(by.css('app-login form button.is-info')).getText();
return cy.get('app-login form button.is-info').invoke('text')
}
}
51 changes: 20 additions & 31 deletions e2e/po/app.filters.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import { browser, by, element, ExpectedConditions, promise } from 'protractor';

export class Filters {
DETERMINISTIC_WAIT = 3000; // in milliseconds
RETRY_ATTEMPTS = 5;
addFilterRetryAttempts = 5;
EC = browser.ExpectedConditions;

/**
* open filter wizard
*/
openFilterWizard() {
browser.ignoreSynchronization = true;
return element(by.css('.add-application a')).click();
return cy.get('.add-application a').click()
}

/**
Expand All @@ -22,46 +18,39 @@ export class Filters {
* @param {string} filter plugin name
*/
addFilter(filterName: string) {
browser.ignoreSynchronization = true;
this.waitForFilterPluginsToLoad(this.DETERMINISTIC_WAIT).then(() => {
browser.ignoreSynchronization = true;
element(by.name('type')).all(by.tagName('option'))
.then(options => {
options[0].click(); // select first plugin in select box
});
this.waitForFilterPluginsToLoad().then(() => {
// select first plugin in select box
cy.get('select').select(0)
// supply filter name
element(by.id('name')).sendKeys(filterName);
cy.get('#name').type(filterName)
// click next button twice
element(by.id('next')).click();
element(by.id('next')).click();
cy.get('#next').click()
cy.get('#next').click()
})
.catch((error) => {
if (this.addFilterRetryAttempts > 0) {
console.log('Retrying load filter plugin.');
this.addFilter(filterName);
} else {
console.log('Rejecting the promise after ' + this.RETRY_ATTEMPTS + ' attempts.');
return Promise.reject(error);
}
});
cy.on("fail", (error) => {
if (this.addFilterRetryAttempts > 0) {
console.log('Retrying load filter plugin.');
this.addFilter(filterName);
} else {
console.log('Rejecting the promise after ' + this.RETRY_ATTEMPTS + ' attempts.');
return Promise.reject(error);
}
});
this.addFilterRetryAttempts--;
}

/**
* Wait for filter plugin visibility
* @param timeOut wait time
*/
waitForFilterPluginsToLoad(timeOut?: number): promise.Promise<{}> {
const isDataVisible = ExpectedConditions.visibilityOf(element(by.name('type')).element(by.tagName('option')));
return browser.wait(ExpectedConditions.and(isDataVisible), timeOut);
waitForFilterPluginsToLoad() {
return cy.wait(this.DETERMINISTIC_WAIT).get('option').should('be.visible')
}

/**
* Get filter name
*/
getAddedFilterName() {
browser.ignoreSynchronization = true;
browser.wait(this.EC.visibilityOf(element(by.css('.accordion.card.cdk-drag'))), this.DETERMINISTIC_WAIT);
return element(by.css('.accordion.card.cdk-drag')).getText();
cy.wait(this.DETERMINISTIC_WAIT)
return cy.get('#list-item-0 .card-header-title').invoke('text')
}
}
Loading

0 comments on commit 7e82423

Please sign in to comment.