Skip to content

Commit

Permalink
add duration tokens to validation (#749)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasoppermann authored Oct 5, 2023
1 parent bcef815 commit 0a3384e
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/schemas/designToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {dimensionToken} from './dimensionToken'
import {colorToken} from './colorToken'
import {fontFamilyToken} from './fontFamilyToken'
import {shadowToken} from './shadowToken'
import {durationToken} from './durationToken'

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: TODO: fix this
Expand All @@ -27,6 +28,7 @@ export const designToken = z.record(
typographyToken,
viewportRangeToken,
numberToken,
durationToken,
stringToken,
]),
// referenceToken,
Expand Down
12 changes: 12 additions & 0 deletions src/schemas/durationToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {z} from 'zod'
import {baseToken} from './baseToken'
import {referenceValue} from './referenceValue'
import {durationValue} from './durationValue'
import {tokenType} from './tokenType'

export const durationToken = baseToken
.extend({
$value: z.union([durationValue, referenceValue]),
$type: tokenType('duration'),
})
.strict()
58 changes: 58 additions & 0 deletions src/schemas/durationTokenSchema.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {durationToken} from './durationToken'

describe('Schema: durationToken', () => {
const validToken = {
$value: '1000ms',
$type: 'duration',
$description: '1000 milliseconds',
}

it('parses valid duration tokens', () => {
expect(durationToken.safeParse(validToken).success).toStrictEqual(true)
})

it('fails on invalid properties', () => {
// additional element
expect(
durationToken.safeParse({
...validToken,
duration: '1000s',
}).success,
).toStrictEqual(false)
// missing value
expect(
durationToken.safeParse({
$type: 'duration',
}).success,
).toStrictEqual(false)
// missing type
expect(
durationToken.safeParse({
$value: '1000ms',
}).success,
).toStrictEqual(false)
})

it('fails on wrong type', () => {
// invalid string
expect(
durationToken.safeParse({
...validToken,
$type: 'motion',
}).success,
).toStrictEqual(false)
// undefined
expect(
durationToken.safeParse({
...validToken,
$type: undefined,
}).success,
).toStrictEqual(false)
// no type
expect(
durationToken.safeParse({
$value: '1000ms',
}).success,
).toStrictEqual(false)
})
})
9 changes: 9 additions & 0 deletions src/schemas/durationValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {z} from 'zod'
import {schemaErrorMessage} from '../utilities/schemaErrorMessage'

export const durationValue = z.string().refine(
duration => /(^[0-9]+ms$)/.test(duration),
val => ({
message: schemaErrorMessage(`Invalid duration: "${val}"`, `A duration must be a string with an "ms"`),
}),
)
25 changes: 25 additions & 0 deletions src/schemas/durationValueSchema.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {durationValue} from './durationValue'

describe('Schema: durationValue', () => {
it('passes on valid duration values', () => {
expect(durationValue.safeParse('0ms').success).toStrictEqual(true)
expect(durationValue.safeParse('100ms').success).toStrictEqual(true)
expect(durationValue.safeParse('20000ms').success).toStrictEqual(true)
})

it('fails on invalid duration values', () => {
expect(durationValue.safeParse(-1).success).toStrictEqual(false)
expect(durationValue.safeParse(0).success).toStrictEqual(false)
expect(durationValue.safeParse(1.1).success).toStrictEqual(false)
expect(durationValue.safeParse('0').success).toStrictEqual(false)
expect(durationValue.safeParse('10').success).toStrictEqual(false)
expect(durationValue.safeParse('10s').success).toStrictEqual(false)
expect(durationValue.safeParse('').success).toStrictEqual(false)
})

it('fails on non-string values', () => {
expect(durationValue.safeParse(undefined).success).toStrictEqual(false)
expect(durationValue.safeParse(null).success).toStrictEqual(false)
expect(durationValue.safeParse(1).success).toStrictEqual(false)
})
})
6 changes: 6 additions & 0 deletions src/schemas/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ describe('Schema validation', () => {
color: {
$value: '#000000',
$type: 'color',
$description: 'The color black',
},
duration: {
$value: '1000ms',
$type: 'duration',
$description: '1000 milliseconds',
},
},
}
Expand Down
1 change: 1 addition & 0 deletions src/schemas/validTokenType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const validTypes = [
'color',
'typography',
'dimension',
'duration',
'border',
'duration',
'shadow',
Expand Down

0 comments on commit 0a3384e

Please sign in to comment.