File size: 4,878 Bytes
9f21d0a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// The suppression matrix. Everything the menu annotates and everything
// SurfaceModel executes comes from here, so this is where the rules are pinned.
import { describe, expect, test } from "vitest";

import { surfaceEffects, viewModeNote } from "./surfaceModels";

describe("surfaceEffects", () => {
  test("None draws nothing and takes nothing away", () => {
    for (const viewMode of ["3D", "2D", "Columbus", "Sky"]) {
      expect(surfaceEffects("None", viewMode)).toMatchObject({
        tileset: undefined,
        hideGlobe: false,
        terrain: undefined,
        inert: [],
      });
    }
  });

  test("OsmBuildings applies on the globe and in the sky, forcing World Terrain", () => {
    for (const viewMode of ["3D", "Sky"]) {
      expect(surfaceEffects("OsmBuildings", viewMode)).toMatchObject({
        tileset: "OsmBuildings",
        hideGlobe: false,
        terrain: "CesiumWorldTerrain",
        inert: ["terrain"],
      });
    }
  });

  // It adds to the globe rather than replacing it, so the imagery underneath is
  // still the map the user picked.
  test("OsmBuildings leaves the imagery selection meaningful", () => {
    expect(surfaceEffects("OsmBuildings", "3D").inert).not.toContain("layers");
  });

  test("GooglePhotorealistic hides the globe, taking imagery and terrain with it", () => {
    expect(surfaceEffects("GooglePhotorealistic", "Sky")).toMatchObject({
      tileset: "GooglePhotorealistic",
      hideGlobe: true,
      inert: ["layers", "terrain"],
    });
  });

  // The terrain is not overridden but not honoured either: a hidden globe loads
  // no terrain at all, so the user's choice simply waits.
  test("GooglePhotorealistic imposes no terrain of its own", () => {
    expect(surfaceEffects("GooglePhotorealistic", "Sky").terrain).toBeUndefined();
  });

  test("GooglePhotorealistic is the sky view only", () => {
    for (const viewMode of ["3D", "2D", "Columbus"]) {
      const effects = surfaceEffects("GooglePhotorealistic", viewMode);
      expect(effects.tileset).toBeUndefined();
      expect(effects.unavailable).toContain("GooglePhotorealistic");
    }
    expect(surfaceEffects("GooglePhotorealistic", "Sky").unavailable).not.toContain("GooglePhotorealistic");
  });

  test("no surface model applies in 2D or Columbus", () => {
    for (const viewMode of ["2D", "Columbus"]) {
      expect(surfaceEffects("OsmBuildings", viewMode).tileset).toBeUndefined();
      expect(surfaceEffects("GooglePhotorealistic", viewMode).tileset).toBeUndefined();
      expect(surfaceEffects("None", viewMode).unavailable).not.toContain("None");
    }
  });

  // Suppression, not deselection: a model that cannot apply here takes nothing
  // else with it, so the imagery and terrain controls still tell the truth.
  test("a suppressed model leaves the other groups alone", () => {
    expect(surfaceEffects("GooglePhotorealistic", "3D")).toMatchObject({
      hideGlobe: false,
      terrain: undefined,
      inert: [],
    });
  });

  // The url is validated before it reaches the store, but the matrix is asked
  // about the store's value and must not be the thing that throws.
  test("an unknown name is read as None", () => {
    expect(surfaceEffects("Garbage", "Sky")).toMatchObject({ tileset: undefined, hideGlobe: false, inert: [] });
  });

  test("an unknown view mode grounds every model", () => {
    const effects = surfaceEffects("OsmBuildings", "Garbage");
    expect(effects.tileset).toBeUndefined();
    expect(effects.unavailable).toEqual(["None", "OsmBuildings", "GooglePhotorealistic"]);
  });
});

// The menu's explanation has to come from the rules, not from a sentence written
// out beside them: a hardcoded one silently lies the moment `viewModes` widens,
// which is the drift the pure matrix exists to prevent.
describe("viewModeNote", () => {
  test("names the single view mode a model applies in", () => {
    expect(viewModeNote("GooglePhotorealistic")).toBe("Applies in the sky view only");
  });

  test("names several, and pluralises", () => {
    expect(viewModeNote("OsmBuildings")).toBe("Applies in the 3D and sky views only");
  });

  test("tracks the rules rather than restating them", () => {
    // The note must mention every mode the model is actually allowed in. Derived
    // from surfaceEffects so this test cannot pass by agreeing with a constant.
    const allowed = ["3D", "2D", "Columbus", "Sky"].filter((viewMode) => !surfaceEffects("OsmBuildings", viewMode).unavailable.includes("OsmBuildings"));
    const note = viewModeNote("OsmBuildings");
    expect(allowed.length).toBeGreaterThan(0);
    for (const viewMode of allowed) {
      expect(note.toLowerCase()).toContain(viewMode === "Sky" ? "sky" : viewMode.toLowerCase());
    }
  });

  test("has nothing to say about a name it does not know", () => {
    expect(viewModeNote("Garbage")).toBe("");
  });
});