Skip to content

Commit

Permalink
chore: add some tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tomzemp committed Aug 15, 2024
1 parent d80340c commit 160e20a
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 30 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@faker-js/faker": "^8.4.1",
"@testing-library/jest-dom": "^6.4.5",
"@testing-library/react": "12.1.5",
"@testing-library/user-event": "^14.5.2",
"cypress": "^13.10.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.6",
Expand Down
227 changes: 226 additions & 1 deletion src/pages/editItem.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
waitFor,
within,
} from '@testing-library/react'
import { userEvent } from '@testing-library/user-event'
import React from 'react'
import { MemoryRouter, Route } from 'react-router-dom'
import { QueryParamProvider } from 'use-query-params'
Expand Down Expand Up @@ -67,6 +68,8 @@ jest.mock('@dhis2/app-runtime', () => ({
}),
}))

const patchExchange = jest.fn()

const setUp = (
ui,
{
Expand All @@ -90,7 +93,13 @@ const setUp = (
}
return undefined
},
[`aggregateDataExchanges/${exchangeIdOrDataExchangeId}`]: () => {
[`aggregateDataExchanges/${exchangeIdOrDataExchangeId}`]: (
type,
query
) => {
if (type === 'json-patch') {
patchExchange(query?.data)
}
return {}
},
analytics: { headers: [], metaData: { items: {}, dimensions: {} } },
Expand Down Expand Up @@ -144,6 +153,10 @@ beforeEach(() => {
})

describe('<EditItem/>', () => {
afterEach(() => {
jest.clearAllMocks()
})

const createRequest = async (screen, { requestName, orgUnit }) => {
const requestNameInput = await screen.findByLabelText('Request name')
fireEvent.input(requestNameInput, { target: { value: requestName } })
Expand Down Expand Up @@ -549,4 +562,216 @@ describe('<EditItem/>', () => {
).toBeInTheDocument()
)
})

it('loads None (follows Input general ID scheme) option if no ID scheme is specified', async () => {
const request = testRequest()
const dataExchange = testDataExchange({
requests: [request],
targetType: 'INTERNAL',
inputIdSchemes: { idScheme: 'UID' },
})

const { screen } = setUp(<EditItem />, {
userContext: testUserContext({ canAddExchange: true }),
dataExchange,
})

expect(
await screen.findByTestId('add-exchange-title')
).toHaveTextContent('Edit exchange')

const defaultElementIdSchemeRadio = within(
screen.getByTestId('element-id-scheme-selector')
).getByRole('radio', { name: 'None (follows Input general ID scheme)' })

expect(defaultElementIdSchemeRadio).toBeChecked()

const defaultOrgUnitIdSchemeRadio = within(
screen.getByTestId('org-unit-id-scheme-selector')
).getByRole('radio', { name: 'None (follows Input general ID scheme)' })

expect(defaultOrgUnitIdSchemeRadio).toBeChecked()

const defaultCategoryOptionComboSchemeRadio = within(
screen.getByTestId('category-option-combo-scheme-selector')
).getByRole('radio', { name: 'None (follows Input general ID scheme)' })

expect(defaultCategoryOptionComboSchemeRadio).toBeChecked()
})

it('displays appropriate ID scheme selections based on exchange values', async () => {
const request = testRequest()
const dataExchange = testDataExchange({
requests: [request],
targetType: 'INTERNAL',
inputIdSchemes: {
idScheme: 'UID',
dataElementIdScheme: 'CODE',
orgUnitIdScheme: 'ATTRIBUTE:attribute001',
categoryOptionComboIdScheme: 'UID',
},
})
const attributes = [
testAttribute({ displayName: 'Taco Friday', id: 'attribute001' }),
testAttribute(),
testAttribute(),
]

const { screen } = setUp(<EditItem />, {
userContext: testUserContext({ canAddExchange: true }),
dataExchange,
attributes,
})

expect(
await screen.findByTestId('add-exchange-title')
).toHaveTextContent('Edit exchange')

const codeElementIdSchemeRadio = within(
screen.getByTestId('element-id-scheme-selector')
).getByRole('radio', { name: 'Code' })

expect(codeElementIdSchemeRadio).toBeChecked()

const attributeOrgUnitIdSchemeRadio = within(
screen.getByTestId('org-unit-id-scheme-selector')
).getByRole('radio', { name: 'Attribute' })

expect(attributeOrgUnitIdSchemeRadio).toBeChecked()
expect(
within(screen.getByTestId('org-unit-id-scheme-selector')).getByText(
'Taco Friday'
)
).toBeInTheDocument()

const idCategoryOptionComboSchemeRadio = within(
screen.getByTestId('category-option-combo-scheme-selector')
).getByRole('radio', { name: 'ID' })

expect(idCategoryOptionComboSchemeRadio).toBeChecked()
})

it('does not post anything for ID schemes when None option is selected', async () => {
const request = testRequest()
const dataExchange = testDataExchange({
requests: [request],
targetType: 'INTERNAL',
inputIdSchemes: {
idScheme: 'UID',
dataElementIdScheme: 'CODE',
orgUnitIdScheme: 'UID',
categoryOptionComboIdScheme: 'CODE',
},
})

const { screen } = setUp(<EditItem />, {
userContext: testUserContext({ canAddExchange: true }),
dataExchange,
})

const user = userEvent.setup()

await screen.findByTestId('add-exchange-title')

const defaultElementIdSchemeRadio = within(
screen.getByTestId('element-id-scheme-selector')
).getByRole('radio', { name: 'None (follows Input general ID scheme)' })
await user.click(defaultElementIdSchemeRadio)

const defaultOrgUnitIdSchemeRadio = within(
screen.getByTestId('org-unit-id-scheme-selector')
).getByRole('radio', { name: 'None (follows Input general ID scheme)' })
await user.click(defaultOrgUnitIdSchemeRadio)

const defaultCategoryOptionComboSchemeRadio = within(
screen.getByTestId('category-option-combo-scheme-selector')
).getByRole('radio', { name: 'None (follows Input general ID scheme)' })
await user.click(defaultCategoryOptionComboSchemeRadio)

const saveExchange = within(
screen.getByTestId('edit-item-footer')
).getByText('Save exchange')
await user.click(saveExchange)

const expectedPayload = [
{
op: 'add',
path: '/target',
value: {
type: 'INTERNAL',
request: {
idScheme: 'UID',
},
},
},
]

expect(patchExchange).toHaveBeenCalled()
expect(patchExchange).toHaveBeenCalledWith(expectedPayload)
}, 7000),
it('posts expected id schemes based on selections', async () => {
const request = testRequest()
const dataExchange = testDataExchange({
requests: [request],
targetType: 'INTERNAL',
inputIdSchemes: {
idScheme: 'UID',
categoryOptionComboIdScheme: 'ATTRIBUTE:snorkmaiden',
},
})
const attributes = [
testAttribute({
name: 'Snorkmaiden',
displayName: 'Snorkmaiden',
id: 'snorkmaiden',
}),
testAttribute(),
testAttribute(),
]

const { screen } = setUp(<EditItem />, {
userContext: testUserContext({ canAddExchange: true }),
dataExchange,
attributes,
})

const user = userEvent.setup()

await screen.findByTestId('add-exchange-title')

const idElementIdSchemeRadio = within(
screen.getByTestId('element-id-scheme-selector')
).getByRole('radio', { name: 'ID' })
await user.click(idElementIdSchemeRadio)

const codeOrgUnitIdSchemeRadio = within(
screen.getByTestId('org-unit-id-scheme-selector')
).getByRole('radio', { name: 'Code' })
await user.click(codeOrgUnitIdSchemeRadio)

const saveExchange = within(
screen.getByTestId('edit-item-footer')
).getByText('Save exchange')
await user.click(saveExchange)

const expectedPayload = [
{
op: 'add',
path: '/target',
value: {
type: 'INTERNAL',
request: {
categoryOptionComboIdScheme:
'ATTRIBUTE:snorkmaiden',
dataElementIdScheme: 'UID',
idScheme: 'UID',
orgUnitIdScheme: 'CODE',
},
},
},
]

expect(patchExchange).toHaveBeenCalled()
expect(patchExchange).toHaveBeenCalledWith(expectedPayload)
})
})
7 changes: 6 additions & 1 deletion src/utils/builders.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const testDataExchange = ({
name = faker.company.name(),
requests = [testRequest()],
targetType = randomValueIn(['INTERNAL', 'EXTERNAL']),
inputIdSchemes = { idScheme: 'UID' },
writeMetadataAccess = faker.datatype.boolean(),
readMetadataAccess = faker.datatype.boolean(),
writeDataAccess = faker.datatype.boolean(),
Expand All @@ -30,7 +31,11 @@ export const testDataExchange = ({
displayName: name,
name,
source: { requests },
target: { type: targetType, api: { url: externalURL } },
target: {
type: targetType,
api: { url: externalURL },
request: inputIdSchemes,
},
access: {
write: writeMetadataAccess,
read: readMetadataAccess,
Expand Down
36 changes: 8 additions & 28 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3858,6 +3858,11 @@
"@testing-library/dom" "^8.0.0"
"@types/react-dom" "<18.0.0"

"@testing-library/user-event@^14.5.2":
version "14.5.2"
resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.5.2.tgz#db7257d727c891905947bd1c1a99da20e03c2ebd"
integrity sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==

"@tootallnate/once@1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
Expand Down Expand Up @@ -15064,7 +15069,7 @@ string-natural-compare@^3.0.1:
resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==

"string-width-cjs@npm:string-width@^4.2.0":
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
Expand All @@ -15090,15 +15095,6 @@ string-width@^3.0.0, string-width@^3.1.0:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"

string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"

string-width@^5.0.1, string-width@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
Expand Down Expand Up @@ -15212,14 +15208,7 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"

"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"

strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
Expand Down Expand Up @@ -16934,7 +16923,7 @@ workbox-window@6.6.1:
"@types/trusted-types" "^2.0.2"
workbox-core "6.6.1"

"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
Expand All @@ -16961,15 +16950,6 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
Expand Down

0 comments on commit 160e20a

Please sign in to comment.