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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,31 @@ test('ReactUnipika: first render', async ({mount, expectScreenshot, page}) => {
await expectScreenshot({component: page});
});

test('ReactUnipika: search key match', async ({mount, expectScreenshot, page}) => {
await mount(<Stories.Json />, {width: 1280});

await page.getByTestId('qa:structuredyson:search').locator('input').fill('timestamp');

await expectScreenshot({component: page});
});

test('ReactUnipika: search key match in collapsed tree', async ({
mount,
expectScreenshot,
page,
}) => {
await mount(<Stories.Json />, {width: 1280});

await page.getByTestId('qa:structuredyson:search').locator('input').fill('timestamp');
await page.getByTestId('qa:structuredyson:collapse-all').click();

await expectScreenshot({component: page});
});

test('ReactUnipika: search next', async ({mount, expectScreenshot, page}) => {
await mount(<Stories.Json />, {width: 1280});

await page.getByTestId('qa:structuredyson:search').locator('input').fill('level10_item0');

await page.getByTestId('qa:structuredyson:search:next').click();
await expectScreenshot({component: page});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,27 @@ test('ReactUnipika: first render', async ({mount, expectScreenshot, page}) => {
await expectScreenshot();
});

test('ReactUnipika: search key match', async ({mount, expectScreenshot, page}) => {
await mount(<Stories.Json />, {width: 1280});

await page.getByTestId('qa:structuredyson:search').locator('input').fill('timestamp');

await expectScreenshot({component: page});
});

test('ReactUnipika: search key match in collapsed tree', async ({
mount,
expectScreenshot,
page,
}) => {
await mount(<Stories.Json />, {width: 1280});

await page.getByTestId('qa:structuredyson:search').locator('input').fill('timestamp');
await page.getByTestId('qa:structuredyson:collapse-all').click();

await expectScreenshot({component: page});
});

test('ReactUnipika: search next', async ({mount, expectScreenshot, page}) => {
await mount(<Stories.Json />, {width: 1280});

Expand Down
58 changes: 53 additions & 5 deletions src/utils/flattenUnipika.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2395,7 +2395,6 @@ describe('flattenUnipika', () => {
'auto_merge/mode',
'auto_merge/job_io/table_writer/desired_chunk_size',
'auto_merge/job_io/table_writer/group_size',
'auto_merge/job_io/table_writer/group_size',
];
const result = flattenUnipika(converted, {
filter: 'size',
Expand Down Expand Up @@ -2433,7 +2432,6 @@ describe('flattenUnipika', () => {
'auto_merge/mode',
'auto_merge/job_io/table_writer/desired_chunk_size',
'auto_merge/job_io/table_writer/group_size',
'auto_merge/job_io/table_writer/group_size',
];
const result = flattenUnipika(converted, {
filter: 'Size',
Expand Down Expand Up @@ -2583,7 +2581,6 @@ describe('flattenUnipika', () => {
'auto_merge/mode',
'auto_merge/job_io/table_writer/desired_chunk_size',
'auto_merge/job_io/table_writer/group_size',
'auto_merge/job_io/table_writer/group_size',
];
const result = flattenUnipika(converted, {
filter: 'size',
Expand Down Expand Up @@ -2642,7 +2639,11 @@ describe('flattenUnipika', () => {
settings: {format: 'yson'},
});

expect(result.allMatchPaths).toStrictEqual(['@', 'level1/@', 'level1/level2']);
expect(result.allMatchPaths).toStrictEqual([
'@/attr1',
'level1/@/attr2',
'level1/level2',
]);
});

it('should find matches in collapsed map keys', () => {
Expand Down Expand Up @@ -2699,7 +2700,8 @@ describe('flattenUnipika', () => {
settings: {format: 'yson'},
});

expect(result.allMatchPaths).toContain('@/columns/0');
expect(result.allMatchPaths).toContain('@/schema/@/testAttr');
expect(result.allMatchPaths).toContain('@/schema/columns/0');
});

it('should return empty allMatchPaths when no matches found', () => {
Expand Down Expand Up @@ -2732,6 +2734,52 @@ describe('flattenUnipika', () => {
expect(result.allMatchPaths).toContain('$attributes/testAttr');
expect(result.allMatchPaths).toContain('$value/testKey');
});

it('should not count a primitive map value twice when both its key and value match', () => {
const converted = unipika.converters.yson({
test: 'test',
});

const result = flattenUnipika(converted, {
filter: 'test',
settings: {format: 'yson'},
});

expect(result.allMatchPaths).toStrictEqual(['test']);
});

it('should not count a primitive attribute value twice when both its key and value match', () => {
const converted = unipika.converters.yson({
$attributes: {test: 'test'},
$value: 'data',
});

const result = flattenUnipika(converted, {
filter: 'test',
settings: {format: 'yson'},
});

expect(result.allMatchPaths).toStrictEqual(['@/test']);
});

it('allMatchPaths.length should equal the number of matched rows when nothing is collapsed', () => {
const converted = unipika.converters.yson({
$attributes: {test: 'test'},
$value: {
test: 'test',
subtitle: 'value',
nested: {caption: 'test'},
list: ['test'],
},
});

const result = flattenUnipika(converted, {
filter: 'test',
settings: {format: 'yson'},
});

expect(result.allMatchPaths?.length).toBe(Object.keys(result.searchIndex).length);
});
});
});

Expand Down
106 changes: 80 additions & 26 deletions src/utils/flattenUnipika.ts
Original file line number Diff line number Diff line change
Expand Up @@ -614,17 +614,49 @@ function collectAttributeMatches(
): Array<UnipikaFlattenTreeJoinedPath> {
const paths: Array<UnipikaFlattenTreeJoinedPath> = [];
if (value.$attributes && value.$attributes.length > 0) {
for (const [_key, attrValue] of value.$attributes) {
const attrPath = currentPath ? `${currentPath}/@` : '@';
collectAllMatchPaths(
paths,
attrValue,
filter,
settings,
isJson,
attrPath,
caseInsensitive,
);
const attrsPath = currentPath ? `${currentPath}/@` : '@';

for (const [key, attrValue] of value.$attributes) {
const attrPath = `${attrsPath}/${key.$value}`;
const keyMatch = rowSearchInfo(key, filter, settings, caseInsensitive);

if (isUnipikaContainerType(attrValue)) {
// The attribute's key opens its own row, separate from its nested rows.
if (keyMatch) {
paths.push(attrPath);
}

collectAllMatchPaths(
paths,
attrValue,
filter,
settings,
isJson,
attrPath,
caseInsensitive,
);
} else {
// A primitive attribute value is rendered on the same row as its key,
// so a key match and a value match must not be counted twice.
const valueMatch = rowSearchInfo(attrValue, filter, settings, caseInsensitive);

if (keyMatch || valueMatch) {
paths.push(attrPath);
}

const nestedAttrMatches = collectAttributeMatches(
attrValue,
filter,
settings,
isJson,
attrPath,
caseInsensitive,
);

if (nestedAttrMatches.length > 0) {
paths.push(...nestedAttrMatches);
}
}
}
}
return paths;
Expand Down Expand Up @@ -663,23 +695,45 @@ function collectMapMatches(
const paths: Array<UnipikaFlattenTreeJoinedPath> = [];
for (const [key, childValue] of mapValue) {
const childPath = valuePath ? `${valuePath}/${key.$value}` : key.$value;

// Check if key matches
const keyMatch = rowSearchInfo(key, filter, settings, caseInsensitive);
if (keyMatch) {
paths.push(childPath);
}

// Recursively collect from value
collectAllMatchPaths(
paths,
childValue,
filter,
settings,
isJson,
childPath,
caseInsensitive,
);
if (isUnipikaContainerType(childValue)) {
// The key opens its own row, separate from the container's nested rows.
if (keyMatch) {
paths.push(childPath);
}

collectAllMatchPaths(
paths,
childValue,
filter,
settings,
isJson,
childPath,
caseInsensitive,
);
} else {
// A primitive value is rendered on the same row as its key,
// so a key match and a value match must not be counted twice.
const valueMatch = rowSearchInfo(childValue, filter, settings, caseInsensitive);

if (keyMatch || valueMatch) {
paths.push(childPath);
}

const attrMatches = collectAttributeMatches(
childValue,
filter,
settings,
isJson,
childPath,
caseInsensitive,
);

if (attrMatches.length > 0) {
paths.push(...attrMatches);
}
}
}
return paths;
}
Expand Down
Loading