Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions packages/kbn-config-schema/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import {
MapOfOptions,
MapOfType,
MaybeType,
NullableType,
NeverType,
NumberOptions,
NumberType,
Expand Down Expand Up @@ -102,7 +101,7 @@ function maybe<V>(type: Type<V>): Type<V | undefined> {
}

function nullable<V>(type: Type<V>): Type<V | null> {
return new NullableType(type);
return schema.oneOf([type, schema.literal(null)], { defaultValue: () => null });
Copy link
Member

Choose a reason for hiding this comment

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

nit: can it just be defaultValue: null?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think I tried that first, it didn't work, and you suggested the function invocation version, which did work. Let me try again ...

Copy link
Member Author

Choose a reason for hiding this comment

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

Huh, only reference I can find is you suggesting this change a long time ago to me. Weird thing is, no idea where the function version came from, I don't think I would have figured that one out myself; I have a feeling maybe it was needed in a previous version of the combinator.

So, commit incoming with that change ...

Copy link
Member

Choose a reason for hiding this comment

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

Heh, yeah, I believe that was me who initially suggested that function syntax 🙈 Just didn't think long enough to suggest the simplest solution, sorry for the confusion.

}

function object<P extends Props>(props: P, options?: ObjectTypeOptions<P>): ObjectType<P> {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion packages/kbn-config-schema/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export { ConditionalType, ConditionalTypeValue } from './conditional_type';
export { DurationOptions, DurationType } from './duration_type';
export { LiteralType } from './literal_type';
export { MaybeType } from './maybe_type';
export { NullableType } from './nullable_type';
export { MapOfOptions, MapOfType } from './map_type';
export { NumberOptions, NumberType } from './number_type';
export { ObjectType, ObjectTypeOptions, Props, TypeOf } from './object_type';
Expand Down
82 changes: 75 additions & 7 deletions packages/kbn-config-schema/src/types/nullable_type.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,66 @@

import { schema } from '..';

test('returns value if specified', () => {
test('returns string value when passed string', () => {
const type = schema.nullable(schema.string());
expect(type.validate('test')).toEqual('test');
expect(type.validate('test')).toBe('test');
});

test('returns null if null', () => {
test('returns number value when passed number', () => {
const type = schema.nullable(schema.number());
expect(type.validate(42)).toBe(42);
});

test('returns boolean value when passed boolean', () => {
const type = schema.nullable(schema.boolean());
expect(type.validate(true)).toBe(true);
});

test('returns object value when passed object', () => {
const type = schema.nullable(
schema.object({
foo: schema.number(),
bar: schema.boolean(),
baz: schema.string(),
})
);
const object = {
foo: 666,
bar: true,
baz: 'foo bar baz',
};

expect(type.validate(object)).toEqual(object);
});

test('returns null if null for string', () => {
const type = schema.nullable(schema.string());
expect(type.validate(null)).toEqual(null);
expect(type.validate(null)).toBe(null);
});

test('returns null if null for number', () => {
const type = schema.nullable(schema.number());
expect(type.validate(null)).toBe(null);
});

test('returns null if undefined', () => {
test('returns null if null for boolean', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

could you add a couple of tests validating it returns value for other types different from null?

const type = schema.nullable(schema.boolean());
expect(type.validate(true)).toBe(true);

Copy link
Member Author

Choose a reason for hiding this comment

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

added some additional tests - validating positively for more basic types, and negatively for a property in an object type

const type = schema.nullable(schema.boolean());
expect(type.validate(null)).toBe(null);
});

test('returns null if undefined for string', () => {
const type = schema.nullable(schema.string());
expect(type.validate(undefined)).toEqual(null);
expect(type.validate(undefined)).toBe(null);
});

test('returns null if undefined for number', () => {
const type = schema.nullable(schema.number());
expect(type.validate(undefined)).toBe(null);
});

test('returns null if undefined for boolean', () => {
const type = schema.nullable(schema.boolean());
expect(type.validate(undefined)).toBe(null);
});

test('returns null even if contained type has a default value', () => {
Expand All @@ -41,7 +88,7 @@ test('returns null even if contained type has a default value', () => {
})
);

expect(type.validate(undefined)).toEqual(null);
expect(type.validate(undefined)).toBe(null);
});

test('validates contained type', () => {
Expand All @@ -56,6 +103,27 @@ test('validates basic type', () => {
expect(() => type.validate(666)).toThrowErrorMatchingSnapshot();
});

test('validates type in object', () => {
const type = schema.object({
foo: schema.nullable(schema.string({ maxLength: 1 })),
bar: schema.nullable(schema.boolean()),
});

expect(type.validate({ foo: 'a' })).toEqual({ foo: 'a', bar: null });
expect(type.validate({ foo: null })).toEqual({ foo: null, bar: null });
expect(type.validate({})).toEqual({ foo: null, bar: null });
expect(type.validate({ bar: null })).toEqual({ foo: null, bar: null });
});

test('validates type errors in object', () => {
const type = schema.object({
foo: schema.nullable(schema.string({ maxLength: 1 })),
bar: schema.nullable(schema.boolean()),
});

expect(() => type.validate({ foo: 'ab' })).toThrowErrorMatchingSnapshot();
});

test('includes namespace in failure', () => {
const type = schema.nullable(schema.string({ maxLength: 1 }));

Expand Down
32 changes: 0 additions & 32 deletions packages/kbn-config-schema/src/types/nullable_type.ts

This file was deleted.