Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/3784/improve quantile diagramm #3827

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
5 changes: 5 additions & 0 deletions visualization/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/)

- Add alternative center-focused zoom option via the `🡹 Shift`-key [#3815](https://github.com/MaibornWolff/codecharta/pull/3815)
- Add an apply button when selecting maps [#3637](https://github.com/MaibornWolff/codecharta/pull/3637)
- Add a crosshair cursor when hovering over the color quantile diagram [#3827](https://github.com/MaibornWolff/codecharta/pull/3827)

### Changed

- Increased the size of the color quantile diagram [#3827](https://github.com/MaibornWolff/codecharta/pull/3827)

### Fixed 🐞

Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,3 @@
#slider-label-left,
#slider-label-right,
#x-label,
#y-label,
#axis-x,
#axis-y {
font-size: 11px;

&[text-anchor] {
&.end {
text-anchor: end;
}

&.start {
text-anchor: start;
}
}
}

#slider-label-left {
font-size: 11px;
fill: #888;
text-anchor: end;
dominant-baseline: hanging;
}

#slider-label-right {
font-size: 11px;
fill: #888;
text-anchor: start;
dominant-baseline: hanging;
}

.cc-range-diagram-container {
svg {
width: 100%;
height: 130px;
}
}

:host {
display: flex;
justify-content: center;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,25 @@ describe("MetricColorRangeDiagramComponent", () => {
expect(xLabel).toBeTruthy()
expect(yLabel).toBeTruthy()

expect(leftArea.getAttribute("height")).toBe("80")
expect(leftArea.getAttribute("width")).toBe("66")
expect(leftArea.getAttribute("x")).toBe("0")
expect(leftArea.getAttribute("height")).toBe("190")
expect(leftArea.getAttribute("width")).toBe("180")
expect(leftArea.getAttribute("x")).toBe("5")
expect(leftArea.style.fill).toBe("#69AE40")

expect(middleArea.getAttribute("height")).toBe("80")
expect(middleArea.getAttribute("width")).toBe("22")
expect(middleArea.getAttribute("x")).toBe("66")
expect(middleArea.getAttribute("height")).toBe("190")
expect(middleArea.getAttribute("width")).toBe("60")
expect(middleArea.getAttribute("x")).toBe("185")
expect(middleArea.style.fill).toBe("#ddcc00")

expect(rightArea.getAttribute("height")).toBe("80")
expect(rightArea.getAttribute("width")).toBe("88")
expect(rightArea.getAttribute("x")).toBe("88")
expect(rightArea.getAttribute("height")).toBe("190")
expect(rightArea.getAttribute("width")).toBe("240")
expect(rightArea.getAttribute("x")).toBe("245")
expect(rightArea.style.fill).toBe("#820E0E")

expect(xLabel.textContent).toContain("mcc")
expect(yLabel.textContent).toContain("mcc")

expect(diagramPath.getAttribute("d")).toBe("M0,59.4L0,59.4L66,59.4L66,54L88,54L88,12L110,12L110,0L176,0")
expect(diagramPath.getAttribute("d")).toBe("M0,178.2L0,178.2L180,178.2L180,162L240,162L240,36L300,36L300,0L480,0")
})

it("should render diagram correctly when attribute direction is inversed", async () => {
Expand Down Expand Up @@ -99,26 +99,26 @@ describe("MetricColorRangeDiagramComponent", () => {
expect(xLabel).toBeTruthy()
expect(yLabel).toBeTruthy()

expect(leftArea.getAttribute("height")).toBe("80")
expect(Number(leftArea.getAttribute("width"))).toBeCloseTo(117.33)
expect(leftArea.getAttribute("x")).toBe("0")
expect(leftArea.getAttribute("height")).toBe("190")
expect(Number(leftArea.getAttribute("width"))).toBeCloseTo(320)
expect(leftArea.getAttribute("x")).toBe("5")
expect(leftArea.style.fill).toBe("#820E0E")

expect(middleArea.getAttribute("height")).toBe("80")
expect(middleArea.getAttribute("height")).toBe("190")
expect(middleArea.getAttribute("width")).toBe("0")
expect(Number(middleArea.getAttribute("x"))).toBeCloseTo(117.33)
expect(Number(middleArea.getAttribute("x"))).toBeCloseTo(325)
expect(middleArea.style.fill).toBe("#ddcc00")

expect(rightArea.getAttribute("height")).toBe("80")
expect(Number(rightArea.getAttribute("width"))).toBeCloseTo(58.666)
expect(Number(rightArea.getAttribute("x"))).toBeCloseTo(117.33)
expect(rightArea.getAttribute("height")).toBe("190")
expect(Number(rightArea.getAttribute("width"))).toBeCloseTo(160)
expect(Number(rightArea.getAttribute("x"))).toBeCloseTo(325)
expect(rightArea.style.fill).toBe("#69AE40")

expect(xLabel.textContent).toContain("branch_coverage")
expect(yLabel.textContent).toContain("branch_coverage")

expect(diagramPath.getAttribute("d")).toBe(
"M0,60L0,60L19.556,60L19.556,59.368L39.111,59.368L39.111,58.737L58.667,58.737L58.667,58.105L78.222,58.105L78.222,57.474L97.778,57.474L97.778,56.842L117.333,56.842L117.333,18.947L136.889,18.947L136.889,15.789L156.444,15.789L156.444,9.474L176,9.474"
"M0,180L0,180L53.333,180L53.333,178.105L106.667,178.105L106.667,176.211L160,176.211L160,174.316L213.333,174.316L213.333,172.421L266.667,172.421L266.667,170.526L320,170.526L320,56.842L373.333,56.842L373.333,47.368L426.667,47.368L426.667,28.421L480,28.421"
)
})

Expand Down Expand Up @@ -150,19 +150,19 @@ describe("MetricColorRangeDiagramComponent", () => {
expect(middleArea).toBeTruthy()
expect(rightArea).toBeTruthy()

expect(leftArea.getAttribute("height")).toBe("80")
expect(leftArea.getAttribute("height")).toBe("190")
expect(leftArea.getAttribute("width")).toBe("0")
expect(leftArea.getAttribute("x")).toBe("0")
expect(leftArea.getAttribute("x")).toBe("5")
expect(leftArea.style.fill).toBe("#69AE40")

expect(middleArea.getAttribute("height")).toBe("80")
expect(middleArea.getAttribute("width")).toBe("88")
expect(middleArea.getAttribute("x")).toBe("0")
expect(middleArea.getAttribute("height")).toBe("190")
expect(middleArea.getAttribute("width")).toBe("240")
expect(middleArea.getAttribute("x")).toBe("5")
expect(middleArea.style.fill).toBe("#ddcc00")

expect(rightArea.getAttribute("height")).toBe("80")
expect(rightArea.getAttribute("width")).toBe("88")
expect(rightArea.getAttribute("x")).toBe("88")
expect(rightArea.getAttribute("height")).toBe("190")
expect(rightArea.getAttribute("width")).toBe("240")
expect(rightArea.getAttribute("x")).toBe("245")
expect(rightArea.style.fill).toBe("#820E0E")
})

Expand Down Expand Up @@ -194,19 +194,177 @@ describe("MetricColorRangeDiagramComponent", () => {
expect(middleArea).toBeTruthy()
expect(rightArea).toBeTruthy()

expect(leftArea.getAttribute("height")).toBe("80")
expect(leftArea.getAttribute("width")).toBe("66")
expect(leftArea.getAttribute("x")).toBe("0")
expect(leftArea.getAttribute("height")).toBe("190")
expect(leftArea.getAttribute("width")).toBe("180")
expect(leftArea.getAttribute("x")).toBe("5")
expect(leftArea.style.fill).toBe("#69AE40")

expect(middleArea.getAttribute("height")).toBe("80")
expect(middleArea.getAttribute("width")).toBe("110")
expect(middleArea.getAttribute("x")).toBe("66")
expect(middleArea.getAttribute("height")).toBe("190")
expect(middleArea.getAttribute("width")).toBe("300")
expect(middleArea.getAttribute("x")).toBe("185")
expect(middleArea.style.fill).toBe("#ddcc00")

expect(rightArea.getAttribute("height")).toBe("80")
expect(rightArea.getAttribute("height")).toBe("190")
expect(rightArea.getAttribute("width")).toBe("0")
expect(rightArea.getAttribute("x")).toBe("176")
expect(rightArea.getAttribute("x")).toBe("485")
expect(rightArea.style.fill).toBe("#820E0E")
})

it("should add cross", async () => {
const { fixture, detectChanges, container } = await render(MetricColorRangeDiagramComponent, {
componentInputs: {
values: [100]
}
})

fixture.componentInstance.ngOnChanges()
detectChanges()

const svg = container.querySelector("svg")
const tooltip = svg.getElementsByClassName("cross-tooltip")[0] as HTMLElement
const dashedVerticalLine = svg.getElementsByClassName("dashed-vertical-line")[0] as HTMLElement
const straightVerticalLine = svg.getElementsByClassName("straight-vertical-line")[0] as HTMLElement
const horizontalLine = svg.getElementsByClassName("horizontal-line")[0] as HTMLElement
const rectangle = svg.getElementsByClassName("mouse-event-rect")[0] as HTMLElement

expect(tooltip).toBeTruthy()
expect(dashedVerticalLine).toBeTruthy()
expect(straightVerticalLine).toBeTruthy()
expect(horizontalLine).toBeTruthy()
expect(rectangle).toBeTruthy()

expect(tooltip.getAttribute("style")).toBe("display: none;")
expect(dashedVerticalLine.getAttribute("style")).toBe("display: none;")
expect(straightVerticalLine.getAttribute("style")).toBe("display: none;")
expect(horizontalLine.getAttribute("style")).toBe("display: none;")
expect(rectangle.getAttribute("width")).toBe("490")
expect(rectangle.getAttribute("height")).toBe("215")
})

it("should change visibility of cross on mousemove and mouseout events correctly", async () => {
const { fixture, container } = await render(MetricColorRangeDiagramComponent, {
componentInputs: {
values: [100]
}
})

fixture.componentInstance.ngOnChanges()
const svg = container.querySelector("svg")
const rectangle = svg.getElementsByClassName("mouse-event-rect")[0] as HTMLElement
const tooltip = svg.getElementsByClassName("cross-tooltip")[0] as HTMLElement
const dashedVerticalLine = svg.getElementsByClassName("dashed-vertical-line")[0] as HTMLElement
const straightVerticalLine = svg.getElementsByClassName("straight-vertical-line")[0] as HTMLElement
const horizontalLine = svg.getElementsByClassName("horizontal-line")[0] as HTMLElement

//WHEN
rectangle.dispatchEvent(new MouseEvent("mousemove"))

//THEN
expect(tooltip.getAttribute("style")).toBe("display: block;")
expect(dashedVerticalLine.getAttribute("style")).toBe("display: block;")
expect(straightVerticalLine.getAttribute("style")).toBe("display: block;")
expect(horizontalLine.getAttribute("style")).toBe("display: block;")

//WHEN
rectangle.dispatchEvent(new MouseEvent("mouseout"))

//THEN
expect(tooltip.getAttribute("style")).toBe("display: none;")
expect(dashedVerticalLine.getAttribute("style")).toBe("display: none;")
expect(straightVerticalLine.getAttribute("style")).toBe("display: none;")
expect(horizontalLine.getAttribute("style")).toBe("display: none;")
})

describe("cross-hair", () => {
let svg: SVGSVGElement
let mouseEventRectangle: HTMLElement

beforeEach(async () => {
const { container } = await render(MetricColorRangeDiagramComponent, {
componentInputs: {
minValue: 1,
maxValue: 10,
values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}
})
svg = container.querySelector("svg")
mouseEventRectangle = svg.getElementsByClassName("mouse-event-rect")[0] as HTMLElement
})

const expectedYLinePositionsForMouseXPositions = [
[167, 0],
[167, 50],
[95, 200],
[5, 450],
[5, 1000]
]
test.each(expectedYLinePositionsForMouseXPositions)("should be on y=%p when mouse on x=%p", (expectedYPosition, mouseXPosition) => {
//WHEN
const simulatedEvent = new MouseEvent("mousemove", {
clientX: mouseXPosition,
clientY: 0
})
mouseEventRectangle.dispatchEvent(simulatedEvent)

//THEN
const horizontalLine = svg.getElementsByClassName("horizontal-line")[0] as HTMLElement
const xPosition = horizontalLine.getAttribute("x2")
const yPosition = horizontalLine.getAttribute("y1")

expect(xPosition).toBe(mouseXPosition.toString())
expect(yPosition).toBe(expectedYPosition.toString())
})

const expectedYTooltipPositionsForMouseXPositions = [
[147, 10, 0],
[147, 60, 50],
[115, 210, 200],
[25, 370, 450],
[25, 920, 1000]
]
test.each(expectedYTooltipPositionsForMouseXPositions)(
"should correctly position the tooltip on y=%p and x=%p for mouse on x=%p",
async (expectedYPosition, expectedXPosition, mouseXPosition) => {
//WHEN
const simulatedEvent = new MouseEvent("mousemove", {
clientX: mouseXPosition,
clientY: 0
})
mouseEventRectangle.dispatchEvent(simulatedEvent)

// Then
const tooltip = svg.getElementsByClassName("cross-tooltip")[0] as HTMLElement
const tooltipXPosition = Number.parseInt(tooltip.getAttribute("x"))
const tooltipYPosition = Number.parseInt(tooltip.getAttribute("y"))

expect(tooltipXPosition).toBe(expectedXPosition)
expect(tooltipYPosition).toBe(expectedYPosition)
}
)

const expectedQuantileAndYValueForMouseXPositions = [
[0, 1, 0],
[9, 1, 50],
[41, 5, 200],
[93, 10, 450],
[100, 10, 1000]
]
test.each(expectedQuantileAndYValueForMouseXPositions)(
"should show Quantile: %p and Value: %p as the correct tooltip text when mouse on x=%p",
(quantile, yValue, mouseXPosition) => {
//WHEN
const simulatedEvent = new MouseEvent("mousemove", {
clientX: mouseXPosition,
clientY: 0
})
mouseEventRectangle.dispatchEvent(simulatedEvent)

//THEN
const tooltip = svg.getElementsByClassName("cross-tooltip")[0] as HTMLElement

expect(tooltip.innerHTML).toContain(`Quantile: ${quantile}`)
expect(tooltip.innerHTML).toContain(`Value: ${yValue}`)
}
)
})
})
Loading