Skip to content

Commit

Permalink
[Tokenization] Tests (#1)
Browse files Browse the repository at this point in the history
* feat/initial implementation the unit test for sdk

* feat: unit tests for the functions getFormElements and getFormValues

* feat: unit tests for functions in the utils folder

* feat: unit tests for tokenize class

* bugfix: Not implemented HTMLFormElement.prototype.submit

* feat: implanted tests happy path for AsyncTokenize

* fix: test correction to throw error in form-values.test

* bugfix: Request validity including request body failure

* feat: Unit tests implemented for the Tokenization SDK completed

* refactor:
creation of functions to reduce repetitions

* refactor: changes to returned error messages

* Refactor: improvments for the unit tests

* refactor: remove some tests

* refactor: more adjustments in the tests

* refactor: remove fragile tests that test implementation

* fix(lock): update lock file

---------

Co-authored-by: Leonardo Pinheiro <[email protected]>
  • Loading branch information
milenacrios and 0xleozera authored Mar 12, 2024
1 parent c38c2c9 commit ea88f26
Show file tree
Hide file tree
Showing 12 changed files with 816 additions and 16 deletions.
165 changes: 165 additions & 0 deletions src/async-tokenize/async-tokenize.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import { fireEvent, waitFor } from '@testing-library/dom'

import { AsyncTokenize } from './async-tokenize'
import {
configureFormSubmissionMock,
formElementsMock,
malgaConfigurations,
} from 'tests/mocks/common-configurations'
import { generateForm } from 'tests/mocks/form-dom'
import { Malga } from 'src/common/malga'

const onSubmit = vi.fn()

vi.mock('src/common/malga', async (importOriginal) => {
const Malga = await importOriginal<typeof import('src/common/malga')>()
return {
...Malga,
tokenization: vi.fn(),
}
})

describe('async-tokenize', () => {
beforeEach(() => {
document.body.innerHTML = ''
})
test('should be possible to find a tokenId element in the DOM and consequently contained in the form element', async () => {
configureFormSubmissionMock()
generateForm(onSubmit)

const malga = new Malga(malgaConfigurations(false))

const asyncTokenizeObject = new AsyncTokenize(malga, formElementsMock)

asyncTokenizeObject.handle()

const form = document.querySelector('form')
fireEvent.submit(form!)

await waitFor(() => {
const tokenIdInput = document.querySelector<HTMLInputElement>(
'input[name="tokenId"]',
)
expect(tokenIdInput).toBeInTheDocument()
expect(form).toContain(tokenIdInput)
expect(tokenIdInput).toBeTruthy()
})
})
test('should be return correct tokenId in sandbox environment ', async () => {
configureFormSubmissionMock()

generateForm(onSubmit)

const malga = new Malga(malgaConfigurations(true))

const asyncTokenizeObject = new AsyncTokenize(malga, formElementsMock)

asyncTokenizeObject.handle()

const form = document.querySelector('form')
fireEvent.submit(form!)

await waitFor(() => {
const tokenIdInput = document.querySelector<HTMLInputElement>(
'input[name="tokenId"]',
)
expect(tokenIdInput?.value).toBe('sandbox-token-id')
})
})
test('should be return correct tokenId in production environment', async () => {
configureFormSubmissionMock()

generateForm(onSubmit)

const malgaConfigurationsProduction = {
apiKey: '17a64c8f-a387-4682-bdd8-d280493715e0',
clientId: 'd1d2b51a-0446-432a-b055-034518c2660e',
}

const malga = new Malga(malgaConfigurationsProduction)

const asyncTokenizeObject = new AsyncTokenize(malga, formElementsMock)

asyncTokenizeObject.handle()

const form = document.querySelector('form')
fireEvent.submit(form!)

await waitFor(() => {
const tokenIdInput = document.querySelector<HTMLInputElement>(
'input[name="tokenId"]',
)
expect(tokenIdInput?.value).toBe('production-token-id')
})
})
test('should be possible to remove the elements and thus there is only 1 after the creation of the tokenIdElement and 4 before its creation', async () => {
configureFormSubmissionMock()

generateForm(onSubmit)

const malga = new Malga(malgaConfigurations(false))

const asyncTokenizeObject = new AsyncTokenize(malga, formElementsMock)

const inputs = document.querySelectorAll('input')
expect(inputs.length).toBe(4)

asyncTokenizeObject.handle()

const form = document.querySelector('form')
fireEvent.submit(form!)

await waitFor(() => {
const inputs = document.querySelectorAll('input')
expect(inputs.length).toBe(1)
})
})

test('should be possible to return an error if empty apiKey and clientId are sent to the Malga constructor', async () => {
configureFormSubmissionMock()

generateForm(onSubmit)

const malgaConfigurationsEmpty = {
apiKey: '',
clientId: '',
}

const malga = new Malga(malgaConfigurationsEmpty)

const asyncTokenizeObject = new AsyncTokenize(malga, formElementsMock)

expect(asyncTokenizeObject.handle).toThrowError(
"Cannot read properties of undefined (reading 'elements')",
)
})
test('should be possible to throw an error when the elements passed are incompatible with those in the DOM', async () => {
configureFormSubmissionMock()

generateForm(onSubmit)

const malga = new Malga(malgaConfigurations(false))

const asyncTokenizeObject = new AsyncTokenize(malga, {
form: 'data-form',
holderName: 'data-holder-name',
number: 'data-number',
expirationDate: 'data-expiration-date',
cvv: 'data-cvv',
})

expect(asyncTokenizeObject.handle).toThrowError(
"Cannot read properties of undefined (reading 'elements')",
)
})
test('should be possible to return an error if the form inputs do not have values assigned', async () => {
configureFormSubmissionMock()
generateForm()

const malga = new Malga(malgaConfigurations(false))

const asyncTokenizeObject = new AsyncTokenize(malga, formElementsMock)

expect(asyncTokenizeObject.handle).toThrowError()
})
})
7 changes: 4 additions & 3 deletions src/async-tokenize/async-tokenize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
removeFormElements,
createFormElement,
getFormValues,
} from 'src/common/utils'
} from '../common/utils'

export class AsyncTokenize {
constructor(
Expand Down Expand Up @@ -33,8 +33,9 @@ export class AsyncTokenize {
removeFormElements(this.elements)
const tokenIdElement = createFormElement('tokenId', tokenId)

form.appendChild(tokenIdElement)
form.submit()
form?.appendChild(tokenIdElement)

form?.submit()
})
}
}
6 changes: 6 additions & 0 deletions src/common/interfaces/malga.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface MalgaCreateTokenResponse {
cardHolderName: string
cardNumber: string
cardExpirationDate: string
cardCvv: string
}
123 changes: 123 additions & 0 deletions src/common/utils/form-elements/form-elements.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import {
createFormElement,
getFormElements,
removeFormElements,
} from './form-elements'
import { generateForm } from 'tests/mocks/form-dom'

const tokenId = '54595fec-87db-44f8-996a-2f4d6bf270b9'
describe('form-elements', () => {
describe('getFormElements', () => {
test('should be possible to find the elements in the dom', () => {
generateForm()

const formElements = getFormElements({
form: 'data-malga-tokenization-form',
holderName: 'data-malga-tokenization-holder-name',
number: 'data-malga-tokenization-number',
expirationDate: 'data-malga-tokenization-expiration-date',
cvv: 'data-malga-tokenization-cvv',
})

expect(formElements.form).toBeInTheDocument()
expect(formElements.holderName).toBeInTheDocument()
expect(formElements.cvv).toBeInTheDocument()
expect(formElements.expirationDate).toBeInTheDocument()
expect(formElements.number).toBeInTheDocument()
})

test("Should be returned null when elements aren't finded", () => {
generateForm()

const formElements = getFormElements({
form: 'data-malga-form',
holderName: 'data-malga-holder-name',
number: 'data-malga-number',
expirationDate: 'data-malga-expiration-date',
cvv: 'data-malga-cvv',
})
expect(formElements.form).toBeNull()
expect(formElements.holderName).toBeNull()
expect(formElements.number).toBeNull()
expect(formElements.expirationDate).toBeNull()
expect(formElements.cvv).toBeNull()
})
})
describe('removeFormElements', () => {
beforeEach(() => {
document.body.innerHTML = ''
})
test('should be possible to return null when trying to find the elements in the dom after calling the function', () => {
generateForm()

removeFormElements({
form: 'data-malga-tokenization-form',
holderName: 'data-malga-tokenization-holder-name',
number: 'data-malga-tokenization-number',
expirationDate: 'data-malga-tokenization-expiration-date',
cvv: 'data-malga-tokenization-cvv',
})

expect(
document.querySelector('data-malga-tokenization-holder-name'),
).toBeNull()
expect(
document.querySelector('data-malga-tokenization-number'),
).toBeNull()
expect(
document.querySelector('data-malga-tokenization-expiration-date'),
).toBeNull()
expect(document.querySelector('data-malga-tokenization-cvv')).toBeNull()
})
test('should be returned the elements in the DOM, when the function are called with selectores wrong, since the elements could not be removed', () => {
generateForm()

removeFormElements({
form: 'data-malga-form',
holderName: 'data-malga-holder-name',
number: 'data-malga-number',
expirationDate: 'data-malga-expiration-date',
cvv: 'data-malga-cvv',
})
const formElements = getFormElements({
form: 'data-malga-tokenization-form',
holderName: 'data-malga-tokenization-holder-name',
number: 'data-malga-tokenization-number',
expirationDate: 'data-malga-tokenization-expiration-date',
cvv: 'data-malga-tokenization-cvv',
})
expect(formElements.form).toBeInTheDocument()
expect(formElements.holderName).toBeInTheDocument()
expect(formElements.number).toBeInTheDocument()
expect(formElements.expirationDate).toBeInTheDocument()
expect(formElements.cvv).toBeInTheDocument()
})
})
describe('createFormElements', () => {
test('should be possible to return a field with attributes of name, type and value which must be the passed tokenId', () => {
const tokenIdElement = createFormElement('tokenId', tokenId)

expect(tokenIdElement).toHaveAttribute('name', 'tokenId')
expect(tokenIdElement).toHaveValue(tokenId)
expect(tokenIdElement).toHaveAttribute('type', 'hidden')
})

test('should be possible for the field field to be the same as the one mounted in the dom', () => {
const tokenIdElement = createFormElement('tokenId', tokenId)

const field = document.createElement('input')
field.type = 'hidden'
field.name = 'tokenId'
field.value = '54595fec-87db-44f8-996a-2f4d6bf270b9'

expect(tokenIdElement).toEqual(field)
})
test('should be possible to insert the element in the body in the dom', () => {
const tokenIdElement = createFormElement('tokenId', tokenId)

document.body.appendChild(tokenIdElement)

expect(tokenIdElement).toBeInTheDocument()
})
})
})
62 changes: 62 additions & 0 deletions src/common/utils/form-values/form-values.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { formValuesMock } from 'tests/mocks/common-configurations'
import { getFormValues } from './form-values'
import { generateForm, generateFormEmptyValues } from 'tests/mocks/form-dom'

describe('getFormValues', () => {
describe('form-values', () => {
beforeEach(() => {
document.body.innerHTML = ''
})
test('should be the values of elements equals to sended', () => {
generateForm()

const formValue = getFormValues({
form: 'data-malga-tokenization-form',
holderName: 'data-malga-tokenization-holder-name',
number: 'data-malga-tokenization-number',
expirationDate: 'data-malga-tokenization-expiration-date',
cvv: 'data-malga-tokenization-cvv',
})

expect(formValue.holderName).toEqual('Taylor Swift')
expect(formValue.number).toEqual('5173000265860114')
expect(formValue.expirationDate).toEqual('05/08/2024')
expect(formValue.cvv).toEqual('114')
})
test('should be returned elements with empty values', () => {
generateFormEmptyValues()

const formValue = getFormValues({
form: 'data-malga-tokenization-form',
holderName: 'data-malga-tokenization-holder-name',
number: 'data-malga-tokenization-number',
expirationDate: 'data-malga-tokenization-expiration-date',
cvv: 'data-malga-tokenization-cvv',
})

expect(formValue.holderName).toBe('')
expect(formValue.number).toBe('')
expect(formValue.expirationDate).toBe('')
expect(formValue.cvv).toBe('')
})
test('should be possible to return error if the elements are not found', () => {
generateForm()

const inputs = document.querySelectorAll('input')
inputs[0].value = formValuesMock.holderName
inputs[1].value = formValuesMock.number
inputs[2].value = formValuesMock.expirationDate
inputs[3].value = formValuesMock.cvv

expect(() =>
getFormValues({
form: 'data-malga-form',
holderName: 'data-malga-holder-name',
number: 'data-malga-number',
expirationDate: 'data-malga-expiration-date',
cvv: 'data-malga-cvv',
}),
).toThrowError()
})
})
})
Loading

0 comments on commit ea88f26

Please sign in to comment.