Skip to content

Commit 93c248b

Browse files
committed
Added unittests
1 parent 0a52f3b commit 93c248b

1 file changed

Lines changed: 121 additions & 0 deletions

File tree

test/legendTest.ts

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,127 @@ describe("legend", () => {
715715
expect(iconY + iconHeight / 2).toBeLessThan((labelY * 2 + labelHeight) * 0.6);
716716
});
717717

718+
describe("Centered vertical legend overflow (regression for Math.max(0, ...) clamp)", () => {
719+
function parseTranslateY(transform: string | null): number {
720+
if (!transform) {
721+
return 0;
722+
}
723+
const match = /translate\(\s*[-+0-9.eE]+\s*[, ]\s*([-+0-9.eE]+)/.exec(transform);
724+
return match ? parseFloat(match[1]) : 0;
725+
}
726+
727+
function expectGroupNotClipped(position: LegendPosition): void {
728+
const legendData = getLotsOfLegendData();
729+
730+
legend.changeOrientation(position);
731+
// Force overflow: tall list of items in a short vertical area.
732+
legend.drawLegend({ dataPoints: legendData }, { height: 50, width: 200 });
733+
734+
flushAllD3Transitions();
735+
736+
const group = element.querySelector("#legendGroup");
737+
expect(group).not.toBeNull();
738+
739+
const translateY = parseTranslateY(group.getAttribute("transform"));
740+
// Before the fix this value went negative (group shifted above the
741+
// SVG, clipping the title and "previous" arrow).
742+
expect(translateY).toBeGreaterThanOrEqual(0);
743+
}
744+
745+
it("LeftCenter with overflowing items does not translate group above 0", () => {
746+
expectGroupNotClipped(LegendPosition.LeftCenter);
747+
});
748+
749+
it("RightCenter with overflowing items does not translate group above 0", () => {
750+
expectGroupNotClipped(LegendPosition.RightCenter);
751+
});
752+
});
753+
754+
describe("Right-aligned horizontal legend (TopRight / BottomRight)", () => {
755+
function parseTranslate(transform: string | null): { x: number; y: number } {
756+
if (!transform) {
757+
return { x: 0, y: 0 };
758+
}
759+
const match = /translate\(\s*([-+0-9.eE]+)\s*[, ]\s*([-+0-9.eE]+)?/.exec(transform);
760+
if (!match) {
761+
return { x: 0, y: 0 };
762+
}
763+
return { x: parseFloat(match[1]), y: match[2] ? parseFloat(match[2]) : 0 };
764+
}
765+
766+
function fittingDataPoints(): LegendDataPoint[] {
767+
return [
768+
{ label: "A", color: "#ff0000", identity: createSelectionIdentity("a"), selected: false },
769+
{ label: "B", color: "#00ff00", identity: createSelectionIdentity("b"), selected: false },
770+
];
771+
}
772+
773+
it("TopRight: when items fit, the legend group is translated to the right edge and no nav arrow is rendered", () => {
774+
legend.changeOrientation(LegendPosition.TopRight);
775+
legend.drawLegend({ dataPoints: fittingDataPoints() }, { height: 100, width: 1000 });
776+
777+
flushAllD3Transitions();
778+
779+
const group = element.querySelector("#legendGroup");
780+
expect(group).not.toBeNull();
781+
782+
const translate = parseTranslate(group.getAttribute("transform"));
783+
// Items fit, so the group should be shifted right by a positive amount.
784+
expect(translate.x).toBeGreaterThan(0);
785+
expect(translate.y).toBe(0);
786+
787+
// No overflow -> no navigation arrows.
788+
expect(element.querySelectorAll(".navArrow").length).toBe(0);
789+
});
790+
791+
it("BottomRight: when items fit, the legend group is translated to the right edge", () => {
792+
legend.changeOrientation(LegendPosition.BottomRight);
793+
legend.drawLegend({ dataPoints: fittingDataPoints() }, { height: 100, width: 1000 });
794+
795+
flushAllD3Transitions();
796+
797+
const group = element.querySelector("#legendGroup");
798+
const translate = parseTranslate(group.getAttribute("transform"));
799+
expect(translate.x).toBeGreaterThan(0);
800+
expect(element.querySelectorAll(".navArrow").length).toBe(0);
801+
});
802+
803+
it("TopRight: when items overflow, falls back to left-aligned with a navigation arrow", () => {
804+
const legendData = getLotsOfLegendData();
805+
806+
legend.changeOrientation(LegendPosition.TopRight);
807+
// Narrow viewport forces overflow.
808+
legend.drawLegend({ dataPoints: legendData }, { height: 100, width: 200 });
809+
810+
flushAllD3Transitions();
811+
812+
const group = element.querySelector("#legendGroup");
813+
const translate = parseTranslate(group.getAttribute("transform"));
814+
815+
// Fallback: group is not translated to the right edge anymore.
816+
expect(translate.x).toBe(0);
817+
818+
// The "next" navigation arrow should be visible at the right side.
819+
const arrows = element.querySelectorAll(".navArrow");
820+
expect(arrows.length).toBeGreaterThan(0);
821+
});
822+
823+
it("BottomRight: when items overflow, falls back to left-aligned with a navigation arrow", () => {
824+
const legendData = getLotsOfLegendData();
825+
826+
legend.changeOrientation(LegendPosition.BottomRight);
827+
legend.drawLegend({ dataPoints: legendData }, { height: 100, width: 200 });
828+
829+
flushAllD3Transitions();
830+
831+
const group = element.querySelector("#legendGroup");
832+
const translate = parseTranslate(group.getAttribute("transform"));
833+
834+
expect(translate.x).toBe(0);
835+
expect(element.querySelectorAll(".navArrow").length).toBeGreaterThan(0);
836+
});
837+
});
838+
718839
function validateLegendDOM(expectedData: LegendDataPoint[]): void {
719840
let len = expectedData.length;
720841
let labels = element.querySelectorAll(".legendText");

0 commit comments

Comments
 (0)