mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
# Backport This will backport the following commits from `main` to `8.8`: - [[Security Solution][Alerts] fix missing fields merge on alerts creation (#157142)](https://github.com/elastic/kibana/pull/157142) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Vitalii Dmyterko","email":"92328789+vitaliidm@users.noreply.github.com"},"sourceCommit":{"committedDate":"2023-05-26T09:11:16Z","message":"[Security Solution][Alerts] fix missing fields merge on alerts creation (#157142)\n\n## Summary\r\n\r\n- addresses https://github.com/elastic/kibana/issues/152446\r\n- now, instead of string path to merged field, array path is used in\r\nmerging utilities, that allows to work with keys, which have `dot` in\r\nnames. For exampe, instead of `a.b.c.d` - `['a', 'b.c', 'd']`\r\n- addresses https://github.com/elastic/kibana/issues/153607, by cloning\r\nsource document, used in tests\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: Ievgen Sorokopud <e40pud@gmail.com>\r\nCo-authored-by: Ryland Herrick <ryalnd@gmail.com>","sha":"11fba5746fb44e829f76c1299f78f110a12cac25","branchLabelMapping":{"^v8.9.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team: SecuritySolution","backport:prev-minor","v8.8.0","v8.9.0","Team:Detection Engine"],"number":157142,"url":"https://github.com/elastic/kibana/pull/157142","mergeCommit":{"message":"[Security Solution][Alerts] fix missing fields merge on alerts creation (#157142)\n\n## Summary\r\n\r\n- addresses https://github.com/elastic/kibana/issues/152446\r\n- now, instead of string path to merged field, array path is used in\r\nmerging utilities, that allows to work with keys, which have `dot` in\r\nnames. For exampe, instead of `a.b.c.d` - `['a', 'b.c', 'd']`\r\n- addresses https://github.com/elastic/kibana/issues/153607, by cloning\r\nsource document, used in tests\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: Ievgen Sorokopud <e40pud@gmail.com>\r\nCo-authored-by: Ryland Herrick <ryalnd@gmail.com>","sha":"11fba5746fb44e829f76c1299f78f110a12cac25"}},"sourceBranch":"main","suggestedTargetBranches":["8.8"],"targetPullRequestStates":[{"branch":"8.8","label":"v8.8.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.9.0","labelRegex":"^v8.9.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/157142","number":157142,"mergeCommit":{"message":"[Security Solution][Alerts] fix missing fields merge on alerts creation (#157142)\n\n## Summary\r\n\r\n- addresses https://github.com/elastic/kibana/issues/152446\r\n- now, instead of string path to merged field, array path is used in\r\nmerging utilities, that allows to work with keys, which have `dot` in\r\nnames. For exampe, instead of `a.b.c.d` - `['a', 'b.c', 'd']`\r\n- addresses https://github.com/elastic/kibana/issues/153607, by cloning\r\nsource document, used in tests\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\n---------\r\n\r\nCo-authored-by: Ievgen Sorokopud <e40pud@gmail.com>\r\nCo-authored-by: Ryland Herrick <ryalnd@gmail.com>","sha":"11fba5746fb44e829f76c1299f78f110a12cac25"}}]}] BACKPORT--> Co-authored-by: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com>
This commit is contained in:
parent
d5e06a0bc2
commit
2b5725d558
8 changed files with 666 additions and 240 deletions
File diff suppressed because it is too large
Load diff
|
@ -17,6 +17,7 @@ import { isPrimitive } from '../utils/is_primitive';
|
|||
import { isArrayOfPrimitives } from '../utils/is_array_of_primitives';
|
||||
import { isTypeObject } from '../utils/is_type_object';
|
||||
import { isPathValid } from '../utils/is_path_valid';
|
||||
import { buildFieldsKeyAsArrayMap } from '../utils/build_fields_key_as_array_map';
|
||||
|
||||
/**
|
||||
* Merges all of "doc._source" with its "doc.fields" on a "best effort" basis. See ../README.md for more information
|
||||
|
@ -33,9 +34,12 @@ export const mergeAllFieldsWithSource: MergeStrategyFunction = ({ doc, ignoreFie
|
|||
const fields = doc.fields ?? {};
|
||||
const fieldEntries = Object.entries(fields);
|
||||
const filteredEntries = filterFieldEntries(fieldEntries, ignoreFields);
|
||||
const fieldsKeyMap = buildFieldsKeyAsArrayMap(source);
|
||||
|
||||
const transformedSource = filteredEntries.reduce(
|
||||
(merged, [fieldsKey, fieldsValue]: [string, FieldsType]) => {
|
||||
(merged, [fieldsKeyAsString, fieldsValue]: [string, FieldsType]) => {
|
||||
const fieldsKey = fieldsKeyMap[fieldsKeyAsString] ?? fieldsKeyAsString;
|
||||
|
||||
if (
|
||||
hasEarlyReturnConditions({
|
||||
fieldsValue,
|
||||
|
@ -101,7 +105,7 @@ const hasEarlyReturnConditions = ({
|
|||
merged,
|
||||
}: {
|
||||
fieldsValue: FieldsType;
|
||||
fieldsKey: string;
|
||||
fieldsKey: string[] | string;
|
||||
merged: SignalSource;
|
||||
}) => {
|
||||
const valueInMergedDocument = get(fieldsKey, merged);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { performance } from 'perf_hooks';
|
||||
import { mergeMissingFieldsWithSource } from './merge_missing_fields_with_source';
|
||||
import type { SignalSourceHit } from '../../../types';
|
||||
|
@ -43,7 +44,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
|
||||
test('when source is "undefined", merged doc is "undefined"', () => {
|
||||
const _source: SignalSourceHit['_source'] = {};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -52,7 +53,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: [],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -61,7 +62,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: 'value',
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -70,7 +71,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: ['value'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -79,7 +80,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: ['value_1', 'value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -88,7 +89,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: { bar: 'some value' },
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -97,7 +98,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: [{ bar: 'some value' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -106,7 +107,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: [{ bar: 'some value' }, { foo: 'some other value' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -132,7 +133,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
'foo.bar': [],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -141,7 +142,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
'foo.bar': 'value',
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -150,7 +151,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
'foo.bar': ['value'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -159,7 +160,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
'foo.bar': ['value_1', 'value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -168,7 +169,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: { bar: 'some value' },
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -177,7 +178,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: [{ bar: 'some value' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -186,7 +187,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: [{ bar: 'some value' }, { foo: 'some other value' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -216,7 +217,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: { bar: [] },
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -225,7 +226,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: { bar: 'value' },
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -234,7 +235,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: { bar: ['value'] },
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -243,7 +244,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: { bar: ['value_1', 'value_2'] },
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -252,7 +253,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: { bar: { mars: 'some value' } },
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -261,7 +262,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: { bar: [{ mars: 'some value' }] },
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -270,7 +271,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: { bar: [{ mars: 'some value' }, { mars: 'some other value' }] },
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -308,7 +309,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
'bar.foo': [],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -317,7 +318,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
'bar.foo': 'value',
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -326,7 +327,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
'bar.foo': ['value'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -335,7 +336,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
'bar.foo': ['value_1', 'value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -344,7 +345,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: { bar: 'some value' },
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -353,7 +354,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: [{ bar: 'some value' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -362,7 +363,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
foo: [{ bar: 'some value' }, { foo: 'some other value' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -381,7 +382,11 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const _source: SignalSourceHit['_source'] = {
|
||||
'bar.foo': [],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields: bigFields };
|
||||
const doc: SignalSourceHit = {
|
||||
...emptyEsResult(),
|
||||
_source: cloneDeep(_source),
|
||||
fields: bigFields,
|
||||
};
|
||||
const start = performance.now();
|
||||
// we don't care about the response just determining performance
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
|
@ -408,7 +413,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>({
|
||||
foo: {
|
||||
|
@ -421,7 +426,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>({
|
||||
foo: {
|
||||
|
@ -434,7 +439,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>({});
|
||||
});
|
||||
|
@ -443,7 +448,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }, { zed: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>({});
|
||||
});
|
||||
|
@ -468,7 +473,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -477,7 +482,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -486,7 +491,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
foo: [{ bar: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -495,7 +500,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
foo: [{ bar: 'other_value_1' }, { bar: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -519,7 +524,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -528,7 +533,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -537,7 +542,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -546,7 +551,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }, { zed: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -572,7 +577,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -581,7 +586,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -590,7 +595,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -599,7 +604,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }, { zed: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -623,7 +628,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -632,7 +637,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -641,7 +646,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -650,7 +655,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }, { zed: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -674,7 +679,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -683,7 +688,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -692,7 +697,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -701,7 +706,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }, { zed: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -725,7 +730,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -734,7 +739,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -743,7 +748,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -752,7 +757,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }, { zed: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -778,7 +783,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -787,7 +792,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -796,7 +801,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -805,7 +810,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }, { zed: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -829,7 +834,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -838,7 +843,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -847,7 +852,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -856,7 +861,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }, { zed: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -882,7 +887,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -891,7 +896,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -900,7 +905,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -909,7 +914,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }, { zed: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -933,7 +938,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -942,7 +947,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -951,7 +956,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ mars: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -960,7 +965,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ mars: 'other_value_1' }, { mars: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -986,7 +991,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -995,7 +1000,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1004,7 +1009,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1013,7 +1018,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }, { zed: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1037,7 +1042,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1046,7 +1051,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1055,7 +1060,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1064,7 +1069,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ zed: 'other_value_1' }, { zed: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1088,7 +1093,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1097,7 +1102,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1106,7 +1111,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ mars: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1115,7 +1120,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ mars: 'other_value_1' }, { mars: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1139,7 +1144,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1148,7 +1153,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1', 'other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1157,7 +1162,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ mars: 'other_value_1' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1166,7 +1171,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': [{ mars: 'other_value_1' }, { mars: 'other_value_2' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1192,7 +1197,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['other_value_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1204,7 +1209,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
'foo.bar': ['value_1', 'value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1228,7 +1233,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
bar: ['bar_other_value_1'],
|
||||
'bar.keyword': ['bar_other_value_keyword_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1246,7 +1251,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'host.hostname': ['hostname_other_value_1'],
|
||||
'host.hostname.keyword': ['hostname_other_value_keyword_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1266,7 +1271,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'foo.host.hostname': ['hostname_other_value_1'],
|
||||
'foo.host.hostname.keyword': ['hostname_other_value_keyword_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1277,7 +1282,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
foo: ['other_value_1'],
|
||||
'foo.bar': ['other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>({
|
||||
foo: 'other_value_1',
|
||||
|
@ -1295,7 +1300,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'process.command_line.text': ['string longer than 10 characters'],
|
||||
'@timestamp': ['2023-02-10T10:15:50.000Z'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1311,7 +1316,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'process.command_line.text': ['string longer than 10 characters'],
|
||||
'@timestamp': ['2023-02-10T10:15:50.000Z'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1329,7 +1334,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'host.hostname': ['hostname_other_value_1'],
|
||||
'host.hostname.keyword': ['hostname_other_value_keyword_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1345,7 +1350,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'foo.host.hostname': ['hostname_other_value_1'],
|
||||
'foo.host.hostname.keyword': ['hostname_other_value_keyword_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1357,7 +1362,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'foo.bar': ['other_value_2'],
|
||||
'foo.bar.zed': ['zed_other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>({
|
||||
foo: 'other_value_1',
|
||||
|
@ -1374,7 +1379,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'process.command_line.text': ['string longer than 10 characters'],
|
||||
'@timestamp': ['2023-02-10T10:15:50.000Z'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1389,7 +1394,112 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'process.command_line.text': ['string longer than 10 characters'],
|
||||
'@timestamp': ['2023-02-10T10:15:50.000Z'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mixed flattened and nested keys for the _source', () => {
|
||||
test('merges fields into source if it is empty', () => {
|
||||
const _source: SignalSourceHit['_source'] = {
|
||||
'email.headers': {},
|
||||
};
|
||||
|
||||
const fields: SignalSourceHit['fields'] = {
|
||||
'email.headers.x-test': ['from fields'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>({
|
||||
email: {
|
||||
headers: {
|
||||
'x-test': 'from fields',
|
||||
},
|
||||
},
|
||||
// preserves conflicting keys if values contain empty objects
|
||||
'email.headers': {},
|
||||
});
|
||||
});
|
||||
|
||||
test('merges fields into source if it is "undefined"', () => {
|
||||
const _source: SignalSourceHit['_source'] = {
|
||||
'email.headers': { 'x-test': undefined },
|
||||
};
|
||||
|
||||
const fields: SignalSourceHit['fields'] = {
|
||||
'email.headers.x-test': ['from fields'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>({
|
||||
'email.headers': {
|
||||
'x-test': 'from fields',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('does not merge fields into source', () => {
|
||||
const _source: SignalSourceHit['_source'] = {
|
||||
'email.headers': { 'x-test': 'a' },
|
||||
};
|
||||
|
||||
const fields: SignalSourceHit['fields'] = {
|
||||
'email.headers.x-test': ['from fields'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
||||
test('does not merge fields into source if source value is array', () => {
|
||||
const _source: SignalSourceHit['_source'] = {
|
||||
'email.headers': { 'x-test': ['a'] },
|
||||
};
|
||||
|
||||
const fields: SignalSourceHit['fields'] = {
|
||||
'email.headers.x-test': ['from fields'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
||||
test('does not merge fields into source if only source has nested fields', () => {
|
||||
const _source: SignalSourceHit['_source'] = {
|
||||
'a.b': { c: [{ d: ['1'] }, { d: ['2'] }] },
|
||||
};
|
||||
|
||||
const fields: SignalSourceHit['fields'] = {
|
||||
'a.b.c.d': ['1', '2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
||||
test('does not merge nested fields into source if source has nested fields', () => {
|
||||
const _source: SignalSourceHit['_source'] = {
|
||||
'a.b': { c: [{ d: ['1'] }, { d: ['2'] }] },
|
||||
};
|
||||
|
||||
const fields: SignalSourceHit['fields'] = {
|
||||
'a.b.c': [{ d: '3 ' }, { d: '4' }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
||||
test('does not duplicate fields in result document if field is equal to source mixed property', () => {
|
||||
const _source: SignalSourceHit['_source'] = {
|
||||
'email.headers': { 'x-test': 'a' },
|
||||
};
|
||||
|
||||
const fields: SignalSourceHit['fields'] = {
|
||||
'email.headers.x-test': ['a'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1414,7 +1524,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'foo.bar': ['other_value_1'],
|
||||
'foo.mars': ['other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1434,7 +1544,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'foo.zed.bar': ['other_value_1'],
|
||||
'foo.zed.mars': ['other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1449,7 +1559,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
foo: [{ bar: ['single_value'], zed: ['single_value'] }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>({});
|
||||
});
|
||||
|
@ -1466,7 +1576,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
const fields: SignalSourceHit['fields'] = {
|
||||
foo: [{ bar: ['single_value'], zed: ['single_value'] }],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source;
|
||||
expect(merged).toEqual<ReturnTypeMergeFieldsWithSource>(_source);
|
||||
});
|
||||
|
@ -1483,7 +1593,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'value.should.ignore': ['other_value_2'], // string value should ignore this
|
||||
'_odd.value': ['other_value_2'], // Regex should ignore this value of: /[_]+/
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({
|
||||
doc,
|
||||
ignoreFields: ['value.should.ignore', '/[_]+/'],
|
||||
|
@ -1502,7 +1612,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'value.should.work': ['other_value_2'],
|
||||
'_odd.value': ['other_value_2'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({
|
||||
doc,
|
||||
ignoreFields: ['other.string', '/[z]+/'], // Neither of these two should match anything
|
||||
|
@ -1533,7 +1643,7 @@ describe('merge_missing_fields_with_source', () => {
|
|||
'foo.bar': ['other_value_1'],
|
||||
_ignored: ['other_value_1'],
|
||||
};
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields };
|
||||
const doc: SignalSourceHit = { ...emptyEsResult(), _source: cloneDeep(_source), fields };
|
||||
const merged = mergeMissingFieldsWithSource({
|
||||
doc,
|
||||
ignoreFields: [],
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { get } from 'lodash/fp';
|
||||
import { set } from '@kbn/safer-lodash-set';
|
||||
|
||||
import type { SignalSource } from '../../../types';
|
||||
import { filterFieldEntries } from '../utils/filter_field_entries';
|
||||
import type { FieldsType, MergeStrategyFunction } from '../types';
|
||||
|
@ -14,6 +15,7 @@ import { recursiveUnboxingFields } from '../utils/recursive_unboxing_fields';
|
|||
import { isTypeObject } from '../utils/is_type_object';
|
||||
import { isNestedObject } from '../utils/is_nested_object';
|
||||
import { isPathValid } from '../utils/is_path_valid';
|
||||
import { buildFieldsKeyAsArrayMap } from '../utils/build_fields_key_as_array_map';
|
||||
|
||||
/**
|
||||
* Merges only missing sections of "doc._source" with its "doc.fields" on a "best effort" basis. See ../README.md for more information
|
||||
|
@ -29,9 +31,11 @@ export const mergeMissingFieldsWithSource: MergeStrategyFunction = ({ doc, ignor
|
|||
const fields = doc.fields ?? {};
|
||||
const fieldEntries = Object.entries(fields);
|
||||
const filteredEntries = filterFieldEntries(fieldEntries, ignoreFields);
|
||||
const fieldsKeyMap = buildFieldsKeyAsArrayMap(source);
|
||||
|
||||
const transformedSource = filteredEntries.reduce(
|
||||
(merged, [fieldsKey, fieldsValue]: [string, FieldsType]) => {
|
||||
(merged, [fieldsKeyAsString, fieldsValue]: [string, FieldsType]) => {
|
||||
const fieldsKey = fieldsKeyMap[fieldsKeyAsString] ?? fieldsKeyAsString;
|
||||
if (
|
||||
hasEarlyReturnConditions({
|
||||
fieldsValue,
|
||||
|
@ -72,7 +76,7 @@ const hasEarlyReturnConditions = ({
|
|||
merged,
|
||||
}: {
|
||||
fieldsValue: FieldsType;
|
||||
fieldsKey: string;
|
||||
fieldsKey: string[] | string;
|
||||
merged: SignalSource;
|
||||
}) => {
|
||||
const valueInMergedDocument = get(fieldsKey, merged);
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { buildFieldsKeyAsArrayMap } from './build_fields_key_as_array_map';
|
||||
|
||||
describe('buildFieldsKeyAsArrayMap()', () => {
|
||||
it('returns primitive type if it passed as source', () => {
|
||||
// @ts-expect-error
|
||||
expect(buildFieldsKeyAsArrayMap(1)).toEqual({});
|
||||
// @ts-expect-error
|
||||
expect(buildFieldsKeyAsArrayMap(Infinity)).toEqual({});
|
||||
// @ts-expect-error
|
||||
expect(buildFieldsKeyAsArrayMap(NaN)).toEqual({});
|
||||
// @ts-expect-error
|
||||
expect(buildFieldsKeyAsArrayMap(false)).toEqual({});
|
||||
// @ts-expect-error
|
||||
expect(buildFieldsKeyAsArrayMap(null)).toEqual({});
|
||||
// @ts-expect-error
|
||||
expect(buildFieldsKeyAsArrayMap(undefined)).toEqual({});
|
||||
// @ts-expect-error
|
||||
expect(buildFieldsKeyAsArrayMap([])).toEqual({});
|
||||
});
|
||||
it('builds map for nested source', () => {
|
||||
expect(buildFieldsKeyAsArrayMap({ a: 'b' })).toEqual({ a: ['a'] });
|
||||
expect(buildFieldsKeyAsArrayMap({ a: ['b'] })).toEqual({ a: ['a'] });
|
||||
expect(buildFieldsKeyAsArrayMap({ a: { b: { c: 1 } } })).toEqual({
|
||||
a: ['a'],
|
||||
'a.b': ['a', 'b'],
|
||||
'a.b.c': ['a', 'b', 'c'],
|
||||
});
|
||||
expect(buildFieldsKeyAsArrayMap({ a: { b: 'c' }, d: { e: 'f' } })).toEqual({
|
||||
a: ['a'],
|
||||
'a.b': ['a', 'b'],
|
||||
d: ['d'],
|
||||
'd.e': ['d', 'e'],
|
||||
});
|
||||
});
|
||||
|
||||
it('builds map for flattened source', () => {
|
||||
expect(buildFieldsKeyAsArrayMap({ a: 'b' })).toEqual({ a: ['a'] });
|
||||
expect(buildFieldsKeyAsArrayMap({ 'a.b.c': 1 })).toEqual({ 'a.b.c': ['a.b.c'] });
|
||||
expect(buildFieldsKeyAsArrayMap({ 'a.b': 'c', 'd.e': 'f' })).toEqual({
|
||||
'a.b': ['a.b'],
|
||||
'd.e': ['d.e'],
|
||||
});
|
||||
});
|
||||
|
||||
it('builds map for arrays in a path', () => {
|
||||
expect(buildFieldsKeyAsArrayMap({ a: { b: [{ c: 1 }, { c: 2 }] } })).toEqual({
|
||||
a: ['a'],
|
||||
'a.b': ['a', 'b'],
|
||||
'a.b.c': ['a', 'b', 'c'],
|
||||
});
|
||||
});
|
||||
|
||||
it('builds map for mixed nested and flattened in a path', () => {
|
||||
expect(
|
||||
buildFieldsKeyAsArrayMap({
|
||||
'a.b': { c: { d: 1 } },
|
||||
})
|
||||
).toEqual({
|
||||
'a.b': ['a.b'],
|
||||
'a.b.c': ['a.b', 'c'],
|
||||
'a.b.c.d': ['a.b', 'c', 'd'],
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { isPlainObject, isArray } from 'lodash';
|
||||
|
||||
import type { SearchTypes } from '../../../../../../../common/detection_engine/types';
|
||||
|
||||
const isObjectTypeGuard = (value: SearchTypes): value is Record<string, SearchTypes> => {
|
||||
return isPlainObject(value);
|
||||
};
|
||||
|
||||
function traverseSource(
|
||||
document: SearchTypes,
|
||||
result: Record<string, string[]> = {},
|
||||
prefix: string[] = []
|
||||
): Record<string, string[]> {
|
||||
if (prefix.length) {
|
||||
result[prefix.join('.')] = prefix;
|
||||
}
|
||||
|
||||
if (isObjectTypeGuard(document)) {
|
||||
for (const [key, value] of Object.entries(document)) {
|
||||
const path = [...prefix, key];
|
||||
|
||||
traverseSource(value, result, path);
|
||||
}
|
||||
} else if (isArray(document)) {
|
||||
// for array of primitive values we can call traverseSource once
|
||||
if (isPlainObject(document[0])) {
|
||||
traverseSource(document[0], result, prefix);
|
||||
} else {
|
||||
document.forEach((doc) => {
|
||||
traverseSource(doc, result, prefix);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* takes object document and creates map of string field keys to array field keys
|
||||
* source `{ 'a.b': { c: { d: 1 } } }`
|
||||
* will result in map: `{
|
||||
* 'a.b': ['a.b'],
|
||||
* 'a.b.c': ['a.b', 'c'],
|
||||
* 'a.b.c.d': ['a.b', 'c', 'd'],
|
||||
* }`
|
||||
* @param document - Record<string, SearchTypes>
|
||||
**/
|
||||
export function buildFieldsKeyAsArrayMap(
|
||||
document: Record<string, SearchTypes>
|
||||
): Record<string, string[]> {
|
||||
if (!isPlainObject(document)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return traverseSource(document);
|
||||
}
|
|
@ -8,67 +8,135 @@
|
|||
import { isPathValid } from './is_path_valid';
|
||||
|
||||
describe('isPathValid', () => {
|
||||
test('not valid when empty string and empty object', () => {
|
||||
expect(isPathValid('', {})).toEqual(false);
|
||||
test('not valid when empty array is key', () => {
|
||||
expect(isPathValid([], {})).toEqual(false);
|
||||
});
|
||||
|
||||
test('valid when empty string is key', () => {
|
||||
expect(isPathValid('', {})).toEqual(true);
|
||||
expect(isPathValid([''], {})).toEqual(true);
|
||||
});
|
||||
|
||||
test('valid when a path and empty object', () => {
|
||||
expect(isPathValid(['a', 'b', 'c'], {})).toEqual(true);
|
||||
expect(isPathValid('a.b.c', {})).toEqual(true);
|
||||
});
|
||||
|
||||
test('not valid when a path and an array exists', () => {
|
||||
expect(isPathValid(['a'], { a: [] })).toEqual(false);
|
||||
expect(isPathValid('a', { a: [] })).toEqual(false);
|
||||
});
|
||||
|
||||
test('not valid when a path and primitive value exists', () => {
|
||||
expect(isPathValid(['a'], { a: 'test' })).toEqual(false);
|
||||
expect(isPathValid(['a'], { a: 1 })).toEqual(false);
|
||||
expect(isPathValid(['a'], { a: true })).toEqual(false);
|
||||
|
||||
expect(isPathValid('a', { a: 'test' })).toEqual(false);
|
||||
expect(isPathValid('a', { a: 1 })).toEqual(false);
|
||||
expect(isPathValid('a', { a: true })).toEqual(false);
|
||||
});
|
||||
|
||||
test('valid when a path and object value exists', () => {
|
||||
expect(isPathValid(['a'], { a: {} })).toEqual(true);
|
||||
|
||||
expect(isPathValid('a', { a: {} })).toEqual(true);
|
||||
});
|
||||
|
||||
test('not valid when a path and an array exists within the parent path at level 1', () => {
|
||||
expect(isPathValid(['a', 'b'], { a: [] })).toEqual(false);
|
||||
|
||||
expect(isPathValid('a.b', { a: [] })).toEqual(false);
|
||||
});
|
||||
|
||||
test('not valid when a path and primitive value exists within the parent path at level 1', () => {
|
||||
expect(isPathValid(['a', 'b'], { a: 'test' })).toEqual(false);
|
||||
expect(isPathValid(['a', 'b'], { a: 1 })).toEqual(false);
|
||||
expect(isPathValid(['a', 'b'], { a: true })).toEqual(false);
|
||||
|
||||
expect(isPathValid('a.b', { a: 'test' })).toEqual(false);
|
||||
expect(isPathValid('a.b', { a: 1 })).toEqual(false);
|
||||
expect(isPathValid('a.b', { a: true })).toEqual(false);
|
||||
});
|
||||
|
||||
test('valid when a path and object value exists within the parent path at level 1', () => {
|
||||
expect(isPathValid(['a', 'b'], { a: {} })).toEqual(true);
|
||||
|
||||
expect(isPathValid('a.b', { a: {} })).toEqual(true);
|
||||
});
|
||||
|
||||
test('not valid when a path and an array exists within the parent path at level 2', () => {
|
||||
expect(isPathValid(['a', 'b', 'c'], { a: { b: [] } })).toEqual(false);
|
||||
expect(isPathValid(['a', 'b', 'c'], { 'a.b': [] })).toEqual(false);
|
||||
|
||||
expect(isPathValid('a.b.c', { a: { b: [] } })).toEqual(false);
|
||||
expect(isPathValid('a.b.c', { 'a.b': [] })).toEqual(false);
|
||||
});
|
||||
|
||||
test('not valid when a path and primitive value exists within the parent path at level 2', () => {
|
||||
expect(isPathValid('a.b', { a: { b: 'test' } })).toEqual(false);
|
||||
expect(isPathValid('a.b', { a: { b: 1 } })).toEqual(false);
|
||||
expect(isPathValid('a.b', { a: { b: true } })).toEqual(false);
|
||||
expect(isPathValid(['a', 'b', 'c'], { a: { b: 'test' } })).toEqual(false);
|
||||
expect(isPathValid(['a', 'b', 'c'], { a: { b: 1 } })).toEqual(false);
|
||||
expect(isPathValid(['a', 'b', 'c'], { a: { b: true } })).toEqual(false);
|
||||
expect(isPathValid(['a', 'b', 'c'], { 'a.b': true })).toEqual(false);
|
||||
|
||||
expect(isPathValid('a.b.c', { a: { b: 'test' } })).toEqual(false);
|
||||
expect(isPathValid('a.b.c', { a: { b: 1 } })).toEqual(false);
|
||||
expect(isPathValid('a.b.c', { a: { b: true } })).toEqual(false);
|
||||
expect(isPathValid('a.b.c', { 'a.b': true })).toEqual(false);
|
||||
});
|
||||
|
||||
test('valid when a path and object value exists within the parent path at level 2', () => {
|
||||
test('valid when a path and object value exists within the parent path at the last level 2', () => {
|
||||
expect(isPathValid(['a', 'b'], { a: { b: {} } })).toEqual(true);
|
||||
|
||||
expect(isPathValid('a.b', { a: { b: {} } })).toEqual(true);
|
||||
});
|
||||
|
||||
test('not valid when a path and an array exists within the parent path at level 3', () => {
|
||||
test('not valid when a path and an array exists within the parent path at the last level 3', () => {
|
||||
expect(isPathValid(['a', 'b', 'c'], { a: { b: { c: [] } } })).toEqual(false);
|
||||
|
||||
expect(isPathValid('a.b.c', { a: { b: { c: [] } } })).toEqual(false);
|
||||
});
|
||||
|
||||
test('not valid when a path and primitive value exists within the parent path at level 3', () => {
|
||||
test('not valid when a path and primitive value exists within the parent path at the last level 3', () => {
|
||||
expect(isPathValid(['a', 'b', 'c'], { a: { b: { c: 'test' } } })).toEqual(false);
|
||||
expect(isPathValid(['a', 'b', 'c'], { a: { b: { c: 1 } } })).toEqual(false);
|
||||
expect(isPathValid(['a', 'b', 'c'], { a: { b: { c: true } } })).toEqual(false);
|
||||
expect(isPathValid(['a', 'b', 'c'], { 'a.b.c': true })).toEqual(false);
|
||||
|
||||
expect(isPathValid('a.b.c', { a: { b: { c: 'test' } } })).toEqual(false);
|
||||
expect(isPathValid('a.b.c', { a: { b: { c: 1 } } })).toEqual(false);
|
||||
expect(isPathValid('a.b.c', { a: { b: { c: true } } })).toEqual(false);
|
||||
expect(isPathValid('a.b.c', { 'a.b.c': true })).toEqual(false);
|
||||
});
|
||||
|
||||
test('valid when a path and object value exists within the parent path at level 3', () => {
|
||||
test('valid when a path and object value exists within the parent path at the last level 3', () => {
|
||||
expect(isPathValid(['a', 'b', 'c'], { a: { b: { c: {} } } })).toEqual(true);
|
||||
expect(isPathValid(['a', 'b', 'c'], { 'a.b.c': {} })).toEqual(true);
|
||||
|
||||
expect(isPathValid('a.b.c', { a: { b: { c: {} } } })).toEqual(true);
|
||||
expect(isPathValid('a.b.c', { 'a.b.c': {} })).toEqual(true);
|
||||
});
|
||||
|
||||
test('valid when any key has dot notation', () => {
|
||||
expect(isPathValid(['a', 'b.c'], { a: { 'b.c': {} } })).toEqual(true);
|
||||
expect(isPathValid(['a.b', 'c'], { 'a.b': { c: {} } })).toEqual(true);
|
||||
expect(isPathValid(['a', 'b.c', 'd'], { a: { 'b.c': { d: {} } } })).toEqual(true);
|
||||
});
|
||||
|
||||
test('not valid when any key has dot notation and array is present in source on the last level', () => {
|
||||
expect(isPathValid(['a', 'b.c'], { a: { 'b.c': [] } })).toEqual(false);
|
||||
expect(isPathValid(['a.b', 'c'], { 'a.b': { c: [] } })).toEqual(false);
|
||||
expect(isPathValid(['a', 'b.c', 'd'], { a: { 'b.c': { d: [] } } })).toEqual(false);
|
||||
});
|
||||
|
||||
test('not valid when any key has dot notation and primitive value is present in source on the last level', () => {
|
||||
expect(isPathValid(['a', 'b.c'], { a: { 'b.c': 1 } })).toEqual(false);
|
||||
expect(isPathValid(['a.b', 'c'], { 'a.b': { c: 1 } })).toEqual(false);
|
||||
expect(isPathValid(['a', 'b.c', 'd'], { a: { 'b.c': { d: 1 } } })).toEqual(false);
|
||||
});
|
||||
|
||||
test('not valid when any key has dot notation and array is present in source on level 2', () => {
|
||||
expect(isPathValid(['a', 'b.c', 'd'], { a: { 'b.c': [] } })).toEqual(false);
|
||||
expect(isPathValid(['a.b', 'c', 'd'], { 'a.b': { c: [] } })).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,15 +16,21 @@ import type { SignalSource } from '../../../types';
|
|||
* @param source The source document
|
||||
* @returns boolean
|
||||
*/
|
||||
export const isPathValid = (path: string, source: SignalSource): boolean => {
|
||||
if (!path) {
|
||||
export const isPathValid = (path: string[] | string, source: SignalSource): boolean => {
|
||||
if (path == null) {
|
||||
return false;
|
||||
}
|
||||
const splitPath = path.split('.');
|
||||
const pathAsArray = typeof path === 'string' ? path.split('.') : path;
|
||||
|
||||
return splitPath.every((_, index, array) => {
|
||||
const newPath = [...array].splice(0, index + 1).join('.');
|
||||
const valueToCheck = get(newPath, source);
|
||||
if (pathAsArray.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return pathAsArray.every((_, index, array) => {
|
||||
const newPath = [...array].splice(0, index + 1);
|
||||
// _.get won't retrieve value of flattened key 'a.b' when receives path ['a', 'b'].
|
||||
// so we would try to call _.get with dot-notation path if array path results in undefined
|
||||
const valueToCheck = get(newPath, source) ?? get(newPath.join('.'), source);
|
||||
return valueToCheck === undefined || isPlainObject(valueToCheck);
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue