Skip to content

Commit

Permalink
fix timestamp tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dcousens committed Jan 22, 2025
1 parent 6a395f5 commit af26bd0
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 112 deletions.
14 changes: 7 additions & 7 deletions examples/custom-field/4-conditional-field/views.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React, { useEffect } from 'react'
import { Text } from '@keystar/ui/typography'
import { TextField } from '@keystar/ui/text-field'

import {
type CellComponent,
type FieldController,
type FieldControllerConfig,
type FieldProps,
import type {
CellComponent,
FieldController,
FieldControllerConfig,
FieldProps,
} from '@keystone-6/core/types'

export function Field ({
Expand Down Expand Up @@ -39,10 +39,10 @@ export function Field ({
}

export const Cell: CellComponent<typeof controller> = ({ item, field }) => {
const discriminant = item?.[field.dependency.field]?.value ?? Infinity
const discriminant = (item as any)?.[field.dependency.field]?.value ?? Infinity
const hidden = discriminant > field.dependency.minimumValue
if (hidden) return <Text><i>hidden</i></Text>
return <Text>{item[field.path]}</Text>
return <Text>{(item as any)[field.path]}</Text>
}

export function controller (
Expand Down
131 changes: 37 additions & 94 deletions packages/core/src/fields/types/timestamp/views/__tests__/index.tsx
Original file line number Diff line number Diff line change
@@ -1,119 +1,62 @@
import { formatISO } from 'date-fns'
import { type FieldControllerConfig } from '../../../../../types'
import { controller, type TimestampFieldMeta } from '../index'
const STUBCONFIG: FieldControllerConfig<TimestampFieldMeta> = {
import { controller, } from '../index'

const STUBCONFIG = {
listKey: 'timestamp',
path: './timestamp',
label: 'timestmap',
label: 'foo',
customViews: {},
fieldMeta: { defaultValue: null, isRequired: false, updatedAt: false },
description: null,
}

describe('controller', () => {
describe('validate', () => {
it('should return true if neither date nor time value are specified', () => {
const { validate } = controller(STUBCONFIG)
it('null is OK if not required', () => {
const { validate } = controller({
...STUBCONFIG,
fieldMeta: {
defaultValue: null,
isRequired: false,
updatedAt: false
}
})
expect(
validate!({
kind: 'create',
value: { dateValue: null, timeValue: { kind: 'parsed', value: null } },
value: null
})
).toBe(true)
})
it('should return true if both date and time values are valid', () => {
const { validate } = controller(STUBCONFIG)
const value = {
kind: 'create',
value: {
dateValue: formatISO(new Date(), { representation: 'date' }),
timeValue: {
kind: 'parsed',
value: '10:00:00.000',
},
},
} as const
expect(validate!(value)).toBe(true)
})
it('should return false if only the date value is missing', () => {
const { validate } = controller(STUBCONFIG)
expect(
validate!({
kind: 'create',
value: {
dateValue: null,
timeValue: {
kind: 'parsed',
value: '10:00:00.000',
},
},
})
).toBe(false)
})
it('should return false if only the time value is missing', () => {
const { validate } = controller(STUBCONFIG)
expect(
validate!({
kind: 'create',
value: {
dateValue: formatISO(new Date(), { representation: 'date' }),
timeValue: { kind: 'parsed', value: null },
},
})
).toBe(false)
})
})
describe('serialize', () => {
it('should return null if neither date nor time value is specified', () => {
const { serialize } = controller(STUBCONFIG)
expect(
serialize({
kind: 'create',
value: {
dateValue: null,
timeValue: { kind: 'parsed', value: null },
},
})
).toStrictEqual({
[STUBCONFIG.path]: null,
it('isRequired enforces required (null)', () => {
const { validate } = controller({
...STUBCONFIG,
fieldMeta: {
defaultValue: null,
isRequired: true,
updatedAt: false
}
})
})
it('should return null if an invalid time value is specified', () => {
const { serialize } = controller(STUBCONFIG)
expect(
serialize({
validate!({
kind: 'create',
value: {
dateValue: '2020-10-20',
timeValue: 'hello',
},
value: null
})
).toStrictEqual({
[STUBCONFIG.path]: null,
).toBe('foo is required')
})
it('isRequired enforces required (value)', () => {
const { validate } = controller({
...STUBCONFIG,
fieldMeta: {
defaultValue: null,
isRequired: true,
updatedAt: false
}
})
})
it('should return null if no dateValue is specified', () => {
const { serialize } = controller(STUBCONFIG)
expect(
serialize({
validate!({
kind: 'create',
value: {
dateValue: null,
timeValue: { kind: 'parsed', value: '10:00:00.000' },
},
value: new Date().toJSON()
})
).toStrictEqual({
[STUBCONFIG.path]: null,
})
})
it('should return a valid ISO8601 string if a valid time and date value are specified', () => {
const { serialize } = controller(STUBCONFIG)
expect(
serialize({
kind: 'create',
value: { dateValue: '2020-10-20', timeValue: { kind: 'parsed', value: '10:00:00.000' } },
})[STUBCONFIG.path]
).toEqual(new Date('2020-10-20T10:00:00.000').toISOString())
).toBe(true)
})
})
})
16 changes: 5 additions & 11 deletions packages/core/src/fields/types/timestamp/views/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,23 +99,20 @@ function validate (
// we should always allow saving it because:
// - the value might be null in the database and we don't want to prevent saving the whole item because of that
// - we might have null because of an access control error
if (value.kind === 'update' && value.initial === null && isEmpty) {
return undefined
}
if (value.kind === 'update' && value.initial === null && isEmpty) return

if (
value.kind === 'create' &&
isEmpty &&
((typeof fieldMeta.defaultValue === 'object' && fieldMeta.defaultValue?.kind === 'now') ||
fieldMeta.updatedAt)
) {
return undefined
}
) return

if (fieldMeta.isRequired && isEmpty) return `${label} is required`

// TODO: update field in "@keystar/ui" to use new validation APIs, for more
// granular validation messages
return undefined
return
}

export const Cell: CellComponent<typeof controller> = ({ value }) => {
Expand Down Expand Up @@ -165,10 +162,7 @@ export function controller (
const { autoFocus, context, forceValidation, typeLabel, onChange, value, type, ...otherProps } = props
const [isDirty, setDirty] = useState(false)

if (type === 'empty' || type === 'not_empty') {
return null;
}

if (type === 'empty' || type === 'not_empty') return null
const parsedValue = value ? parseAbsoluteToLocal(value) : null

return (
Expand Down

0 comments on commit af26bd0

Please sign in to comment.