Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

# dependencies
/node_modules
/e2e/node_modules

# profiling files
chrome-profiler-events*.json
Expand Down
56 changes: 35 additions & 21 deletions e2e/protractor.conf.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,46 @@
// @ts-check
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts

const { SpecReporter } = require('jasmine-spec-reporter');

/**
* @type { import("protractor").Config }
*/
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
getPageTimeout: 60000,
capabilities: {
'browserName': 'chrome'
'browserName': 'chrome',
'chromeOptions': {
'args': [
'--start-maximized', // Uncomment to launch tests using the browser and comment the argument `properties` below
// '--headless',
// '--disable-gpu',
// '--window-size=1920,1080',
// '--no-sandbox',
// '--disable-dev-shm-usage'
]
}
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
baseUrl: 'localhost:4200',
specs: [
'src/feature/employee/employee.feature',
],
framework: 'custom',
frameworkPath: require.resolve('protractor-cucumber-framework'),
cucumberOpts: {
require: [
'src/step_definition/*.definitions.ts',
'src/hooks/generic.hooks.ts'
],
tags: '@Employee',
strict: true,
format: [
`json:reports/mryumul.json`,
],
dryRun: false,
compiler: []
},
params: {},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.json')
project: 'e2e/tsconfig.e2e.json'
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};
},
// ignoreUncaughtExceptions: true,
};
32 changes: 32 additions & 0 deletions e2e/src/feature/employee/employee.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@Employee
Feature: Employee
As a user
I should be able to create, read, update, and delete an Employee record

@Create
Scenario: Create an Employee record
Given I am on the dashboard page
When I "create" an employee record
Then I should see the success message "Success: Data has been added!"
And I should "see" the "created" employee record in the list

@Read
Scenario: Read Employee records
Given I am on the dashboard page
When I "read" an employee record
Then I should see the employee records in the list

@Update
Scenario: Update an Employee record
Given I am on the dashboard page
And There are existing employee records
When I "update" an employee record
Then I should see the success message "Success: Data has been updated!"
And I should "see" the "updated" employee record in the list

@Delete
Scenario: Delete an Employee record
Given I am on the dashboard page
And There are existing employee records
When I "delete" an employee record
Then I should "not see" the "deleted" employee record in the list
19 changes: 19 additions & 0 deletions e2e/src/hooks/generic.hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { BeforeAll, Before, setDefaultTimeout } from 'cucumber';
import { browser, protractor } from 'protractor';
import { SecurityPage } from '../po/security.po';

const EC = protractor.ExpectedConditions;

BeforeAll(() => {
browser.waitForAngularEnabled(false);
setDefaultTimeout(60 *10000);
});

Before(async () => {
// Check if logged out, else login
if (await browser.getCurrentUrl() === 'data:,' || await browser.getCurrentUrl() === 'http://localhost:4200/login') {
browser.get(`http://localhost:4200/login`);
await browser.wait(EC.urlIs(`http://localhost:4200/login`), browser.params.defaultTimer);
await SecurityPage.login();
}
});
115 changes: 115 additions & 0 deletions e2e/src/model/employee.class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
export interface EmployeeDetails {
id?: number;
firstName: string;
lastName: string;
country?: string;
nationality?: string;
company?: string;
designation?: string;
workExp?: string;
dataSource?: string;
}

export class Employee implements EmployeeDetails {
id: number;
firstName: string;
lastName: string;
country: string;
nationality: string;
company: string;
designation: string;
workExp: string;
dataSource: string;

constructor(
employeeDetails: EmployeeDetails
) {
this.id = employeeDetails.id;
this.firstName = employeeDetails.firstName;
this.lastName = employeeDetails.lastName;
this.company = employeeDetails.company;
this.country = employeeDetails.country;
this.nationality = employeeDetails.nationality;
this.designation = employeeDetails.designation;
this.workExp = employeeDetails.workExp;
this.dataSource = employeeDetails.dataSource;
}

get getFirstName() {
return this.firstName;
}

get getLastName() {
return this.lastName;
}

get getCountry() {
return this.country;
}

get getNationality() {
return this.nationality;
}

get getCompany() {
return this.company;
}

get getDesignation() {
return this.designation;
}

get getWorkExp() {
return this.workExp;
}

get getDataSource() {
return this.dataSource;
}

set updateFirstName(newName: string) {
this.firstName = newName;
}

set updateLastName(newLastName: string) {
this.lastName = newLastName;
}

set setCountry(newCountry: string) {
this.country = newCountry;
}

set setNationality(newNationality: string) {
this.nationality = newNationality;
}

set setCompany(newCompany: string) {
this.company = newCompany;
}

set setDesignation(newDesignation: string) {
this.designation = newDesignation;
}

set setWorkExp(newWorkExp: string) {
this.workExp = newWorkExp;
}

set setDataSource(newDataSource: string) {
this.dataSource = newDataSource;
}

get details(): EmployeeDetails {
return {
id: this.id,
firstName: this.firstName,
lastName: this.lastName,
country: this.country,
nationality: this.nationality,
company: this.company,
designation: this.designation,
workExp: this.workExp,
dataSource: this.dataSource,
};
}
}
74 changes: 74 additions & 0 deletions e2e/src/po/dashboard.po.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { element, by, browser } from 'protractor';
import { FormPage } from './form.po';
import { Employee, EmployeeDetails } from '../model/employee.class';

export class DashboardPage {
static get table() {
return element(by.tagName('p-table'));
}
static get tableRows() {
return this.table.all(by.tagName('tr'));
}

static get tableBody() {
return this.table.all(by.tagName('tbody')).get(0);
}

static get tableBodyRows() {
return this.tableBody.all(by.tagName('tr'));
}
static get tableNextPageButton() {
return element(by.css('span[class="ui-paginator-icon pi pi-caret-right"]'));
}

static async checkTableRowForData(data: string) {
let foundData = null;
for (const trData of (await this.tableRows.getText() as any)) {
console.log('tr ->', trData)
console.log('data ->', data)
if (trData.includes(data)) {
foundData = trData;
break;
}
}
return foundData;
}

static get newEmployeeButton() {
return element(by.buttonText('New Employee'));
}

static deleteEmployeeButton(index: number) {
return element.all(by.buttonText('Delete')).get(index);
}

static async createEmployee(createData: EmployeeDetails) {
await this.newEmployeeButton.click();
await FormPage.fillForm(createData);
await browser.sleep(800);
await FormPage.formButton('Add').click();
}

static async updateEmployee(updateData: EmployeeDetails): Promise<EmployeeDetails> {
const employeeRecordElement = this.tableBodyRows.get(4);
const employeeRecordID = JSON.parse(await employeeRecordElement.all(by.tagName('td')).get(0).getText());

await employeeRecordElement.click();
await FormPage.fillForm(updateData);
await browser.sleep(800);
await FormPage.formButton('Update').click();

updateData.id = employeeRecordID;
return updateData;
}

static async deleteEmployee(): Promise<EmployeeDetails> {
await this.deleteEmployeeButton(3).click();
await (await browser.switchTo().alert()).accept();

return new Employee({id: 3, firstName: 'Doris', lastName: 'Wilder'});
}
}
45 changes: 45 additions & 0 deletions e2e/src/po/form.po.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { element, by, ElementFinder } from 'protractor';
import { EmployeeDetails, Employee } from '../model/employee.class';



export class FormPage {

static get updateButton() {
return element(by.buttonText('Update'));
}

static get newEmployeeButton(): ElementFinder{
return element(by.id('new-employee'));
}

static getFormControlElement(formControlName: string) {
return element(by.css(`[formcontrolname=${formControlName}]`));
}

static formButton(buttonText: string) {
return element(by.buttonText(buttonText));
}

static async fillForm(employeeData: EmployeeDetails) {
// tslint:disable-next-line: forin
for (const key in employeeData) {
if (key === 'id') {
continue;
}

const formElement = this.getFormControlElement(key);

if (key !== 'dataSource') {
await formElement.clear();
await formElement.sendKeys(employeeData[key]);
} else {
await formElement.click();
const dropdownItemsElements = element.all(by.tagName('p-dropdownitem'));
const dropdownItems = await dropdownItemsElements.getText();

await dropdownItemsElements.get(dropdownItems.indexOf(employeeData[key])).click();
}
}
}
}
11 changes: 11 additions & 0 deletions e2e/src/po/message.po.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { element, by } from 'protractor';
export class MessagePage {
static get successMessage() {
return element(by.id('success-message'));
}
​ static get updatedMessage() {
return element(by.css('span[class="ui-messages-detail ng-tns-c3-2 ng-star-inserted"]'));
}
}
Loading