2021-05-03 14:25:11 -07:00

247 lines
7.5 KiB
TypeScript

import { browser, element, by, protractor, ElementFinder, ElementArrayFinder } from 'protractor';
// THESE TESTS ARE INCOMPLETE
describe('Form Validation Tests', () => {
beforeAll(() => browser.get(''));
describe('Template-driven form', () => {
beforeAll(() => {
getPage('app-hero-form-template');
});
tests('Template-Driven Form');
bobTests();
asyncValidationTests();
crossValidationTests();
});
describe('Reactive form', () => {
beforeAll(() => {
getPage('app-hero-form-reactive');
});
tests('Reactive Form');
bobTests();
asyncValidationTests();
crossValidationTests();
});
});
//////////
const testName = 'Test Name';
let page: {
section: ElementFinder,
form: ElementFinder,
title: ElementFinder,
nameInput: ElementFinder,
alterEgoInput: ElementFinder,
powerSelect: ElementFinder,
powerOption: ElementFinder,
errorMessages: ElementArrayFinder,
heroFormButtons: ElementArrayFinder,
heroSubmitted: ElementFinder,
alterEgoErrors: ElementFinder,
crossValidationErrorMessage: ElementFinder,
};
function getPage(sectionTag: string) {
const section = element(by.css(sectionTag));
const buttons = section.all(by.css('button'));
page = {
section,
form: section.element(by.css('form')),
title: section.element(by.css('h2')),
nameInput: section.element(by.css('#name')),
alterEgoInput: section.element(by.css('#alterEgo')),
powerSelect: section.element(by.css('#power')),
powerOption: section.element(by.css('#power option')),
errorMessages: section.all(by.css('div.alert')),
heroFormButtons: buttons,
heroSubmitted: section.element(by.css('.submitted-message')),
alterEgoErrors: section.element(by.css('.alter-ego-errors')),
crossValidationErrorMessage: section.element(by.css('.cross-validation-error-message')),
};
}
function tests(title: string) {
it('should display correct title', async () => {
expect(await page.title.getText()).toContain(title);
});
it('should not display submitted message before submit', async () => {
expect(await page.heroSubmitted.isElementPresent(by.css('p'))).toBe(false);
});
it('should have form buttons', async () => {
expect(await page.heroFormButtons.count()).toEqual(2);
});
it('should have error at start', async () => {
await expectFormIsInvalid();
});
// it('showForm', () => {
// page.form.getInnerHtml().then(html => console.log(html));
// });
it('should have disabled submit button', async () => {
expect(await page.heroFormButtons.get(0).isEnabled()).toBe(false);
});
it('resetting name to valid name should clear errors', async () => {
const ele = page.nameInput;
expect(await ele.isPresent()).toBe(true, 'nameInput should exist');
await ele.clear();
await ele.sendKeys(testName);
await expectFormIsValid();
});
it('should produce "required" error after clearing name', async () => {
await page.nameInput.clear();
// await page.alterEgoInput.click(); // to blur ... didn't work
await page.nameInput.sendKeys('x', protractor.Key.BACK_SPACE); // ugh!
expect(await page.form.getAttribute('class')).toMatch('ng-invalid');
expect(await page.errorMessages.get(0).getText()).toContain('required');
});
it('should produce "at least 4 characters" error when name="x"', async () => {
await page.nameInput.clear();
await page.nameInput.sendKeys('x'); // too short
await expectFormIsInvalid();
expect(await page.errorMessages.get(0).getText()).toContain('at least 4 characters');
});
it('resetting name to valid name again should clear errors', async () => {
await page.nameInput.sendKeys(testName);
await expectFormIsValid();
});
it('should have enabled submit button', async () => {
const submitBtn = page.heroFormButtons.get(0);
expect(await submitBtn.isEnabled()).toBe(true);
});
it('should hide form after submit', async () => {
await page.heroFormButtons.get(0).click();
expect(await page.heroFormButtons.get(0).isDisplayed()).toBe(false);
});
it('submitted form should be displayed', async () => {
expect(await page.heroSubmitted.isElementPresent(by.css('p'))).toBe(true);
});
it('submitted form should have new hero name', async () => {
expect(await page.heroSubmitted.getText()).toContain(testName);
});
it('clicking edit button should reveal form again', async () => {
const newFormBtn = page.heroSubmitted.element(by.css('button'));
await newFormBtn.click();
expect(await page.heroSubmitted.isElementPresent(by.css('p')))
.toBe(false, 'submitted hidden again');
expect(await page.title.isDisplayed()).toBe(true, 'can see form title');
});
}
async function expectFormIsValid() {
expect(await page.form.getAttribute('class')).toMatch('ng-valid');
}
async function expectFormIsInvalid() {
expect(await page.form.getAttribute('class')).toMatch('ng-invalid');
}
async function triggerAlterEgoValidation() {
// alterEgo has updateOn set to 'blur', click outside of the input to trigger the blur event
await element(by.css('app-root')).click();
}
async function waitForAlterEgoValidation() {
// alterEgo async validation will be performed in 400ms
await browser.sleep(400);
}
function bobTests() {
const emsg = 'Name cannot be Bob.';
it('should produce "no bob" error after setting name to "Bobby"', async () => {
// Re-populate select element
await page.powerSelect.click();
await page.powerOption.click();
await page.nameInput.clear();
await page.nameInput.sendKeys('Bobby');
await expectFormIsInvalid();
expect(await page.errorMessages.get(0).getText()).toBe(emsg);
});
it('should be ok again with valid name', async () => {
await page.nameInput.clear();
await page.nameInput.sendKeys(testName);
await expectFormIsValid();
});
}
function asyncValidationTests() {
const emsg = 'Alter ego is already taken.';
it(`should produce "${emsg}" error after setting alterEgo to Eric`, async () => {
await page.alterEgoInput.clear();
await page.alterEgoInput.sendKeys('Eric');
await triggerAlterEgoValidation();
await waitForAlterEgoValidation();
await expectFormIsInvalid();
expect(await page.alterEgoErrors.getText()).toBe(emsg);
});
it('should be ok again with different values', async () => {
await page.alterEgoInput.clear();
await page.alterEgoInput.sendKeys('John');
await triggerAlterEgoValidation();
await waitForAlterEgoValidation();
await expectFormIsValid();
expect(await page.alterEgoErrors.isPresent()).toBe(false);
});
}
function crossValidationTests() {
const emsg = 'Name cannot match alter ego.';
it(`should produce "${emsg}" error after setting name and alter ego to the same value`, async () => {
await page.nameInput.clear();
await page.nameInput.sendKeys('Batman');
await page.alterEgoInput.clear();
await page.alterEgoInput.sendKeys('Batman');
await triggerAlterEgoValidation();
await waitForAlterEgoValidation();
await expectFormIsInvalid();
expect(await page.crossValidationErrorMessage.getText()).toBe(emsg);
});
it('should be ok again with different values', async () => {
await page.nameInput.clear();
await page.nameInput.sendKeys('Batman');
await page.alterEgoInput.clear();
await page.alterEgoInput.sendKeys('Superman');
await triggerAlterEgoValidation();
await waitForAlterEgoValidation();
await expectFormIsValid();
expect(await page.crossValidationErrorMessage.isPresent()).toBe(false);
});
}