Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add more jest tests #333

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
6 changes: 2 additions & 4 deletions src/shared/locked-status/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
export {
useCheckLockStatus,
updateLockStatusFromBackend,
} from './use-check-lock-status.js'
export { LockedContext } from './locked-info-context.js'
export { LockedProvider } from './locked-info-provider.js'
export { LockedStates } from './locked-states.js'
export { useCheckLockStatus } from './use-check-lock-status.js'
export { useLockedContext } from './use-locked-context.js'
export { updateLockStatusFromBackend } from './update-lock-status-from-backend.js'
32 changes: 32 additions & 0 deletions src/shared/locked-status/update-lock-status-from-backend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { LockedStates } from './locked-states.js'

export const updateLockStatusFromBackend = (
frontEndLockStatus,
backEndLockStatus,
setLockStatus
) => {
// if the lock status is APPROVED, set to approved
if (backEndLockStatus === 'APPROVED') {
setLockStatus(LockedStates.LOCKED_APPROVED)
return
}

// if the lock status is LOCKED, this is locked due to expiry days
if (backEndLockStatus === 'LOCKED') {
setLockStatus(LockedStates.LOCKED_EXPIRY_DAYS)
return
}

// a lock status of 'OPEN' from the backend could mean either that the form is open OR
// that the form should be locked due to data input period, OR
// that the form should be locked because an organisation unit is out of range, SO
// set to OPEN unless frontend check has identified that data input period as out-of-bounds
if (
![
LockedStates.LOCKED_DATA_INPUT_PERIOD,
LockedStates.LOCKED_ORGANISATION_UNIT,
].includes(frontEndLockStatus)
) {
setLockStatus(LockedStates.OPEN)
}
}
51 changes: 15 additions & 36 deletions src/shared/locked-status/use-check-lock-status.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
usePeriodId,
useDataSetId,
useOrgUnitId,
} from '../use-context-selection/use-context-selection.js'
} from '../use-context-selection/index.js'
import { useDataValueSet } from '../use-data-value-set/use-data-value-set.js'
import { useOrgUnit } from '../use-org-unit/use-organisation-unit.js'
import { LockedStates, BackendLockStatusMap } from './locked-states.js'
Expand Down Expand Up @@ -38,7 +38,17 @@ const isDataInputPeriodLocked = ({
)
}

const isOrgUnitLocked = ({
/**
* An org unit is locked not based on the current date,
* but based on the selected period.
*
* -> If org unit's close date is before the period's end date,
* then the user is not allowed to modify data.
*
* -> If the org unit's open date is after the period's start date,
* then the user is not allowed to modify data.
*/
const isOrgUnitTimeConstraintWithinDataInputPeriodConstraint = ({
Copy link
Member

@Birkbjo Birkbjo Jun 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't isOrgUnitLocked good enough? This starts to be a bit too long imo. If it's used for other things other than lockStatus its fine, but if its only for lockstatus, I think we should keep it. It is very descriptive of what it does though.
isOrgunitLocked describes what it's used for, not the implementation details of what makes it locked, which could in theory change, and you would need another function.

orgUnitOpeningDateString,
orgUnitClosedDateString,
selectedPeriod,
Expand All @@ -61,15 +71,15 @@ const isOrgUnitLocked = ({
// if orgUnitOpeningDate exists, it must be earlier than the periodStartDate
if (orgUnitOpeningDateString) {
const orgUnitOpeningDate = new Date(orgUnitOpeningDateString)
if (!(orgUnitOpeningDate <= periodStartDate)) {
if (orgUnitOpeningDate > periodStartDate) {
return true
}
}

// if orgUnitClosedDate exists, it must be after the periodEndDate
if (orgUnitClosedDateString) {
const orgUnitClosedDate = new Date(orgUnitClosedDateString)
if (!(orgUnitClosedDate >= periodEndDate)) {
if (orgUnitClosedDate < periodEndDate) {
return true
}
}
Expand Down Expand Up @@ -112,7 +122,7 @@ export const useCheckLockStatus = () => {
}

if (
isOrgUnitLocked({
isOrgUnitTimeConstraintWithinDataInputPeriodConstraint({
orgUnitOpeningDateString,
orgUnitClosedDateString,
selectedPeriod,
Expand Down Expand Up @@ -143,34 +153,3 @@ export const useCheckLockStatus = () => {
currentDayString,
])
}

export const updateLockStatusFromBackend = (
frontEndLockStatus,
backEndLockStatus,
setLockStatus
) => {
// if the lock status is APPROVED, set to approved
if (backEndLockStatus === 'APPROVED') {
setLockStatus(LockedStates.LOCKED_APPROVED)
return
}

// if the lock status is LOCKED, this is locked due to expiry days
if (backEndLockStatus === 'LOCKED') {
setLockStatus(LockedStates.LOCKED_EXPIRY_DAYS)
return
}

// a lock status of 'OPEN' from the backend could mean either that the form is open OR
// that the form should be locked due to data input period, OR
// that the form should be locked because an organisation unit is out of range, SO
// set to OPEN unless frontend check has identified that data input period as out-of-bounds
if (
![
LockedStates.LOCKED_DATA_INPUT_PERIOD,
LockedStates.LOCKED_ORGANISATION_UNIT,
].includes(frontEndLockStatus)
) {
setLockStatus(LockedStates.OPEN)
}
}
151 changes: 151 additions & 0 deletions src/shared/locked-status/use-check-lock-status.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import { renderHook } from '@testing-library/react-hooks'
import { useClientServerDate } from '../date/index.js'
import { useMetadata } from '../metadata/index.js'
import {
usePeriodId,
useDataSetId,
useOrgUnitId,
} from '../use-context-selection/index.js'
import { useDataValueSet } from '../use-data-value-set/use-data-value-set.js'
import { useOrgUnit } from '../use-org-unit/use-organisation-unit.js'
import { LockedStates } from './locked-states.js'
import { useCheckLockStatus } from './use-check-lock-status.js'
import { useLockedContext } from './use-locked-context.js'

jest.mock('../date/use-client-server-date.js', () => ({
__esModule: true,
default: jest.fn(),
}))

jest.mock('../metadata/use-metadata.js', () => ({
useMetadata: jest.fn(),
}))

jest.mock('../use-context-selection/use-context-selection.js', () => ({
useDataSetId: jest.fn(),
useOrgUnitId: jest.fn(),
usePeriodId: jest.fn(),
}))

jest.mock('./use-locked-context.js', () => ({
useLockedContext: jest.fn(),
}))

jest.mock('../use-data-value-set/use-data-value-set.js', () => ({
useDataValueSet: jest.fn(),
}))

jest.mock('../use-org-unit/use-organisation-unit.js', () => ({
useOrgUnit: jest.fn(),
}))

describe('useCheckLockStatus', () => {
useDataSetId.mockImplementation(() => ['dataSet1'])
useOrgUnitId.mockImplementation(() => ['orgUnit1'])
usePeriodId.mockImplementation(() => ['202301'])
useOrgUnit.mockImplementation(() => ({
data: {
id: 'orgUnit1',
displayName: 'Org unit 1',
path: '/orgUnit1',
openingDate: '2015-01-01',
closedDate: '2023-01-18',
},
}))
useMetadata.mockImplementation(() => ({
data: {
dataSets: {
dataSet1: {
id: 'dataSet1',
dataInputPeriods: [
{
period: { id: '202301', name: '202301' },
// This defines in which time frame you're allowed
// to enter data for this period
openingDate: '2022-07-01T00:00:00.000',
closingDate: '2023-01-28T00:00:00.000',
},
],
},
},
},
}))
useDataValueSet.mockImplementation(() => ({
loading: false,
error: null,
data: null,
}))

const setLockStatus = jest.fn()
useLockedContext.mockImplementation(() => ({ setLockStatus }))

afterEach(() => {
setLockStatus.mockClear()
})

it('should set the lock status to LOCKED_DATA_INPUT_PERIOD', () => {
useClientServerDate.mockImplementation(() => ({
serverDate: new Date('2023-01-30'),
clientDate: new Date('2023-01-30'),
}))

renderHook(useCheckLockStatus)

expect(setLockStatus).toHaveBeenCalledWith(
LockedStates.LOCKED_DATA_INPUT_PERIOD
)
})

it('should set the lock status to LOCKED_ORGANISATION_UNIT', () => {
useClientServerDate.mockImplementation(() => ({
serverDate: new Date('2023-01-22'),
clientDate: new Date('2023-01-22'),
}))

renderHook(useCheckLockStatus)

expect(setLockStatus).toHaveBeenCalledWith(
LockedStates.LOCKED_ORGANISATION_UNIT
)
})

it('should set the lock status to OPEN', () => {
usePeriodId.mockImplementation(() => ['202301'])

useOrgUnit.mockImplementation(() => ({
data: {
id: 'orgUnit1',
displayName: 'Org unit 1',
path: '/orgUnit1',
openingDate: '2015-01-01',
closedDate: '2023-02-01',
},
}))

useMetadata.mockImplementation(() => ({
data: {
dataSets: {
dataSet1: {
id: 'dataSet1',
dataInputPeriods: [
{
period: { id: '202301', name: '202301' },
openingDate: '2022-07-01T00:00:00.000',
closingDate: '2023-01-31T00:00:00.000',
},
],
},
},
},
}))

useClientServerDate.mockImplementation(() => ({
serverDate: new Date('2022-12-10'),
clientDate: new Date('2022-12-10'),
}))

renderHook(useCheckLockStatus)

expect(setLockStatus).toHaveBeenCalledWith(LockedStates.OPEN)
})
})
9 changes: 3 additions & 6 deletions src/shared/use-context-selection/use-is-valid-selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,15 @@ export function useIsValidSelection() {
const dataSet = selectors.getDataSetById(data, dataSetId)
const catComboId = dataSet?.categoryCombo?.id
const categoryCombo = selectors.getCategoryComboById(data, catComboId)
if (
dataSet === undefined ||
categoryCombo === null ||
categoryCombo === undefined
) {

if (!dataSet || !categoryCombo) {
return false
}

const selectedOptions = Object.values(attributeOptionComboSelection)

// if default catCombo, no selection is needed
if (categoryCombo?.isDefault) {
if (categoryCombo.isDefault) {
return true
}

Expand Down
Loading