-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extended rule execution logging to Event Log
- Loading branch information
Showing
239 changed files
with
6,517 additions
and
3,092 deletions.
There are no files selected for viewing
214 changes: 214 additions & 0 deletions
214
packages/kbn-securitysolution-io-ts-types/src/default_csv_array/index.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import * as t from 'io-ts'; | ||
import { pipe } from 'fp-ts/lib/pipeable'; | ||
import { left } from 'fp-ts/lib/Either'; | ||
import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; | ||
import { defaultCsvArray } from '.'; | ||
|
||
describe('defaultCsvArray', () => { | ||
describe('Creates a schema of an array that works in the following way:', () => { | ||
type TestType = t.TypeOf<typeof TestType>; | ||
const TestType = t.union( | ||
[t.literal('foo'), t.literal('bar'), t.literal('42'), t.null, t.undefined], | ||
'TestType' | ||
); | ||
|
||
const TestCsvArray = defaultCsvArray(TestType); | ||
|
||
describe('Name of the schema', () => { | ||
it('has a default value', () => { | ||
const CsvArray = defaultCsvArray(TestType); | ||
expect(CsvArray.name).toEqual('DefaultCsvArray<TestType>'); | ||
}); | ||
|
||
it('can be overriden', () => { | ||
const CsvArray = defaultCsvArray(TestType, 'CustomName'); | ||
expect(CsvArray.name).toEqual('CustomName'); | ||
}); | ||
}); | ||
|
||
describe('Validation succeeds', () => { | ||
describe('when input is a single valid string value', () => { | ||
const cases = [{ input: 'foo' }, { input: 'bar' }, { input: '42' }]; | ||
|
||
cases.forEach(({ input }) => { | ||
it(`${input}`, () => { | ||
const decoded = TestCsvArray.decode(input); | ||
const message = pipe(decoded, foldLeftRight); | ||
const expectedOutput = [input]; // note that it's an array after decode | ||
|
||
expect(getPaths(left(message.errors))).toEqual([]); | ||
expect(message.schema).toEqual(expectedOutput); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('when input is an array of valid string values', () => { | ||
const cases = [ | ||
{ input: ['foo'] }, | ||
{ input: ['foo', 'bar'] }, | ||
{ input: ['foo', 'bar', '42'] }, | ||
]; | ||
|
||
cases.forEach(({ input }) => { | ||
it(`${input}`, () => { | ||
const decoded = TestCsvArray.decode(input); | ||
const message = pipe(decoded, foldLeftRight); | ||
const expectedOutput = input; | ||
|
||
expect(getPaths(left(message.errors))).toEqual([]); | ||
expect(message.schema).toEqual(expectedOutput); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('when input is a string which is a comma-separated array of valid values', () => { | ||
const cases = [ | ||
{ | ||
input: 'foo,bar', | ||
expectedOutput: ['foo', 'bar'], | ||
}, | ||
{ | ||
input: 'foo,bar,42', | ||
expectedOutput: ['foo', 'bar', '42'], | ||
}, | ||
]; | ||
|
||
cases.forEach(({ input, expectedOutput }) => { | ||
it(`${input}`, () => { | ||
const decoded = TestCsvArray.decode(input); | ||
const message = pipe(decoded, foldLeftRight); | ||
|
||
expect(getPaths(left(message.errors))).toEqual([]); | ||
expect(message.schema).toEqual(expectedOutput); | ||
}); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('Validation fails', () => { | ||
describe('when input is a single invalid value', () => { | ||
const cases = [ | ||
{ | ||
input: 'val', | ||
expectedErrors: ['Invalid value "val" supplied to "DefaultCsvArray<TestType>"'], | ||
}, | ||
{ | ||
input: '5', | ||
expectedErrors: ['Invalid value "5" supplied to "DefaultCsvArray<TestType>"'], | ||
}, | ||
{ | ||
input: 5, | ||
expectedErrors: ['Invalid value "5" supplied to "DefaultCsvArray<TestType>"'], | ||
}, | ||
{ | ||
input: {}, | ||
expectedErrors: ['Invalid value "{}" supplied to "DefaultCsvArray<TestType>"'], | ||
}, | ||
]; | ||
|
||
cases.forEach(({ input, expectedErrors }) => { | ||
it(`${input}`, () => { | ||
const decoded = TestCsvArray.decode(input); | ||
const message = pipe(decoded, foldLeftRight); | ||
|
||
expect(getPaths(left(message.errors))).toEqual(expectedErrors); | ||
expect(message.schema).toEqual({}); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('when input is an array of invalid values', () => { | ||
const cases = [ | ||
{ | ||
input: ['value 1', 5], | ||
expectedErrors: [ | ||
'Invalid value "value 1" supplied to "DefaultCsvArray<TestType>"', | ||
'Invalid value "5" supplied to "DefaultCsvArray<TestType>"', | ||
], | ||
}, | ||
{ | ||
input: ['value 1', 'foo'], | ||
expectedErrors: ['Invalid value "value 1" supplied to "DefaultCsvArray<TestType>"'], | ||
}, | ||
{ | ||
input: ['', 5, {}], | ||
expectedErrors: [ | ||
'Invalid value "" supplied to "DefaultCsvArray<TestType>"', | ||
'Invalid value "5" supplied to "DefaultCsvArray<TestType>"', | ||
'Invalid value "{}" supplied to "DefaultCsvArray<TestType>"', | ||
], | ||
}, | ||
]; | ||
|
||
cases.forEach(({ input, expectedErrors }) => { | ||
it(`${input}`, () => { | ||
const decoded = TestCsvArray.decode(input); | ||
const message = pipe(decoded, foldLeftRight); | ||
|
||
expect(getPaths(left(message.errors))).toEqual(expectedErrors); | ||
expect(message.schema).toEqual({}); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('when input is a string which is a comma-separated array of invalid values', () => { | ||
const cases = [ | ||
{ | ||
input: 'value 1,5', | ||
expectedErrors: [ | ||
'Invalid value "value 1" supplied to "DefaultCsvArray<TestType>"', | ||
'Invalid value "5" supplied to "DefaultCsvArray<TestType>"', | ||
], | ||
}, | ||
{ | ||
input: 'value 1,foo', | ||
expectedErrors: ['Invalid value "value 1" supplied to "DefaultCsvArray<TestType>"'], | ||
}, | ||
{ | ||
input: ',5,{}', | ||
expectedErrors: [ | ||
'Invalid value "" supplied to "DefaultCsvArray<TestType>"', | ||
'Invalid value "5" supplied to "DefaultCsvArray<TestType>"', | ||
'Invalid value "{}" supplied to "DefaultCsvArray<TestType>"', | ||
], | ||
}, | ||
]; | ||
|
||
cases.forEach(({ input, expectedErrors }) => { | ||
it(`${input}`, () => { | ||
const decoded = TestCsvArray.decode(input); | ||
const message = pipe(decoded, foldLeftRight); | ||
|
||
expect(getPaths(left(message.errors))).toEqual(expectedErrors); | ||
expect(message.schema).toEqual({}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('Validation returns default value (an empty array)', () => { | ||
describe('when input is', () => { | ||
const cases = [{ input: null }, { input: undefined }, { input: '' }, { input: [] }]; | ||
|
||
cases.forEach(({ input }) => { | ||
it(`${input}`, () => { | ||
const decoded = TestCsvArray.decode(input); | ||
const message = pipe(decoded, foldLeftRight); | ||
const expectedOutput: string[] = []; | ||
|
||
expect(getPaths(left(message.errors))).toEqual([]); | ||
expect(message.schema).toEqual(expectedOutput); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
48 changes: 48 additions & 0 deletions
48
packages/kbn-securitysolution-io-ts-types/src/default_csv_array/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import * as t from 'io-ts'; | ||
import { Either } from 'fp-ts/lib/Either'; | ||
|
||
/** | ||
* Creates a schema of an array that works in the following way: | ||
* - If input is a CSV string, it will be parsed to an array which will be validated. | ||
* - If input is an array, each item is validated to match `itemSchema`. | ||
* - If input is a single string, it is validated to match `itemSchema`. | ||
* - If input is not specified, the result will be set to [] (empty array): | ||
* - null, undefined, empty string, empty array | ||
* | ||
* In all cases when an input is valid, the resulting decoded value will be an array, | ||
* either an empty one or containing valid items. | ||
* | ||
* @param itemSchema Schema of the array's items. | ||
* @param name (Optional) Name of the resulting schema. | ||
*/ | ||
export const defaultCsvArray = <TItem>( | ||
itemSchema: t.Type<TItem>, | ||
name?: string | ||
): t.Type<TItem[]> => { | ||
return new t.Type<TItem[]>( | ||
name ?? `DefaultCsvArray<${itemSchema.name}>`, | ||
t.array(itemSchema).is, | ||
(input, context): Either<t.Errors, TItem[]> => { | ||
if (input == null) { | ||
return t.success([]); | ||
} else if (typeof input === 'string') { | ||
if (input === '') { | ||
return t.success([]); | ||
} else { | ||
return t.array(itemSchema).validate(input.split(','), context); | ||
} | ||
} else { | ||
return t.array(itemSchema).validate(input, context); | ||
} | ||
}, | ||
t.identity | ||
); | ||
}; |
106 changes: 106 additions & 0 deletions
106
packages/kbn-securitysolution-io-ts-types/src/default_value/index.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import * as t from 'io-ts'; | ||
import { pipe } from 'fp-ts/lib/pipeable'; | ||
import { left } from 'fp-ts/lib/Either'; | ||
import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; | ||
import { defaultValue } from '.'; | ||
|
||
describe('defaultValue', () => { | ||
describe('Creates a schema that sets a default value if the input value is not specified', () => { | ||
type TestType = t.TypeOf<typeof TestType>; | ||
const TestType = t.union([t.string, t.number, t.null, t.undefined], 'TestType'); | ||
|
||
const DefaultValue = defaultValue(TestType, 42); | ||
|
||
describe('Name of the schema', () => { | ||
it('has a default value', () => { | ||
expect(defaultValue(TestType, 42).name).toEqual('DefaultValue<TestType>'); | ||
}); | ||
|
||
it('can be overriden', () => { | ||
expect(defaultValue(TestType, 42, 'CustomName').name).toEqual('CustomName'); | ||
}); | ||
}); | ||
|
||
describe('Validation succeeds', () => { | ||
describe('when input is a valid value', () => { | ||
const cases = [ | ||
{ input: 'foo' }, | ||
{ input: '42' }, | ||
{ input: 42 }, | ||
// including all "falsey" values which are not null or undefined | ||
{ input: '' }, | ||
{ input: 0 }, | ||
]; | ||
|
||
cases.forEach(({ input }) => { | ||
it(`${input}`, () => { | ||
const decoded = DefaultValue.decode(input); | ||
const message = pipe(decoded, foldLeftRight); | ||
const expectedOutput = input; | ||
|
||
expect(getPaths(left(message.errors))).toEqual([]); | ||
expect(message.schema).toEqual(expectedOutput); | ||
}); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('Validation fails', () => { | ||
describe('when input is an invalid value', () => { | ||
const cases = [ | ||
{ | ||
input: {}, | ||
expectedErrors: ['Invalid value "{}" supplied to "DefaultValue<TestType>"'], | ||
}, | ||
{ | ||
input: { foo: 42 }, | ||
expectedErrors: ['Invalid value "{"foo":42}" supplied to "DefaultValue<TestType>"'], | ||
}, | ||
{ | ||
input: [], | ||
expectedErrors: ['Invalid value "[]" supplied to "DefaultValue<TestType>"'], | ||
}, | ||
{ | ||
input: ['foo', 42], | ||
expectedErrors: ['Invalid value "["foo",42]" supplied to "DefaultValue<TestType>"'], | ||
}, | ||
]; | ||
|
||
cases.forEach(({ input, expectedErrors }) => { | ||
it(`${input}`, () => { | ||
const decoded = DefaultValue.decode(input); | ||
const message = pipe(decoded, foldLeftRight); | ||
|
||
expect(getPaths(left(message.errors))).toEqual(expectedErrors); | ||
expect(message.schema).toEqual({}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('Validation returns specified default value', () => { | ||
describe('when input is', () => { | ||
const cases = [{ input: null }, { input: undefined }]; | ||
|
||
cases.forEach(({ input }) => { | ||
it(`${input}`, () => { | ||
const decoded = DefaultValue.decode(input); | ||
const message = pipe(decoded, foldLeftRight); | ||
const expectedOutput = 42; | ||
|
||
expect(getPaths(left(message.errors))).toEqual([]); | ||
expect(message.schema).toEqual(expectedOutput); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.