Skip to content

Commit

Permalink
validate values, default them to appropriate properties and test them
Browse files Browse the repository at this point in the history
  • Loading branch information
kainpets committed Jul 19, 2024
1 parent 0191a0d commit f859271
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 64 deletions.
47 changes: 23 additions & 24 deletions src/lib/blueprint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,29 +405,28 @@ const createResponse = (responses: OpenapiOperation['responses']): Response => {
}
}

const PropertySchema = z.object({
name: z.string(),
description: z.string().optional().default(''),
// TODO: Remove the transforms.
// This should be a boolean, but the OpenAPI spec allows for a string value
isDeprecated: z
.union([z.boolean(), z.string()])
.transform((value) => {
if (typeof value === 'boolean') return value
return value === 'true'
})
.default(false),
deprecationMessage: z.string().optional().default(''),
isUndocumented: z
.union([z.boolean(), z.string()])
.transform((value) => {
if (typeof value === 'boolean') return value
return value === 'true'
})
.default(false),
'x-undocumented': z.string().optional(),
'x-deprecated': z.string().default('false'),
})
const PropertySchema = z
.object({
name: z.string(),
description: z.string().optional().default(''),
// TODO: Remove the transform
isDeprecated: z
.union([z.boolean(), z.string()])
.transform((value) => {
if (typeof value === 'boolean') return value
return value === 'true'
})
.default(false),
deprecationMessage: z.string().optional().default(''),
isUndocumented: z.boolean().default(true),
'x-undocumented': z.string().optional(),
'x-deprecated': z.string().default('false'),
})
.transform((data) => ({
...data,
isUndocumented:
data['x-undocumented'] !== undefined ? true : data.isUndocumented,
}))

const createProperties = (
properties: Record<string, OpenapiSchema>,
Expand All @@ -438,7 +437,7 @@ const createProperties = (
description: prop.description,
isDeprecated: prop.deprecated,
deprecationMessage: prop['x-deprecated'],
isUndocumented: prop['x-undocumented'] !== undefined,
isUndocumented: true, // Default value, will be overwritten if x-undocumented is present
})

const baseProperty = {
Expand Down
61 changes: 49 additions & 12 deletions test/data-validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,26 +63,63 @@ test('Deprecated and undocumented properties are correctly handled', (t) => {
const blueprint = createBlueprint(types)
const fooResource = blueprint.resources['foo']

const systemTypeProp = fooResource?.properties.find(
(p) => p.name === 'system_type',
const deprecatedProp = fooResource?.properties.find(
(p) => p.name === 'deprecated_foo',
)
t.truthy(systemTypeProp, 'system_type property should exist')
t.true(
systemTypeProp?.isDeprecated,
'system_type should be marked as deprecated',
deprecatedProp?.isDeprecated,
'deprecated property should be marked as deprecated',
)
t.is(
systemTypeProp?.deprecationMessage,
'Use `external_type` instead.',
deprecatedProp?.deprecationMessage,
'Use `other_foo_type` instead.',
'Deprecation message should be correct',
)

const warningsProp = fooResource?.properties.find(
(p) => p.name === 'warnings',
const undocumentedProp = fooResource?.properties.find(
(p) => p.name === 'undocumented_foo',
)
t.truthy(warningsProp, 'warnings property should exist')
t.truthy(undocumentedProp, 'undocumented property should exist')
t.true(
warningsProp?.isUndocumented,
'warnings should be marked as undocumented',
undocumentedProp?.isUndocumented,
'undocumented property should be marked as undocumented',
)

const missingXProp = fooResource?.properties.find(
(p) => p.name === 'missing_x_properties',
)
t.truthy(missingXProp, 'Property missing x- values should exist')
t.false(
missingXProp?.isDeprecated,
'Property without x-deprecated should not be marked as deprecated',
)
t.true(
missingXProp?.isUndocumented,
'Property without x-undocumented should be marked as undocumented',
)
})

test('Properties missing x- values get correct default values', (t) => {
// @ts-expect-error Remove once the fixture is properly typed
const blueprint = createBlueprint(types)
const fooResource = blueprint.resources['foo']

const missingXProp = fooResource?.properties.find(
(p) => p.name === 'missing_x_properties',
)

t.truthy(missingXProp, 'Property missing x- values should exist')
t.is(missingXProp?.type, 'string', 'Type should be correctly set')
t.is(
missingXProp?.description,
'This property is missing `x-` properties.',
'Description should be set correctly',
)
t.false(missingXProp?.isDeprecated, 'isDeprecated should default to false')
t.is(
missingXProp?.deprecationMessage,
'',
'deprecationMessage should default to an empty string',
)
t.true(missingXProp?.isUndocumented, 'isUndocumented should default to true')
})
12 changes: 8 additions & 4 deletions test/fixtures/types/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ export default {
description: 'Foo name',
type: 'string',
},
system_type: {
deprecated_foo: {
type: 'string',
enum: ['type1', 'type2'],
deprecated: true,
'x-deprecated': 'Use `external_type` instead.',
'x-deprecated': 'Use `other_foo_type` instead.',
},
external_type: {
type: 'string',
enum: ['type1', 'type2'],
description: 'Brand-specific terminology for the foo type.',
description: 'Foo-specific terminology for the foo type.',
},
warnings: {
undocumented_foo: {
type: 'array',
items: {
type: 'object',
Expand All @@ -37,6 +37,10 @@ export default {
},
'x-undocumented': 'Currently, no warnings defined for `foo`s.',
},
missing_x_properties: {
type: 'string',
description: 'This property is missing `x-` properties.',
},
},
required: ['foo_id', 'name'],
},
Expand Down
24 changes: 16 additions & 8 deletions test/snapshots/blueprint.test.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,24 @@ Generated by [AVA](https://avajs.dev).
deprecationMessage: '',
description: 'Foo id',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'foo_id',
type: 'string',
},
{
deprecationMessage: '',
description: 'Foo name',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'name',
type: 'string',
},
{
deprecationMessage: 'Use `external_type` instead.',
deprecationMessage: 'Use `other_foo_type` instead.',
description: '',
isDeprecated: true,
isUndocumented: false,
name: 'system_type',
isUndocumented: true,
name: 'deprecated_foo',
type: 'enum',
values: [
{
Expand All @@ -46,9 +46,9 @@ Generated by [AVA](https://avajs.dev).
},
{
deprecationMessage: '',
description: 'Brand-specific terminology for the foo type.',
description: 'Foo-specific terminology for the foo type.',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'external_type',
type: 'enum',
values: [
Expand All @@ -65,9 +65,17 @@ Generated by [AVA](https://avajs.dev).
description: '',
isDeprecated: false,
isUndocumented: true,
name: 'warnings',
name: 'undocumented_foo',
type: 'list',
},
{
deprecationMessage: '',
description: 'This property is missing `x-` properties.',
isDeprecated: false,
isUndocumented: true,
name: 'missing_x_properties',
type: 'string',
},
],
resourceType: 'foo',
},
Expand Down
Binary file modified test/snapshots/blueprint.test.ts.snap
Binary file not shown.
32 changes: 16 additions & 16 deletions test/snapshots/seam-blueprint.test.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,71 +16,71 @@ Generated by [AVA](https://avajs.dev).
deprecationMessage: '',
description: 'ID of the `acs_system`.',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'acs_system_id',
type: 'string',
},
{
deprecationMessage: '',
description: 'Indicates whether the `acs_system` supports [adding users to access groups](https://docs.seam.co/latest/capability-guides/access-systems/assigning-users-to-access-groups#add-an-acs-user-to-an-access-group). See also [Access Group-based Access Control Systems](https://docs.seam.co/latest/capability-guides/access-systems/understanding-access-control-system-differences#access-group-based-access-control-systems).',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'can_add_acs_users_to_acs_access_groups',
type: 'boolean',
},
{
deprecationMessage: '',
description: 'Indicates whether it is possible to [launch enrollment automations](https://docs.seam.co/latest/capability-guides/mobile-access-in-development/issuing-mobile-credentials-from-an-access-control-system#prepare-the-phones-for-a-user-identity-to-start-receiving-mobile-credentials-using-an-enrollment-aut) for the `acs_system`.',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'can_automate_enrollment',
type: 'boolean',
},
{
deprecationMessage: '',
description: 'Indicates whether the `acs_system` supports creating [access groups](https://docs.seam.co/latest/capability-guides/access-systems/assigning-users-to-access-groups). See also [Access Group-based Access Control Systems](https://docs.seam.co/latest/capability-guides/access-systems/understanding-access-control-system-differences#access-group-based-access-control-systems).',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'can_create_acs_access_groups',
type: 'boolean',
},
{
deprecationMessage: '',
description: 'Indicates whether the `acs_system` supports [removing users from access groups](https://docs.seam.co/latest/capability-guides/access-systems/assigning-users-to-access-groups#remove-an-acs-user-from-an-access-group). See also [Access Group-based Access Control Systems](https://docs.seam.co/latest/capability-guides/access-systems/understanding-access-control-system-differences#access-group-based-access-control-systems).',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'can_remove_acs_users_from_acs_access_groups',
type: 'boolean',
},
{
deprecationMessage: '',
description: 'IDs of the [connected accounts](https://docs.seam.co/latest/core-concepts/connected-accounts) associated with the `acs_system`.',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'connected_account_ids',
type: 'list',
},
{
deprecationMessage: '',
description: 'Date and time at which the `acs_system` was created.',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'created_at',
type: 'string',
},
{
deprecationMessage: '',
description: 'Errors associated with the `acs_system`.',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'errors',
type: 'list',
},
{
deprecationMessage: '',
description: 'Brand-specific terminology for the `acs_system` type.',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'external_type',
type: 'enum',
values: [
Expand Down Expand Up @@ -114,39 +114,39 @@ Generated by [AVA](https://avajs.dev).
deprecationMessage: '',
description: 'Display name that corresponds to the brand-specific terminology for the `acs_system` type.',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'external_type_display_name',
type: 'string',
},
{
deprecationMessage: '',
description: 'Alternative text for the `acs_system` image.',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'image_alt_text',
type: 'string',
},
{
deprecationMessage: '',
description: 'URL for the image that represents the `acs_system`.',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'image_url',
type: 'string',
},
{
deprecationMessage: '',
description: 'Name of the `acs_system`.',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'name',
type: 'string',
},
{
deprecationMessage: 'Use `external_type`.',
description: '',
isDeprecated: true,
isUndocumented: false,
isUndocumented: true,
name: 'system_type',
type: 'enum',
values: [
Expand Down Expand Up @@ -180,7 +180,7 @@ Generated by [AVA](https://avajs.dev).
deprecationMessage: 'Use `external_type_display_name`.',
description: '',
isDeprecated: true,
isUndocumented: false,
isUndocumented: true,
name: 'system_type_display_name',
type: 'string',
},
Expand All @@ -196,7 +196,7 @@ Generated by [AVA](https://avajs.dev).
deprecationMessage: '',
description: 'ID of the [workspace](https://docs.seam.co/latest/core-concepts/workspaces) that contains the `acs_system`.',
isDeprecated: false,
isUndocumented: false,
isUndocumented: true,
name: 'workspace_id',
type: 'string',
},
Expand Down
Binary file modified test/snapshots/seam-blueprint.test.ts.snap
Binary file not shown.

0 comments on commit f859271

Please sign in to comment.