Skip to content
This repository has been archived by the owner on Mar 8, 2023. It is now read-only.

Commit

Permalink
HARP-13345: Add unit tests for line marker replacement.
Browse files Browse the repository at this point in the history
  • Loading branch information
atomicsulfate committed Jan 11, 2021
1 parent 57e62d9 commit 059999b
Show file tree
Hide file tree
Showing 5 changed files with 270 additions and 144 deletions.
10 changes: 6 additions & 4 deletions @here/harp-mapview/test/TextElementBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,18 @@ export function poiBuilder(text: string = DEF_TEXT): TextElementBuilder {
.withPoiInfo(new PoiInfoBuilder().withPoiTechnique());
}

export function createPath(coordScale: number, points: THREE.Vector3[]) {
return points.map((point: THREE.Vector3) => point.clone().multiplyScalar(coordScale));
}

export function pathTextBuilder(coordScale: number, text: string = DEF_TEXT): TextElementBuilder {
return new TextElementBuilder()
.withText(text)
.withPath(DEF_PATH.map((point: THREE.Vector3) => point.clone().multiplyScalar(coordScale)));
return new TextElementBuilder().withText(text).withPath(createPath(coordScale, DEF_PATH));
}

export function lineMarkerBuilder(coordScale: number, text: string = DEF_TEXT): TextElementBuilder {
return new TextElementBuilder()
.withText(text)
.withPath(DEF_PATH.map((point: THREE.Vector3) => point.clone().multiplyScalar(coordScale)))
.withPath(createPath(coordScale, DEF_PATH))
.withPoiInfo(new PoiInfoBuilder().withLineMarkerTechnique());
}

Expand Down
166 changes: 129 additions & 37 deletions @here/harp-mapview/test/TextElementsRendererTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import * as THREE from "three";

import { TextElement } from "../lib/text/TextElement";
import { DEFAULT_FONT_CATALOG_NAME } from "../lib/text/TextElementsRenderer";
import { TextElementType } from "../lib/text/TextElementType";
import { PoiInfoBuilder } from "./PoiInfoBuilder";
import {
createPath,
DEF_PATH,
lineMarkerBuilder,
pathTextBuilder,
Expand Down Expand Up @@ -81,7 +83,7 @@ const tests: TestCase[] = [
},
{
name: "Newly visited, visible line marker fades in",
tiles: [{ labels: [[lineMarkerBuilder(WORLD_SCALE), FADE_IN]] }],
tiles: [{ labels: [[lineMarkerBuilder(WORLD_SCALE), [FADE_IN, FADE_IN], [], []]] }],
frameTimes: FADE_CYCLE
},
{
Expand Down Expand Up @@ -113,7 +115,17 @@ const tests: TestCase[] = [
name: "Non-visited, persistent line marker is not rendered",
tiles: [
{
labels: [[lineMarkerBuilder(WORLD_SCALE), fadeInAndFadedOut(FADE_2_CYCLES.length)]],
labels: [
[
lineMarkerBuilder(WORLD_SCALE),
[
fadeInAndFadedOut(FADE_2_CYCLES.length),
fadeInAndFadedOut(FADE_2_CYCLES.length)
],
[],
[]
]
],
frames: firstNFrames(FADE_2_CYCLES, FADE_IN.length)
}
],
Expand Down Expand Up @@ -260,10 +272,17 @@ const tests: TestCase[] = [
tiles: [
{
labels: [
[lineMarkerBuilder(WORLD_SCALE, "P0").withPriority(0), FADE_IN_OUT],
[
lineMarkerBuilder(WORLD_SCALE, "P0").withPriority(0),
[FADE_IN_OUT, FADE_IN_OUT],
[],
[]
],
[
lineMarkerBuilder(WORLD_SCALE, "P1").withPriority(1),
fadeIn(FADE_IN_OUT.length)
[fadeIn(FADE_IN_OUT.length), fadeIn(FADE_IN_OUT.length)],
[],
[]
]
]
}
Expand Down Expand Up @@ -615,6 +634,56 @@ const tests: TestCase[] = [
],
frameTimes: FADE_2_CYCLES
},
{
name: "Line marker replaces predecessor with same text and nearby location without fading",
tiles: [
{
labels: [
[
lineMarkerBuilder(WORLD_SCALE).withPath(
createPath(WORLD_SCALE, [
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(0.3, 0.3, 0),
new THREE.Vector3(0.6, 0.6, 0)
])
),
[
fadeInAndFadedOut(FADE_2_CYCLES.length),
fadeInAndFadedOut(FADE_2_CYCLES.length),
fadeInAndFadedOut(FADE_2_CYCLES.length)
],
[], // all frames enabled
[] // same frame states for icons and text.
]
],
frames: firstNFrames(FADE_2_CYCLES, FADE_IN.length)
},
{
labels: [
[
lineMarkerBuilder(WORLD_SCALE).withPath(
createPath(WORLD_SCALE, [
new THREE.Vector3(0.3, 0.3, 0),
new THREE.Vector3(0.9, 0.9, 0)
])
),
[
fadedOut(FADE_IN.length).concat(
fadedIn(FADE_2_CYCLES.length - FADE_IN.length)
),
fadedOut(FADE_IN.length).concat(
fadeIn(FADE_2_CYCLES.length - FADE_IN.length)
)
],
[], // all frames enabled
[] // same frame states for icons and text.
]
],
frames: not(firstNFrames(FADE_2_CYCLES, FADE_IN.length))
}
],
frameTimes: FADE_2_CYCLES
},
// TERRAIN OVERLAY TEST CASES
{
name: "Point text only fades in when terrain is available",
Expand Down Expand Up @@ -657,9 +726,16 @@ const tests: TestCase[] = [
labels: [
[
lineMarkerBuilder(WORLD_SCALE),
fadedOut(FADE_IN.length).concat(
fadeIn(FADE_2_CYCLES.length - FADE_IN.length)
)
[
fadedOut(FADE_IN.length).concat(
fadeIn(FADE_2_CYCLES.length - FADE_IN.length)
),
fadedOut(FADE_IN.length).concat(
fadeIn(FADE_2_CYCLES.length - FADE_IN.length)
)
],
[],
[]
]
],
terrainFrames: not(firstNFrames(FADE_2_CYCLES, FADE_IN.length))
Expand Down Expand Up @@ -746,43 +822,58 @@ describe("TextElementsRenderer", function() {
}
});

type ElementFrameStates = Array<[TextElement, FadeState[][], FadeState[][] | undefined]>;
function buildLabels(
inputElements: InputTextElement[] | undefined,
elementFrameStates: Array<[TextElement, FadeState[], FadeState[] | undefined]>,
elementFrameStates: ElementFrameStates,
frameCount: number
): TextElement[] {
if (!inputElements) {
return [];
}
return inputElements.map((inputElement: InputTextElement) => {
expect(frameStates(inputElement).length).equal(
frameCount,
"frameStates of inputElement equals frameCount"
);
const iconStates = iconFrameStates(inputElement);
if (iconStates !== undefined) {
expect(iconStates.length).equal(
frameCount,
"iconFrameStates of inputElement equals frameCount"
);
let textFrameStates = frameStates(inputElement);
let iconStates = iconFrameStates(inputElement);

expect(textFrameStates).not.empty;

if (!Array.isArray(textFrameStates[0])) {
textFrameStates = [textFrameStates as FadeState[]];
if (iconStates !== undefined) {
iconStates = [iconStates as FadeState[]];
}
} else if (iconStates && iconStates.length > 0) {
expect(iconStates).has.lengthOf(textFrameStates.length);
}

textFrameStates.forEach((e: any) =>
expect(e).lengthOf(frameCount, "one state per frame required")
);

iconStates?.forEach((e: any) =>
expect(e).lengthOf(frameCount, "one state per frame required")
);
// Only used to identify some text elements for testing purposes.
const dummyUserData = {};
const element = builder(inputElement)
.withUserData(dummyUserData)
.build();
elementFrameStates.push([element, frameStates(inputElement), iconStates]);
elementFrameStates.push([
element,
textFrameStates as FadeState[][],
iconStates as FadeState[][]
]);
return element;
});
}
async function initTest(
test: TestCase
): Promise<{
elementFrameStates: Array<[TextElement, FadeState[], FadeState[]]>;
prevOpacities: number[];
elementFrameStates: ElementFrameStates;
prevOpacities: Array<[number, number]>;
}> {
// Array with all text elements and their corresponding expected frame states.
const elementFrameStates = new Array<[TextElement, FadeState[], FadeState[]]>();
const elementFrameStates: ElementFrameStates = new Array();

let enableElevation = false;
const allTileIndices: number[] = [];
Expand All @@ -808,7 +899,7 @@ describe("TextElementsRenderer", function() {
});

// Keeps track of the opacity that text elements had in the previous frame.
const prevOpacities: number[] = new Array(elementFrameStates.length).fill(0);
const prevOpacities = new Array(elementFrameStates.length).fill([0, 0]);

// Extra frame including all tiles to set the glyph loading state of all text elements
// to initialized.
Expand Down Expand Up @@ -859,25 +950,26 @@ describe("TextElementsRenderer", function() {
prepareTextElements(frameIdx, test.tiles, tileIdcs);
await fixture.renderFrame(frameTime, tileIdcs, terrainTileIdcs, collisionEnabled);

let elementIdx = 0;
let opacityIdx = 0;

for (const [
textElement,
expectedStates,
expectedIconStates
] of elementFrameStates) {
const expectedState = expectedStates[frameIdx];
const expectedIconState = expectedIconStates
? expectedIconStates[frameIdx]
: undefined;

const prevOpacity = prevOpacities[elementIdx];
const newOpacity = fixture.checkTextElementState(
textElement,
expectedState,
expectedIconState,
prevOpacity
);
prevOpacities[elementIdx++] = newOpacity;
let stateIdx = 0;
for (const textState of expectedStates) {
const elementNewOpacities = fixture.checkTextElementState(
textElement,
textState[frameIdx],
expectedIconStates?.[stateIdx][frameIdx],
prevOpacities[opacityIdx],
textElement.type === TextElementType.LineMarker ? stateIdx : undefined
);
prevOpacities[opacityIdx] = elementNewOpacities;
opacityIdx++;
stateIdx++;
}
}
}
});
Expand Down
Loading

0 comments on commit 059999b

Please sign in to comment.