// Copyright (C) 2021 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import { arrayOf, num, oneOf, record, requiredStr, runValidator, ValidatedType, ValidationError } from './validators'; const colors = ['RED', 'GREEN', 'BLUE'] as const; type Color = typeof colors[number]; const point = record({ id: requiredStr, color: oneOf(colors, 'RED'), x: num(), y: num(1), properties: record({mass: num(10)}) }); type Point = ValidatedType; const nested = record({deeply: record({nested: record({array: arrayOf(point)})})}); test('validator ensures presence of required fields', () => { expect(() => { runValidator(point, {}); }).toThrow(ValidationError); }); test('validator ensures correct type of required fields', () => { expect(() => { runValidator(point, {id: 0}); }).toThrow(ValidationError); }); test('validator fills default values', () => { const p: Point = runValidator(point, {id: 'test'}).result; expect(p.color).toEqual('RED'); expect(p.x).toEqual(0); expect(p.y).toEqual(1); expect(p.properties.mass).toEqual(10); }); test('validator uses provided values', () => { const p: Point = runValidator( point, {id: 'test', x: 100, y: 200, color: 'GREEN', properties: {mass: 20}}) .result; expect(p.color).toEqual('GREEN'); expect(p.x).toEqual(100); expect(p.y).toEqual(200); expect(p.properties.mass).toEqual(20); }); test('validator keeps information about extra and invalid keys', () => { const result = runValidator(point, { id: 'test', x: 'should not be a string', extra: 'should not be here', properties: {mass: 'should be a number', weight: 'should not be here'} }); expect(result.extraKeys).toContain('extra'); expect(result.extraKeys).toContain('properties.weight'); expect(result.invalidKeys).toContain('x'); expect(result.invalidKeys).toContain('properties.mass'); }); test('validator correctly keeps track of path when reporting keys', () => { const result = runValidator(nested, { extra1: 0, deeply: { extra2: 1, nested: { array: [ {id: 'point1', x: 'should not be a string'}, {id: 'point2', extra3: 'should not be here'} ] } } }); expect(result.extraKeys).toContain('extra1'); expect(result.extraKeys).toContain('deeply.extra2'); expect(result.extraKeys).toContain('deeply.nested.array[1].extra3'); expect(result.invalidKeys).toContain('deeply.nested.array[0].x'); });