diff --git a/src/index.test.ts b/src/index.test.ts index 63bd278..08081bc 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -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', () => { diff --git a/src/index.ts b/src/index.ts index 19ded30..0b957b0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -168,40 +168,41 @@ const getFormValues = (form: HTMLFormElement, submitter?: HTMLSubmitterElement) } const formElements = form.elements as unknown as Record const allFormFieldElements = Object.entries(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 ) diff --git a/test/fixtures/templates/default.html b/test/fixtures/templates/everything.html similarity index 100% rename from test/fixtures/templates/default.html rename to test/fixtures/templates/everything.html diff --git a/test/fixtures/templates/single-input-with-double-submitters.html b/test/fixtures/templates/single-input-with-double-button-submitters.html similarity index 100% rename from test/fixtures/templates/single-input-with-double-submitters.html rename to test/fixtures/templates/single-input-with-double-button-submitters.html diff --git a/test/integrations/blank.e2e.ts b/test/integrations/blank.e2e.ts index adacc43..af58ac4 100644 --- a/test/integrations/blank.e2e.ts +++ b/test/integrations/blank.e2e.ts @@ -1,6 +1,7 @@ /// 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); }) }); }) diff --git a/test/integrations/default.e2e.ts b/test/integrations/default.e2e.ts deleted file mode 100644 index 6662e94..0000000 --- a/test/integrations/default.e2e.ts +++ /dev/null @@ -1,49 +0,0 @@ -/// - -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); - }) - }) - }) - }) -}); diff --git a/test/integrations/everything.e2e.ts b/test/integrations/everything.e2e.ts new file mode 100644 index 0000000..b0fb4fd --- /dev/null +++ b/test/integrations/everything.e2e.ts @@ -0,0 +1,104 @@ +/// + +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()); + }) + }) +}); diff --git a/test/integrations/single-disabled-input.e2e.ts b/test/integrations/single-disabled-input.e2e.ts deleted file mode 100644 index de049ed..0000000 --- a/test/integrations/single-disabled-input.e2e.ts +++ /dev/null @@ -1,28 +0,0 @@ -/// - -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); - }) - }) - }) -}); diff --git a/test/integrations/single-input-with-double-input-submitters.e2e.ts b/test/integrations/single-input-with-double-input-submitters.e2e.ts deleted file mode 100644 index 307cf5e..0000000 --- a/test/integrations/single-input-with-double-input-submitters.e2e.ts +++ /dev/null @@ -1,28 +0,0 @@ -/// - -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); - }) - }) - }) -}); diff --git a/test/integrations/single-input-with-double-submitters.e2e.ts b/test/integrations/single-input-with-double-submitters.e2e.ts deleted file mode 100644 index b0fba93..0000000 --- a/test/integrations/single-input-with-double-submitters.e2e.ts +++ /dev/null @@ -1,28 +0,0 @@ -/// - -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); - }) - }) - }) -}); diff --git a/test/integrations/single-input.e2e.ts b/test/integrations/single-input.e2e.ts deleted file mode 100644 index bf9fb96..0000000 --- a/test/integrations/single-input.e2e.ts +++ /dev/null @@ -1,28 +0,0 @@ -/// - -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); - }) - }) - }) -}); diff --git a/test/integrations/single-readonly-input.e2e.ts b/test/integrations/single-readonly-input.e2e.ts deleted file mode 100644 index 1190866..0000000 --- a/test/integrations/single-readonly-input.e2e.ts +++ /dev/null @@ -1,28 +0,0 @@ -/// - -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); - }) - }) - }) -}); diff --git a/test/integrations/single.e2e.ts b/test/integrations/single.e2e.ts new file mode 100644 index 0000000..6309a91 --- /dev/null +++ b/test/integrations/single.e2e.ts @@ -0,0 +1,162 @@ +/// + +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); + }) + }) +}); diff --git a/test/utils/index.ts b/test/utils/index.ts index 2ad18f4..a0e9b02 100644 --- a/test/utils/index.ts +++ b/test/utils/index.ts @@ -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 => { +export const loadTemplate = async (templateName: string): Promise => { 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') } diff --git a/test/utils/search.ts b/test/utils/search.ts new file mode 100644 index 0000000..2f5cc3c --- /dev/null +++ b/test/utils/search.ts @@ -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() + )