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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "12.1.5",
"@testing-library/user-event": "^14.4.3",
"@trivago/prettier-plugin-sort-imports": "^4.0.0",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/node": "^20.8.2",
"@types/react": "17.0.50",
"@types/react-dom": "17.0.17",
Expand Down
5 changes: 3 additions & 2 deletions src/components/Trendline/Trendline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ import { TrendlineProps } from '../../types';
const Trendline: FC<TrendlineProps> = ({
children,
color,
dimensionExtent,
dimensionRange = [null, null],
displayOnHover = false,
highlightRawPoint = false,
lineType = 'dashed',
lineWidth = 'M',
method = 'linear',
displayOnHover = false,
highlightRawPoint = false,
opacity = 1,
}) => {
return null;
Expand Down
51 changes: 25 additions & 26 deletions src/specBuilder/line/lineSpecBuilder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,30 +371,29 @@ describe('lineSpecBuilder', () => {
});

test('scaleTypes "point" and "linear" should return the original data', () => {
expect(addData([], { ...defaultLineProps, scaleType: 'point' })).toEqual([]);
expect(addData([], { ...defaultLineProps, scaleType: 'linear' })).toEqual([]);
expect(addData(baseData, { ...defaultLineProps, scaleType: 'point' })).toEqual(baseData);
expect(addData(baseData, { ...defaultLineProps, scaleType: 'linear' })).toEqual(baseData);
});

test('should add trendline transform', () => {
expect(
addData(baseData, {
...defaultLineProps,
children: [createElement(Trendline, { method: 'average' })],
})[2].transform
})[2].transform,
).toStrictEqual([
{
type: 'collect',
sort: {
field: DEFAULT_TRANSFORMED_TIME_DIMENSION,
},
},
{
type: 'joinaggregate',
groupby: ['series'],
fields: ['value'],
ops: ['mean'],
as: [TRENDLINE_VALUE],
as: [
TRENDLINE_VALUE,
`${DEFAULT_TRANSFORMED_TIME_DIMENSION}Min`,
`${DEFAULT_TRANSFORMED_TIME_DIMENSION}Max`,
],
fields: [DEFAULT_METRIC, DEFAULT_TRANSFORMED_TIME_DIMENSION, DEFAULT_TRANSFORMED_TIME_DIMENSION],
groupby: [DEFAULT_COLOR],
ops: ['mean', 'min', 'max'],
type: 'aggregate',
},
{ as: SERIES_ID, expr: `datum.${DEFAULT_COLOR}`, type: 'formula' },
]);
});

Expand All @@ -403,7 +402,7 @@ describe('lineSpecBuilder', () => {
addData(baseData, {
...defaultLineProps,
children: [createElement(Trendline, { method: 'movingAverage-7' })],
})[0].transform
})[0].transform,
).toHaveLength(2);
});

Expand All @@ -430,7 +429,7 @@ describe('lineSpecBuilder', () => {
setScales(startingSpec.scales ?? [], {
...defaultLineProps,
scaleType: 'linear',
})
}),
).toStrictEqual([defaultSpec.scales?.[0], defaultLinearScale, defaultSpec.scales?.[2]]);
});

Expand All @@ -439,7 +438,7 @@ describe('lineSpecBuilder', () => {
setScales(startingSpec.scales ?? [], {
...defaultLineProps,
scaleType: 'point',
})
}),
).toStrictEqual([defaultSpec.scales?.[0], defaultPointScale, defaultSpec.scales?.[2]]);
});

Expand All @@ -456,7 +455,7 @@ describe('lineSpecBuilder', () => {
setScales(startingSpec.scales ?? [], {
...defaultLineProps,
children: [createElement(MetricRange, { scaleAxisToFit: true, metricEnd, metricStart })],
})
}),
).toStrictEqual([defaultSpec.scales?.[0], defaultSpec.scales?.[1], metricRangeMetricScale]);
});
});
Expand Down Expand Up @@ -498,13 +497,13 @@ describe('lineSpecBuilder', () => {

test('with metric range', () => {
expect(addLineMarks([], { ...defaultLineProps, children: [getMetricRangeElement()] })).toStrictEqual(
metricRangeMarks
metricRangeMarks,
);
});

test('with displayPointMark', () => {
expect(addLineMarks([], { ...defaultLineProps, staticPoint: 'staticPoint' })).toStrictEqual(
displayPointMarks
displayPointMarks,
);
});

Expand All @@ -514,7 +513,7 @@ describe('lineSpecBuilder', () => {
...defaultLineProps,
staticPoint: 'staticPoint',
children: [getMetricRangeElement()],
})
}),
).toStrictEqual(metricRangeWithDisplayPointMarks);
});
});
Expand All @@ -534,8 +533,8 @@ describe('lineSpecBuilder', () => {
value: null,
},
],
defaultLineProps
)
defaultLineProps,
),
).toStrictEqual([
{
name: 'line0_selectedSeries',
Expand All @@ -556,7 +555,7 @@ describe('lineSpecBuilder', () => {
value: null,
},
],
{ ...defaultLineProps, children: [createElement(ChartPopover)] }
{ ...defaultLineProps, children: [createElement(ChartPopover)] },
);

expect(getGenericSignalSpy).toHaveBeenCalledTimes(1);
Expand All @@ -565,7 +564,7 @@ describe('lineSpecBuilder', () => {

test('hover signals with metric range', () => {
expect(
addSignals([], { ...defaultLineProps, children: [getMetricRangeElement({ displayOnHover: true })] })
addSignals([], { ...defaultLineProps, children: [getMetricRangeElement({ displayOnHover: true })] }),
).toStrictEqual([
{
name: 'line0_hoveredSeries',
Expand Down Expand Up @@ -616,7 +615,7 @@ describe('lineSpecBuilder', () => {
...defaultLineProps,
staticPoint: 'staticPoint',
children: [getMetricRangeElement({ displayOnHover: true })],
})
}),
).toStrictEqual([
{
name: 'line0_hoveredSeries',
Expand Down
11 changes: 3 additions & 8 deletions src/specBuilder/line/lineSpecBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@ import {
getMetricRanges,
} from '@specBuilder/metricRange/metricRangeUtils';
import { getFacetsFromProps } from '@specBuilder/specUtils';
import {
addTrendlineData,
getTrendlineMarks,
getTrendlineScales,
getTrendlineSignals,
} from '@specBuilder/trendline/trendlineUtils';
import { addTrendlineData, getTrendlineMarks, getTrendlineScales, getTrendlineSignals } from '@specBuilder/trendline';
import { sanitizeMarkChildren, toCamelCase } from '@utils';
import { produce } from 'immer';
import { ColorScheme, LineProps, LineSpecProps, MarkChildElement } from 'types';
Expand Down Expand Up @@ -56,7 +51,7 @@ export const addLine = produce<Spec, [LineProps & { colorScheme?: ColorScheme; i
opacity = { value: 1 },
scaleType = 'time',
...props
}
},
) => {
const sanitizedChildren = sanitizeMarkChildren(children);
const lineName = toCamelCase(name || `line${index}`);
Expand All @@ -83,7 +78,7 @@ export const addLine = produce<Spec, [LineProps & { colorScheme?: ColorScheme; i
spec.marks = addLineMarks(spec.marks ?? [], lineProps);

return spec;
}
},
);

export const addData = produce<Data[], [LineSpecProps]>((data, props) => {
Expand Down
12 changes: 6 additions & 6 deletions src/specBuilder/marks/markUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
ScaledValueRef,
SignalRef,
} from 'vega';
import { getScaleName } from '@specBuilder/scale/scaleSpecBuilder';

/**
* If a popover exists on the mark, then set the cursor to a pointer.
Expand Down Expand Up @@ -96,7 +97,7 @@ export const hasInteractiveChildren = (children: ReactElement[]): boolean => {
child.type === ChartTooltip ||
child.type === ChartPopover ||
(child.type === Trendline && child.props.displayOnHover) ||
(child.type === MetricRange && child.props.displayOnHover)
(child.type === MetricRange && child.props.displayOnHover),
);
};
export const hasMetricRange = (children: ReactElement[]): boolean =>
Expand All @@ -119,7 +120,7 @@ export const getColorProductionRule = (color: ColorFacet | DualFacet, colorSchem
};

export const getLineWidthProductionRule = (
lineWidth: LineWidthFacet | DualFacet | undefined
lineWidth: LineWidthFacet | DualFacet | undefined,
): NumericValueRef | undefined => {
if (!lineWidth) return;
if (Array.isArray(lineWidth)) {
Expand Down Expand Up @@ -183,10 +184,9 @@ export const getHighlightOpacityValue = (opacityValue: { signal: string } | { va
* @returns x encoding
*/
export const getXProductionRule = (scaleType: ScaleType, dimension: string): ProductionRule<NumericValueRef> => {
const scale = getScaleName('x', scaleType);
if (scaleType === 'time') {
return { scale: 'xTime', field: DEFAULT_TRANSFORMED_TIME_DIMENSION };
} else if (scaleType === 'linear') {
return { scale: 'xLinear', field: dimension };
return { scale, field: DEFAULT_TRANSFORMED_TIME_DIMENSION };
}
return { scale: 'xPoint', field: dimension };
return { scale, field: dimension };
};
122 changes: 64 additions & 58 deletions src/specBuilder/scale/scaleSpecBuilder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
addDomainFields,
addFieldToFacetScaleDomain,
getPadding,
getScaleName,
} from './scaleSpecBuilder';

const defaultColorScale: OrdinalScale = {
Expand All @@ -25,77 +26,82 @@ const defaultColorScale: OrdinalScale = {
type: 'ordinal',
};

describe('scaleSpecBuilder', () => {
describe('addDomainFields()', () => {
test('no domain fields', () => {
expect(addDomainFields({ name: 'color', type: 'ordinal' }, [DEFAULT_COLOR])).toStrictEqual({
domain: { data: 'table', fields: [DEFAULT_COLOR] },
name: 'color',
type: 'ordinal',
});
describe('addDomainFields()', () => {
test('no domain fields', () => {
expect(addDomainFields({ name: 'color', type: 'ordinal' }, [DEFAULT_COLOR])).toStrictEqual({
domain: { data: 'table', fields: [DEFAULT_COLOR] },
name: 'color',
type: 'ordinal',
});
});

test('field matches existing one, nothing should change', () => {
expect(addDomainFields(defaultColorScale, [DEFAULT_COLOR])).toStrictEqual(defaultColorScale);
});
test('field matches existing one, nothing should change', () => {
expect(addDomainFields(defaultColorScale, [DEFAULT_COLOR])).toStrictEqual(defaultColorScale);
});

test('new field should be added to existing one', () => {
expect(
addDomainFields({ ...defaultColorScale, domain: { data: 'table', fields: ['test'] } }, [DEFAULT_COLOR])
).toStrictEqual({ ...defaultColorScale, domain: { data: 'table', fields: ['test', DEFAULT_COLOR] } });
});
test('new field should be added to existing one', () => {
expect(
addDomainFields({ ...defaultColorScale, domain: { data: 'table', fields: ['test'] } }, [DEFAULT_COLOR]),
).toStrictEqual({ ...defaultColorScale, domain: { data: 'table', fields: ['test', DEFAULT_COLOR] } });
});
});

describe('getPadding()', () => {
test('time', () => {
expect(getPadding('time')).toStrictEqual({
padding: 32,
});
describe('getPadding()', () => {
test('time', () => {
expect(getPadding('time')).toStrictEqual({
padding: 32,
});
test('linear', () => {
expect(getPadding('time')).toStrictEqual({
padding: 32,
});
});
test('linear', () => {
expect(getPadding('time')).toStrictEqual({
padding: 32,
});
test('point', () => {
expect(getPadding('point')).toStrictEqual({
paddingOuter: 0.5,
});
});
test('point', () => {
expect(getPadding('point')).toStrictEqual({
paddingOuter: 0.5,
});
test('band', () => {
expect(getPadding('band')).toStrictEqual({
paddingInner: 0.4,
paddingOuter: 0.2,
});
});
test('band', () => {
expect(getPadding('band')).toStrictEqual({
paddingInner: 0.4,
paddingOuter: 0.2,
});
});
});

describe('addFieldToFacetScaleDomain()', () => {
test('should add fields to correct scale', () => {
const scales: Scale[] = [{ name: 'color', type: 'ordinal' }];
addFieldToFacetScaleDomain(scales, 'color', DEFAULT_COLOR);
expect(scales).toStrictEqual([
{ name: 'color', type: 'ordinal', domain: { data: 'table', fields: [DEFAULT_COLOR] } },
]);
});
describe('addFieldToFacetScaleDomain()', () => {
test('should add fields to correct scale', () => {
const scales: Scale[] = [{ name: 'color', type: 'ordinal' }];
addFieldToFacetScaleDomain(scales, 'color', DEFAULT_COLOR);
expect(scales).toStrictEqual([
{ name: 'color', type: 'ordinal', domain: { data: 'table', fields: [DEFAULT_COLOR] } },
]);
});

test('should not add any fields to the domain if the facet value is static', () => {
const scales: Scale[] = [{ name: 'color', type: 'ordinal' }];
addFieldToFacetScaleDomain(scales, 'color', { value: 'red-500' });
expect(scales).toStrictEqual([{ name: 'color', type: 'ordinal' }]);
});
test('should not add any fields to the domain if the facet value is static', () => {
const scales: Scale[] = [{ name: 'color', type: 'ordinal' }];
addFieldToFacetScaleDomain(scales, 'color', { value: 'red-500' });
expect(scales).toStrictEqual([{ name: 'color', type: 'ordinal' }]);
});
});

describe('addContinuousDimensionScale()', () => {
test('should override padding if it exists', () => {
const scales = [];
addContinuousDimensionScale(scales, { scaleType: 'linear', dimension: 'x', padding: 24 });
expect(scales[0]).toHaveProperty('padding', 24);
});
test('should override paddingOuter if padding exists', () => {
const scales: Scale[] = [{ type: 'band', name: 'xBand', paddingInner: 0.3, paddingOuter: 0.7 }];
addContinuousDimensionScale(scales, { scaleType: 'band', dimension: 'x', padding: 0 });
expect(scales[0]).toHaveProperty('paddingOuter', 0);
});
describe('addContinuousDimensionScale()', () => {
test('should override padding if it exists', () => {
const scales = [];
addContinuousDimensionScale(scales, { scaleType: 'linear', dimension: 'x', padding: 24 });
expect(scales[0]).toHaveProperty('padding', 24);
});
test('should override paddingOuter if padding exists', () => {
const scales: Scale[] = [{ type: 'band', name: 'xBand', paddingInner: 0.3, paddingOuter: 0.7 }];
addContinuousDimensionScale(scales, { scaleType: 'band', dimension: 'x', padding: 0 });
expect(scales[0]).toHaveProperty('paddingOuter', 0);
});
});

describe('getScaleName()', () => {
test('should return correct scale name', () => {
expect(getScaleName('x', 'linear')).toBe('xLinear');
expect(getScaleName('y', 'band')).toBe('yBand');
});
});
Loading