Both the JSDOM and the Cypress tests are organized.master
@@ -1,10 +1,11 @@ | |||
import * as fixtures from '../test/utils' | |||
import getFormValues from '.' | |||
import {DOMWindow, JSDOM} from 'jsdom'; | |||
describe('blank template', () => { | |||
let window: fixtures.Window | |||
let window: DOMWindow | |||
beforeEach(async () => { | |||
window = await fixtures.loadTemplate('blank') | |||
window = new JSDOM(await fixtures.loadTemplate('blank')).window | |||
}) | |||
it('should have blank form value', () => { | |||
const [form] = Array.from(window.document.getElementsByTagName('form')) | |||
@@ -14,9 +15,9 @@ describe('blank template', () => { | |||
}) | |||
describe('single input template', () => { | |||
let window: fixtures.Window | |||
let window: DOMWindow | |||
beforeEach(async () => { | |||
window = await fixtures.loadTemplate('single-input') | |||
window = new JSDOM(await fixtures.loadTemplate('single-input')).window | |||
}) | |||
it('should have a single form value', () => { | |||
const [form] = Array.from(window.document.getElementsByTagName('form')) | |||
@@ -26,9 +27,9 @@ describe('single input template', () => { | |||
}) | |||
describe('single disabled input template', () => { | |||
let window: fixtures.Window | |||
let window: DOMWindow | |||
beforeEach(async () => { | |||
window = await fixtures.loadTemplate('single-disabled-input') | |||
window = new JSDOM(await fixtures.loadTemplate('single-disabled-input')).window | |||
}) | |||
it('should have blank form value', () => { | |||
const [form] = Array.from(window.document.getElementsByTagName('form')) | |||
@@ -38,9 +39,9 @@ describe('single disabled input template', () => { | |||
}) | |||
describe('single readonly input template', () => { | |||
let window: fixtures.Window | |||
let window: DOMWindow | |||
beforeEach(async () => { | |||
window = await fixtures.loadTemplate('single-readonly-input') | |||
window = new JSDOM(await fixtures.loadTemplate('single-readonly-input')).window | |||
}) | |||
it('should have a single form value', () => { | |||
const [form] = Array.from(window.document.getElementsByTagName('form')) | |||
@@ -49,10 +50,10 @@ describe('single readonly input template', () => { | |||
}) | |||
}) | |||
describe('single input with double submitters template', () => { | |||
let window: fixtures.Window | |||
describe('single input with double button submitters template', () => { | |||
let window: DOMWindow | |||
beforeEach(async () => { | |||
window = await fixtures.loadTemplate('single-input-with-double-submitters') | |||
window = new JSDOM(await fixtures.loadTemplate('single-input-with-double-button-submitters')).window | |||
}) | |||
it('should have a single form value', () => { | |||
const [form] = Array.from(window.document.getElementsByTagName('form')) | |||
@@ -69,9 +70,9 @@ describe('single input with double submitters template', () => { | |||
}) | |||
describe('single input with double input submitters template', () => { | |||
let window: fixtures.Window | |||
let window: DOMWindow | |||
beforeEach(async () => { | |||
window = await fixtures.loadTemplate('single-input-with-double-input-submitters') | |||
window = new JSDOM(await fixtures.loadTemplate('single-input-with-double-input-submitters')).window | |||
}) | |||
it('should have a single form value', () => { | |||
@@ -168,40 +168,41 @@ const getFormValues = (form: HTMLFormElement, submitter?: HTMLSubmitterElement) | |||
} | |||
const formElements = form.elements as unknown as Record<string | number, FieldNode> | |||
const allFormFieldElements = Object.entries<FieldNode>(formElements) | |||
const formFieldElements = allFormFieldElements.filter(([, el]) => isValidFormField(el)) | |||
const formFieldElements = allFormFieldElements.filter(([k, el]) => { | |||
return ( | |||
// get only indexed forms | |||
!isNaN(Number(k)) | |||
&& isValidFormField(el) | |||
) | |||
}) | |||
const fieldValues = formFieldElements.reduce( | |||
(theFormValues, [,el]) => { | |||
const inputEl = el as HTMLInputElement | |||
if (inputEl.tagName === 'INPUT' && inputEl.type === 'radio' && !inputEl.checked) { | |||
return theFormValues | |||
} | |||
const fieldValue = getFieldValue(el, submitter) | |||
if (fieldValue === null) { | |||
return theFormValues | |||
} | |||
const fieldName = el['name'] as string; | |||
// const { [fieldName]: oldFormValue = null } = theFormValues; | |||
const { [fieldName]: oldFormValue = null } = theFormValues; | |||
// if (oldFormValue === null) { | |||
if (oldFormValue === null) { | |||
return { | |||
...theFormValues, | |||
[fieldName]: fieldValue, | |||
} | |||
// } | |||
// | |||
// if (!Array.isArray(oldFormValue)) { | |||
// return { | |||
// ...theFormValues, | |||
// [fieldName]: [oldFormValue, fieldValue], | |||
// } | |||
// } | |||
// | |||
// return { | |||
// ...theFormValues, | |||
// [fieldName]: [...oldFormValue, fieldValue], | |||
// } | |||
} | |||
if (!Array.isArray(oldFormValue)) { | |||
return { | |||
...theFormValues, | |||
[fieldName]: [oldFormValue, fieldValue], | |||
} | |||
} | |||
return { | |||
...theFormValues, | |||
[fieldName]: [...oldFormValue, fieldValue], | |||
} | |||
}, | |||
{} as any | |||
) | |||
@@ -1,6 +1,7 @@ | |||
/// <reference types="cypress" /> | |||
import getFormValues from '../../src' | |||
import {makeSearchParams} from '../utils/search'; | |||
describe('blank template', () => { | |||
beforeEach(() => { | |||
@@ -9,21 +10,20 @@ describe('blank template', () => { | |||
}) | |||
it('should have blank form value', () => { | |||
let beforeValues; | |||
let form; | |||
cy | |||
.visit('/') | |||
.get('form') | |||
.then((formResult) => { | |||
const [form] = Array.from(formResult); | |||
beforeValues = getFormValues(form); | |||
form.submit(); | |||
cy.wait('@submitted') | |||
cy.location('search').then(search => { | |||
console.log(beforeValues) | |||
const before = new URLSearchParams(beforeValues).toString(); | |||
const after = new URLSearchParams(search).toString(); | |||
expect(before).to.equal(after); | |||
}) | |||
[form] = Array.from(formResult); | |||
}) | |||
.submit() | |||
.wait('@submitted') | |||
.location('search') | |||
.then(search => { | |||
const before = makeSearchParams(getFormValues(form)).toString(); | |||
const after = new URLSearchParams(search).toString(); | |||
expect(before).to.equal(after); | |||
}) | |||
}); | |||
}) |
@@ -1,49 +0,0 @@ | |||
/// <reference types="cypress" /> | |||
import getFormValues from '../../src' | |||
describe('single input template', () => { | |||
beforeEach(() => { | |||
cy.intercept({ url: '/' }, { fixture: 'templates/default.html' }); | |||
cy.intercept({ url: '/?*' }, { fixture: 'templates/default.html' }).as('submitted'); | |||
}) | |||
it('should have a single form value', () => { | |||
let beforeValues; | |||
cy | |||
.visit('/') | |||
.then(() => { | |||
cy.get('[name="first_name"]').type('John') | |||
cy.get('[name="middle_name"]').type('Marcelo') | |||
cy.get('[name="last_name"]').type('Dela Cruz') | |||
cy.get('[name="gender"][value="m"]').check() | |||
cy.get('[name="civil_status"]').select('Married') | |||
cy.get('[name="new_registration"]').check() | |||
cy.get('[name="nationality"][value="filipino"]').check() | |||
cy.get('[name="dependent"][value="Jun"]').check() | |||
// cy.get('button.dependents').click() | |||
// cy.get('.additional-dependent [name="dependent"][type="text"]').eq(0).type('Juana') | |||
// cy.get('button.dependents').click() | |||
// cy.get('.additional-dependent [name="dependent"][type="text"]').eq(1).type('Jane') | |||
// cy.get('button.dependents').click() | |||
// cy.get('.additional-dependent [name="dependent"][type="text"]').eq(2).type('Josh') | |||
cy.get('[name="notes"]').type('Test content\n\nNew line\n\nAnother line').as('filled') | |||
}) | |||
.get('form') | |||
.then((theForm) => { | |||
cy | |||
.get('[name="submit"][value="Hi"]') | |||
.then((submitterEl) => { | |||
const [submitter] = Array.from(submitterEl) as HTMLButtonElement[]; | |||
beforeValues = getFormValues(theForm[0], submitter); | |||
submitterEl.trigger('click'); | |||
cy.wait('@submitted') | |||
cy.location('search').then(search => { | |||
const before = JSON.stringify(new URLSearchParams(beforeValues).toString().split('&')); | |||
const after = JSON.stringify(new URLSearchParams(search).toString().split('&')); | |||
expect(before).to.equal(after); | |||
}) | |||
}) | |||
}) | |||
}) | |||
}); |
@@ -0,0 +1,104 @@ | |||
/// <reference types="cypress" /> | |||
import getFormValues from '../../src' | |||
import {makeSearchParams} from '../utils/search'; | |||
describe('default template', () => { | |||
beforeEach(() => { | |||
cy.intercept({ url: '/' }, { fixture: 'templates/everything.html' }); | |||
cy.intercept({ url: '/?*' }, { fixture: 'templates/everything.html' }).as('submitted'); | |||
}) | |||
it('should have a single form value', () => { | |||
let form; | |||
let submitter; | |||
cy | |||
.visit('/') | |||
cy | |||
.get('[name="first_name"]') | |||
.type('John') | |||
cy | |||
.get('[name="middle_name"]') | |||
.type('Marcelo') | |||
cy | |||
.get('[name="last_name"]') | |||
.type('Dela Cruz') | |||
cy | |||
.get('[name="gender"][value="m"]') | |||
.check() | |||
cy | |||
.get('[name="civil_status"]') | |||
.select('Married') | |||
cy | |||
.get('[name="new_registration"]') | |||
.check() | |||
cy | |||
.get('[name="nationality"][value="filipino"]') | |||
.check() | |||
cy | |||
.get('[name="dependent"][value="Jun"]') | |||
.check() | |||
cy | |||
.get('button.dependents') | |||
.click() | |||
cy | |||
.get('.additional-dependent [name="dependent"][type="text"]') | |||
.last() | |||
.type('Juana') | |||
cy | |||
.get('button.dependents') | |||
.click() | |||
cy | |||
.get('.additional-dependent [name="dependent"][type="text"]') | |||
.last() | |||
.type('Jane') | |||
cy | |||
.get('button.dependents') | |||
.click() | |||
cy | |||
.get('.additional-dependent [name="dependent"][type="text"]') | |||
.last() | |||
.type('Josh') | |||
cy | |||
.get('[name="notes"]') | |||
.type('Test content\n\nNew line\n\nAnother line') | |||
cy | |||
.get('form') | |||
.then((theForm) => { | |||
[form] = Array.from(theForm) | |||
}) | |||
cy | |||
.get('[name="submit"][value="Hi"]') | |||
.then((submitterEl) => { | |||
[submitter] = Array.from(submitterEl) as HTMLButtonElement[]; | |||
submitterEl.trigger('click'); | |||
}) | |||
cy | |||
.wait('@submitted') | |||
.location('search') | |||
.then(search => { | |||
const before = makeSearchParams(getFormValues(form, submitter)); | |||
const after = new URLSearchParams(search) | |||
expect(before.toString()).to.equal(after.toString()); | |||
}) | |||
}) | |||
}); |
@@ -1,28 +0,0 @@ | |||
/// <reference types="cypress" /> | |||
import getFormValues from '../../src' | |||
describe('single input template', () => { | |||
beforeEach(() => { | |||
cy.intercept({ url: '/' }, { fixture: 'templates/single-disabled-input.html' }); | |||
cy.intercept({ url: '/?*' }, { fixture: 'templates/single-disabled-input.html' }).as('submitted'); | |||
}) | |||
it('should have a single form value', () => { | |||
let beforeValues; | |||
cy | |||
.visit('/') | |||
.get('form') | |||
.then((formResult) => { | |||
const [form] = Array.from(formResult); | |||
beforeValues = getFormValues(form); | |||
form.submit(); | |||
cy.wait('@submitted') | |||
cy.location('search').then(search => { | |||
const before = new URLSearchParams(beforeValues).toString(); | |||
const after = new URLSearchParams(search).toString(); | |||
expect(before).to.equal(after); | |||
}) | |||
}) | |||
}) | |||
}); |
@@ -1,28 +0,0 @@ | |||
/// <reference types="cypress" /> | |||
import getFormValues from '../../src' | |||
describe('single input template', () => { | |||
beforeEach(() => { | |||
cy.intercept({ url: '/' }, { fixture: 'templates/single-input-with-double-input-submitters.html' }); | |||
cy.intercept({ url: '/?*' }, { fixture: 'templates/single-input-with-double-input-submitters.html' }).as('submitted'); | |||
}) | |||
it('should have a single form value', () => { | |||
let beforeValues; | |||
cy | |||
.visit('/') | |||
.get('form') | |||
.then((formResult) => { | |||
const [form] = Array.from(formResult); | |||
beforeValues = getFormValues(form); | |||
form.submit(); | |||
cy.wait('@submitted') | |||
cy.location('search').then(search => { | |||
const before = new URLSearchParams(beforeValues).toString(); | |||
const after = new URLSearchParams(search).toString(); | |||
expect(before).to.equal(after); | |||
}) | |||
}) | |||
}) | |||
}); |
@@ -1,28 +0,0 @@ | |||
/// <reference types="cypress" /> | |||
import getFormValues from '../../src' | |||
describe('single input template', () => { | |||
beforeEach(() => { | |||
cy.intercept({ url: '/' }, { fixture: 'templates/single-input-with-double-submitters.html' }); | |||
cy.intercept({ url: '/?*' }, { fixture: 'templates/single-input-with-double-submitters.html' }).as('submitted'); | |||
}) | |||
it('should have a single form value', () => { | |||
let beforeValues; | |||
cy | |||
.visit('/') | |||
.get('form') | |||
.then((formResult) => { | |||
const [form] = Array.from(formResult); | |||
beforeValues = getFormValues(form); | |||
form.submit(); | |||
cy.wait('@submitted') | |||
cy.location('search').then(search => { | |||
const before = new URLSearchParams(beforeValues).toString(); | |||
const after = new URLSearchParams(search).toString(); | |||
expect(before).to.equal(after); | |||
}) | |||
}) | |||
}) | |||
}); |
@@ -1,28 +0,0 @@ | |||
/// <reference types="cypress" /> | |||
import getFormValues from '../../src' | |||
describe('single input template', () => { | |||
beforeEach(() => { | |||
cy.intercept({ url: '/' }, { fixture: 'templates/single-input.html' }); | |||
cy.intercept({ url: '/?*' }, { fixture: 'templates/single-input.html' }).as('submitted'); | |||
}) | |||
it('should have a single form value', () => { | |||
let beforeValues; | |||
cy | |||
.visit('/') | |||
.get('form') | |||
.then((formResult) => { | |||
const [form] = Array.from(formResult); | |||
beforeValues = getFormValues(form); | |||
form.submit(); | |||
cy.wait('@submitted') | |||
cy.location('search').then(search => { | |||
const before = new URLSearchParams(beforeValues).toString(); | |||
const after = new URLSearchParams(search).toString(); | |||
expect(before).to.equal(after); | |||
}) | |||
}) | |||
}) | |||
}); |
@@ -1,28 +0,0 @@ | |||
/// <reference types="cypress" /> | |||
import getFormValues from '../../src' | |||
describe('single input template', () => { | |||
beforeEach(() => { | |||
cy.intercept({ url: '/' }, { fixture: 'templates/single-readonly-input.html' }); | |||
cy.intercept({ url: '/?*' }, { fixture: 'templates/single-readonly-input.html' }).as('submitted'); | |||
}) | |||
it('should have a single form value', () => { | |||
let beforeValues; | |||
cy | |||
.visit('/') | |||
.get('form') | |||
.then((formResult) => { | |||
const [form] = Array.from(formResult); | |||
beforeValues = getFormValues(form); | |||
form.submit(); | |||
cy.wait('@submitted') | |||
cy.location('search').then(search => { | |||
const before = new URLSearchParams(beforeValues).toString(); | |||
const after = new URLSearchParams(search).toString(); | |||
expect(before).to.equal(after); | |||
}) | |||
}) | |||
}) | |||
}); |
@@ -0,0 +1,162 @@ | |||
/// <reference types="cypress" /> | |||
import getFormValues from '../../src' | |||
import {makeSearchParams} from '../utils/search'; | |||
describe('single input template', () => { | |||
beforeEach(() => { | |||
cy.intercept({ url: '/' }, { fixture: 'templates/single-input.html' }); | |||
cy.intercept({ url: '/?*' }, { fixture: 'templates/single-input.html' }).as('submitted'); | |||
}) | |||
it('should have a single form value', () => { | |||
let form | |||
cy | |||
.visit('/') | |||
.get('form') | |||
.then((formResult) => { | |||
[form] = Array.from(formResult); | |||
}) | |||
.get('[type="submit"]') | |||
.click() | |||
.wait('@submitted') | |||
.location('search') | |||
.then(search => { | |||
const before = makeSearchParams(getFormValues(form)).toString(); | |||
const after = new URLSearchParams(search).toString(); | |||
expect(before).to.equal(after); | |||
}) | |||
}) | |||
}); | |||
describe('single readonly template', () => { | |||
beforeEach(() => { | |||
cy.intercept({ url: '/' }, { fixture: 'templates/single-readonly-input.html' }); | |||
cy.intercept({ url: '/?*' }, { fixture: 'templates/single-readonly-input.html' }).as('submitted'); | |||
}) | |||
it('should have a single form value', () => { | |||
let form | |||
cy | |||
.visit('/') | |||
.get('form') | |||
.then((formResult) => { | |||
[form] = Array.from(formResult); | |||
}) | |||
.get('[type="submit"]') | |||
.click() | |||
.wait('@submitted') | |||
.location('search') | |||
.then(search => { | |||
const before = makeSearchParams(getFormValues(form)).toString(); | |||
const after = new URLSearchParams(search).toString(); | |||
expect(before).to.equal(after); | |||
}) | |||
}) | |||
}); | |||
describe('single disabled template', () => { | |||
beforeEach(() => { | |||
cy.intercept({ url: '/' }, { fixture: 'templates/single-disabled-input.html' }); | |||
cy.intercept({ url: '/?*' }, { fixture: 'templates/single-disabled-input.html' }).as('submitted'); | |||
}) | |||
it('should have a single form value', () => { | |||
let form | |||
cy | |||
.visit('/') | |||
.get('form') | |||
.then((formResult) => { | |||
[form] = Array.from(formResult); | |||
}) | |||
.get('[type="submit"]') | |||
.click() | |||
.wait('@submitted') | |||
.location('search') | |||
.then(search => { | |||
const before = makeSearchParams(getFormValues(form)).toString(); | |||
const after = new URLSearchParams(search).toString(); | |||
expect(before).to.equal(after); | |||
}) | |||
}) | |||
}); | |||
describe('single input with double button submitters template', () => { | |||
beforeEach(() => { | |||
cy | |||
.intercept( | |||
{ url: '/' }, | |||
{ fixture: 'templates/single-input-with-double-button-submitters.html' } | |||
); | |||
cy | |||
.intercept( | |||
{ url: '/?*' }, | |||
{ fixture: 'templates/single-input-with-double-button-submitters.html' } | |||
) | |||
.as('submitted'); | |||
}) | |||
it('should have a single form value', () => { | |||
let submitter; | |||
let form; | |||
cy | |||
.visit('/') | |||
.get('form') | |||
.then((formResult) => { | |||
[form] = Array.from(formResult); | |||
}) | |||
.get('[name="action"][value="Bar"]') | |||
.then((submitterEl) => { | |||
[submitter] = Array.from(submitterEl) | |||
}) | |||
.click() | |||
.wait('@submitted') | |||
.location('search') | |||
.then(search => { | |||
const before = makeSearchParams(getFormValues(form, submitter as HTMLInputElement)).toString(); | |||
const after = new URLSearchParams(search).toString(); | |||
expect(before).to.equal(after); | |||
}) | |||
}) | |||
}); | |||
describe('single input with double input submitters template', () => { | |||
beforeEach(() => { | |||
cy | |||
.intercept( | |||
{ url: '/' }, | |||
{ fixture: 'templates/single-input-with-double-input-submitters.html' } | |||
); | |||
cy | |||
.intercept( | |||
{ url: '/?*' }, | |||
{ fixture: 'templates/single-input-with-double-input-submitters.html' } | |||
) | |||
.as('submitted'); | |||
}) | |||
it('should have a single form value', () => { | |||
let submitter; | |||
let form; | |||
cy | |||
.visit('/') | |||
.get('form') | |||
.then((formResult) => { | |||
[form] = Array.from(formResult); | |||
}) | |||
.get('[name="action"][value="Foo"]') | |||
.then((submitterEl) => { | |||
[submitter] = Array.from(submitterEl) | |||
}) | |||
.click() | |||
.wait('@submitted') | |||
.location('search') | |||
.then(search => { | |||
const before = makeSearchParams(getFormValues(form, submitter as HTMLInputElement)).toString(); | |||
const after = new URLSearchParams(search).toString(); | |||
expect(before).to.equal(after); | |||
}) | |||
}) | |||
}); |
@@ -1,11 +1,8 @@ | |||
import fs from 'fs' | |||
import path from 'path' | |||
import {DOMWindow, JSDOM} from 'jsdom' | |||
export type Window = DOMWindow | |||
export const loadTemplate = async (templateName: string): Promise<Window> => { | |||
export const loadTemplate = async (templateName: string): Promise<string> => { | |||
const templatePath = path.join('test', 'fixtures', 'templates', `${templateName}.html`) | |||
const templateRaw = await fs.promises.readFile(templatePath) | |||
return new JSDOM(templateRaw.toString('utf-8')).window | |||
return templateRaw.toString('utf-8') | |||
} |
@@ -0,0 +1,12 @@ | |||
export const makeSearchParams = (beforeValues) => Object | |||
.entries(beforeValues) | |||
.reduce( | |||
(beforeSearchParams, [key, value]) => { | |||
const theValue = !Array.isArray(value) ? [value] : value | |||
theValue.forEach(v => { | |||
beforeSearchParams.append(key, v) | |||
}) | |||
return beforeSearchParams | |||
}, | |||
new URLSearchParams() | |||
) |