diff --git a/tests/account_creation.spec.js b/tests/account_creation.spec.js index 12aaae4..530f80e 100644 --- a/tests/account_creation.spec.js +++ b/tests/account_creation.spec.js @@ -1,35 +1,101 @@ -// @ts-check -import { faker } from '@faker-js/faker'; +// Importing necessary libraries and modules + +const { faker } = require('@faker-js/faker'); const { chromium } = require('playwright'); -const { test, expect } = require('@playwright/test'); +const { test } = require('@playwright/test'); const LoginPage = require('./login_page'); const RegistrationPage = require('./registration_page'); +const ContactsPage = require('./contacts_page'); +const AddContactsPage = require('./add_contacts_page'); +// Generating fake user data using faker library let userName = faker.person.firstName() let userSurname = faker.person.lastName() let userEmail = faker.internet.email({ firstName: userName, lastName: userSurname }) let userPass = faker.internet.password() +let userEmailFalse = faker.internet.email() // for Negative email test +let userPassFalse = faker.internet.password() // for Negative password test -test.beforeAll(async () => { - const browser = await chromium.launch(); - await browser.newPage(); +// Generating fake contact information using faker library + +let contactFirstName = faker.person.firstName(); +let contactLastName = faker.person.lastName(); +let contactDateOfBirth = faker.date.past() // should stringify the output afterwards since we want a string, not an object +let contactEmail = faker.internet.email({ firstName: contactFirstName, lastName: contactLastName }) +let contactPhone = faker.string.numeric({ length: 11 }) +let contactPhone2 = '976.620.4768 x7104' // faker.phone.number() // FIXME number validation is not versatile. Has to accept greater string lengths and formats + +// FIXME address has no validation in relativity. For example city and state/province may not match but still be accepted +// FIXME address data is not mandatory to be entered and does not throw an error if it dont + +let contactAddress1 = faker.location.streetAddress(); +let contactAddress2 = faker.location.secondaryAddress(); // FIXME secondaryAddress info not appearing at Contact List +let contactCity = faker.location.city(); +let contactStateOrProvince = faker.location.state(); +let contactPostalCode = faker.location.zipCode(); +let contactCountry = faker.location.country(); + +// NOTE created two different datasets because some of the data that is sent upon Contact Creation is concatenated at the Contact List + +let contactArrayPost = [contactFirstName, contactLastName, (JSON.stringify(contactDateOfBirth)).substring(1, (JSON.stringify(contactDateOfBirth)).indexOf('T')), contactEmail, contactPhone, contactAddress1, contactAddress2, contactCity, contactStateOrProvince, contactPostalCode, contactCountry] +let contactArrayGet = [`${contactFirstName} ${contactLastName}`, (JSON.stringify(contactDateOfBirth)).substring(1, (JSON.stringify(contactDateOfBirth)).indexOf('T')), contactEmail, contactPhone, contactAddress1, `${contactCity} ${contactStateOrProvince} ${contactPostalCode}`, contactCountry] + +test('Positive testing', async ({ page }) => { + const loginPage = new LoginPage(page); + const registrationPage = new RegistrationPage(page); + const contactsPage = new ContactsPage(page); + const addContactsPage = new AddContactsPage(page); + + await loginPage.open(); + await loginPage.assertLoggedOut(); + await loginPage.clickRegisterButton(); + await registrationPage.fillRegistrationForm(userName, userSurname, userEmail, userPass); + await registrationPage.submitRegistrationForm(true); + await contactsPage.assertContactsPage(); + await contactsPage.clickLogoutButton(); + await loginPage.assertLoggedOut(); + await loginPage.logIn(userEmail, userPass, true); + await contactsPage.clickAddANewContact(); + await addContactsPage.addNewContact(contactArrayPost) + await addContactsPage.submitNewContact(true); + await contactsPage.verifyContactRow(contactArrayGet) + await contactsPage.clickLogoutButton() + await loginPage.assertLoggedOut(); + }); -test('Open the login page and create account', async ({ page }) => { +test('Negative testing', async ({ page }) => { const loginPage = new LoginPage(page); const registrationPage = new RegistrationPage(page); + const contactsPage = new ContactsPage(page); + const addContactsPage = new AddContactsPage(page); + const phoneIndex = contactArrayPost.indexOf(contactPhone); + const emailIndex = contactArrayPost.indexOf(contactEmail); + + contactArrayPost.splice(phoneIndex, 1, contactPhone2); // replace contactPhone with contactPhone2 to explicitly cause a failure + contactArrayPost.splice(emailIndex, 1, contactEmail.replace('@', '')) // remove @ sign from the email to explicitly cause a failure await loginPage.open(); + await loginPage.logIn(userEmailFalse, userPass, false); + await loginPage.logIn(userEmail, userPassFalse, false); + await loginPage.logIn(userEmailFalse, userPassFalse, false); await loginPage.clickRegisterButton(); await registrationPage.fillRegistrationForm(userName, userSurname, userEmail, userPass); - await registrationPage.submitRegistrationForm(); - await registrationPage.landsAtContactsPage(); + await registrationPage.submitRegistrationForm(false); // NOTE test if duplicate accounts cannot be created + await registrationPage.cancelRegistrationForm() + await loginPage.logIn(userEmail, userPass, true); + await contactsPage.clickAddANewContact(); + await addContactsPage.addNewContact(contactArrayPost) // FIXME duplicate contacts can be created. Since this can indeed happen we should add the email as a unique identifier and warn the user + await addContactsPage.submitNewContact(false) // NOTE submit Contact Creation form with erroneous data + await addContactsPage.cancelAddContactForm() }); +// Closing the browser after all tests have finished running + test.afterAll(async () => { const browser = await chromium.launch(); await browser.close(); diff --git a/tests/add_contacts_page.js b/tests/add_contacts_page.js new file mode 100644 index 0000000..f9b5890 --- /dev/null +++ b/tests/add_contacts_page.js @@ -0,0 +1,68 @@ +const { test, expect } = require('@playwright/test'); + +class AddContactsPage { + constructor(page) { + this.page = page; + } + + async open() { + await this.page.goto('https://thinking-tester-contact-list.herokuapp.com/addContact'); + await expect(this.page).toHaveTitle(/Add Contact/); + await expect(this.page.locator('h1')).toHaveText('Add Contact'); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com/addContact'); + } + + async addNewContact(dataArray) { + + const locatorsArray = ['First Name', 'Last Name', 'yyyy-MM-dd', 'example@email.com', '8005551234', 'Address 1', 'Address 2', 'City', 'State or Province', 'Postal Code', 'Country'] + + await expect(this.page).toHaveTitle(/Add Contact/); + await expect(this.page.locator('h1')).toHaveText('Add Contact'); + await expect(this.page.getByRole('button', { name: 'Logout' })).toBeAttached() + await expect(this.page.getByRole('button', { name: 'Submit' })).toBeAttached() + await expect(this.page.getByRole('button', { name: 'Cancel' })).toBeAttached() + + for (let i = 0; i < dataArray.length; i++) { + + await this.page.getByPlaceholder(locatorsArray[i]).fill(dataArray[i]) + + } + + } + + async submitNewContact(isSuccessful) { + + await this.page.getByRole('button', { name: 'Submit' }).click(); + + if (isSuccessful) { + + await expect(this.page.getByText('Contact validation failed')).not.toBeAttached(); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com/contactList'); + } + + else { + + await expect(this.page.getByText('Contact validation failed')).toBeAttached(); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com/addContact'); + + } + + } + + async clickLogoutButton() { + await this.page.getByRole('button', { name: 'Logout' }).click(); + await expect(this.page).toHaveTitle(/Contact List App/); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com'); + + } + + async cancelAddContactForm() { + + await this.page.getByRole('button', { name: 'Cancel' }).click(); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com/contactList'); + + } + +} + +module.exports = AddContactsPage; diff --git a/tests/contacts_page.js b/tests/contacts_page.js new file mode 100644 index 0000000..9a7aa4a --- /dev/null +++ b/tests/contacts_page.js @@ -0,0 +1,46 @@ +const { test, expect } = require('@playwright/test'); + +class ContactsPage { + constructor(page) { + this.page = page; + } + + async open() { + await this.page.goto('https://thinking-tester-contact-list.herokuapp.com/contactList'); + await expect(this.page).toHaveTitle(/My Contacts/); + await expect(this.page.locator('h1')).toHaveText('Contact List'); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com/contactList'); + + } + + async assertContactsPage() { + await expect(this.page).toHaveTitle(/My Contacts/); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com/contactList'); + await expect(this.page.locator('h1')).toHaveText('Contact List'); + await expect(this.page.getByRole('button', { name: 'Logout' })).toBeAttached() + await expect(this.page.getByRole('button', { name: 'Add a New Contact' })).toBeAttached() + await expect(this.page.locator('div.contacts')).toBeVisible(); + + } + async clickLogoutButton() { + await this.page.getByRole('button', { name: 'Logout' }).click(); + await expect(this.page).toHaveTitle(/Contact List App/); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com'); + } + + async clickAddANewContact() { + await this.page.getByRole('button', { name: 'Add a New Contact' }).click(); + await expect(this.page).toHaveTitle(/Add Contact/); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com/addContact'); + } + async verifyContactRow(dataArray) { + await expect(this.page.locator('h1')).toHaveText('Contact List'); + + for (let i = 0; i < dataArray.length; i++) { + await expect(this.page.getByText(dataArray[i], { exact: false })).toBeVisible(); + } + + } +} + +module.exports = ContactsPage; diff --git a/tests/login_page.js b/tests/login_page.js index b4a4cdd..a483747 100644 --- a/tests/login_page.js +++ b/tests/login_page.js @@ -1,20 +1,46 @@ const { test, expect } = require('@playwright/test'); class LoginPage { - constructor(page) { - this.page = page; - } - - async open() { - await this.page.goto('https://thinking-tester-contact-list.herokuapp.com/'); - await expect(this.page).toHaveTitle(/Contact List App/); - await expect(this.page.locator('h1')).toHaveText('Contact List App'); + constructor(page) { + this.page = page; + } + + async open() { + await this.page.goto('https://thinking-tester-contact-list.herokuapp.com/'); + await expect(this.page).toHaveTitle(/Contact List App/); + await expect(this.page.locator('h1')).toHaveText('Contact List App'); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com'); + } + + async clickRegisterButton() { + await this.page.getByRole('button', { name: 'Sign up' }).click(); + await expect(this.page).toHaveTitle(/Add User/); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com/addUser'); + } + + async assertLoggedOut() { + await expect(this.page).toHaveTitle(/Contact List App/); + await expect(this.page.getByText('Logout')).not.toBeAttached(); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com'); + } + + async logIn(email, password, isSuccessful) { + await this.page.fill('input[placeholder="Email"]', email); + await this.page.fill('input[placeholder="Password"]', password); + await this.page.getByRole('button', { name: 'Submit' }).click(); + + if (isSuccessful) { + await expect(this.page.getByText('Incorrect username or password')).not.toBeAttached(); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com/contactList'); } - - async clickRegisterButton() { - await this.page.getByRole('button', { name: 'Sign up' }).click(); - await expect(this.page).toHaveTitle(/Add User/); + + else { + await expect(this.page.getByText('Incorrect username or password')).toBeAttached(); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com'); } + } - - module.exports = LoginPage; \ No newline at end of file + +} + +module.exports = LoginPage; \ No newline at end of file diff --git a/tests/registration_page.js b/tests/registration_page.js index 587f2b0..87062a0 100644 --- a/tests/registration_page.js +++ b/tests/registration_page.js @@ -5,34 +5,46 @@ class RegistrationPage { this.page = page; } + async open() { + await this.page.goto('https://thinking-tester-contact-list.herokuapp.com/addUser'); + await expect(this.page).toHaveTitle(/Add User/); + await expect(this.page.locator('h1')).toHaveText('Add User'); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com/addUser'); + } + async fillRegistrationForm(username, usersurname, email, password) { - await expect(this.page.locator('h1')).toHaveText('Add User'); + await expect(this.page.locator('h1')).toHaveText('Add User'); await this.page.fill('input[id="firstName"]', username); await this.page.fill('input[id="lastName"]', usersurname); await this.page.fill('input[id="email"]', email); await this.page.fill('input[id="password"]', password); } - async submitRegistrationForm() { + async submitRegistrationForm(isSuccessful) { await this.page.getByRole('button', { name: 'Submit' }).click(); + if (isSuccessful) { + + await expect(this.page.getByText('Email address is already in use')).not.toBeAttached(); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com/contactList'); + } + + else { + await expect(this.page.getByText('Email address is already in use')).toBeAttached(); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com/addUser'); + } + + } async cancelRegistrationForm() { await this.page.getByRole('button', { name: 'Cancel' }).click(); + await expect(this.page).toHaveURL('https://thinking-tester-contact-list.herokuapp.com/login'); } - async landsAtContactsPage() { - await expect(this.page).toHaveTitle(/My Contacts/); - await expect(this.page.locator('h1')).toHaveText('Contact List'); - await expect(this.page.getByRole('button', { name: 'Logout' })).toBeAttached() - await expect(this.page.getByRole('button', { name: 'Add a New Contact' })).toBeAttached() - await expect(this.page.locator('div.contacts')).toBeVisible(); - - } } module.exports = RegistrationPage;