• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

visgl / deck.gl / 23691694676

28 Mar 2026 06:36PM UTC coverage: 79.906% (+0.03%) from 79.878%
23691694676

push

github

web-flow
chore: Upgrade to luma.gl 9.3.0-alpha.10 (#10123)

3047 of 3706 branches covered (82.22%)

Branch coverage included in aggregate %.

37 of 46 new or added lines in 9 files covered. (80.43%)

1 existing line in 1 file now uncovered.

13993 of 17619 relevant lines covered (79.42%)

26918.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

3.7
/modules/test-utils/src/test-runner.ts
1
// deck.gl
2
// SPDX-License-Identifier: MIT
3
// Copyright (c) vis.gl contributors
4

5
/* global window, console, setTimeout */
6
/* eslint-disable no-console */
7
import {Deck, DeckProps, MapView} from '@deck.gl/core';
8
import type {Device} from '@luma.gl/core';
9

10
const DEFAULT_DECK_PROPS: DeckProps<any> = {
2✔
11
  ...Deck.defaultProps,
12
  id: 'deckgl-render-test',
13
  width: 800,
14
  height: 450,
15
  style: {position: 'absolute', left: '0px', top: '0px'},
16
  views: [new MapView({})],
17
  useDevicePixels: false,
18
  debug: true
19
};
20

21
export type TestCase = {
22
  name: string;
23
  /** milliseconds to wait before aborting */
24
  timeout?: number;
25
};
26

27
type TestOptions<TestCaseT extends TestCase, ResultT> = {
28
  /** Called when a test case starts */
29
  onTestStart: (testCase: TestCaseT) => void;
30
  /** Called when a test case passes */
31
  onTestPass: (testCase: TestCaseT, result: ResultT) => void;
32
  /** Called when a test case fails */
33
  onTestFail: (testCase: TestCaseT, result: ResultT | {error: string}) => void;
34

35
  /** milliseconds to wait for each test case before aborting */
36
  timeout: number;
37
};
38

39
const DEFAULT_TEST_OPTIONS: TestOptions<TestCase, unknown> = {
2✔
40
  // test lifecycle callback
41
  onTestStart: testCase => console.log(`# ${testCase.name}`),
×
42
  onTestPass: testCase => console.log(`ok ${testCase.name} passed`),
×
43
  onTestFail: testCase => console.log(`not ok ${testCase.name} failed`),
×
44

45
  // milliseconds to wait for each test case before aborting
46
  timeout: 2000
47
};
48

49
export abstract class TestRunner<TestCaseT extends TestCase, ResultT, ExtraOptions = {}> {
50
  deck: Deck<any> | null = null;
×
51
  props: DeckProps<any>;
52
  isHeadless: boolean;
53
  isRunning: boolean = false;
×
54
  testOptions: TestOptions<TestCaseT, ResultT> & ExtraOptions;
55
  gpuVendor?: string;
56

57
  private _testCases: TestCaseT[] = [];
×
58
  private _currentTestCase: TestCaseT | null = null;
×
59
  private _testCaseData: unknown = null;
×
60

61
  /**
62
   * props
63
   *   Deck props
64
   */
65
  constructor(props: DeckProps = {}, options: ExtraOptions) {
66
    this.props = {...DEFAULT_DECK_PROPS, ...props};
×
67

68
    // @ts-ignore browserTestDriver_isHeadless is injected by @probe.gl/test-utils if running in headless browser
69
    this.isHeadless = Boolean(window.browserTestDriver_isHeadless);
×
70

71
    this.testOptions = {...DEFAULT_TEST_OPTIONS, ...options};
×
72
  }
73

74
  get defaultTestCase(): TestCaseT {
75
    throw new Error('Not implemented');
×
76
  }
77

78
  /**
79
   * Add testCase(s)
80
   */
81
  add(testCases: TestCaseT[]): this {
82
    if (!Array.isArray(testCases)) {
×
83
      testCases = [testCases];
×
84
    }
85
    for (const testCase of testCases) {
×
86
      this._testCases.push(testCase);
×
87
    }
88
    return this;
×
89
  }
90

91
  /**
92
   * Returns a promise that resolves when all the test cases are done
93
   */
94
  run(options: Partial<TestOptions<TestCaseT, ResultT> & ExtraOptions> = {}): Promise<void> {
95
    Object.assign(this.testOptions, options);
×
96

97
    return new Promise<void>((resolve, reject) => {
×
98
      this.deck = new Deck({
×
99
        ...this.props,
100
        onDeviceInitialized: this._onDeviceInitialized.bind(this),
101
        onLoad: resolve
102
      });
103

104
      this.isRunning = true;
×
105
      this._currentTestCase = null;
×
106
    })
107
      .then(() => {
108
        let promise = Promise.resolve();
×
109
        // chain test case promises
110
        this._testCases.forEach(testCase => {
×
111
          promise = promise.then(() => this._runTest(testCase));
×
112
        });
113
        return promise;
×
114
      })
115
      .catch((error: unknown) => {
116
        this.fail({error: (error as Error).message});
×
117
      })
118
      .finally(() => {
119
        this.deck!.finalize();
×
120
        this.deck = null;
×
121
      });
122
  }
123

124
  /* Lifecycle methods for subclassing */
125

126
  initTestCase(testCase: TestCaseT) {
127
    for (const key in this.defaultTestCase) {
×
128
      if (!(key in testCase)) {
×
129
        testCase[key] = this.defaultTestCase[key];
×
130
      }
131
    }
132
    this.testOptions.onTestStart(testCase);
×
133
  }
134

135
  /** Execute the test case. Fails if takes longer than options.timeout */
136
  abstract runTestCase(testCase: TestCaseT): Promise<void>;
137
  /** Check the result of the test case. Calls pass() or fail() */
138
  abstract assert(testCase: TestCaseT): Promise<void>;
139

140
  /* Utilities */
141

142
  protected pass(result: ResultT) {
143
    this.testOptions.onTestPass(this._currentTestCase!, result);
×
144
  }
145

146
  protected fail(result: ResultT | {error: string}) {
147
    this.testOptions.onTestFail(this._currentTestCase!, result);
×
148
  }
149

150
  /* Private Methods */
151

152
  private _onDeviceInitialized(device: Device) {
153
    this.gpuVendor = device.info.vendor;
×
154
  }
155

156
  private async _runTest(testCase: TestCaseT) {
157
    this._currentTestCase = testCase;
×
158

159
    // normalize test case
160
    this.initTestCase(testCase);
×
161

162
    const timeout = testCase.timeout || this.testOptions.timeout;
×
163
    const task = this.runTestCase(testCase);
×
164
    const timeoutTask = new Promise((_, reject) => {
×
165
      setTimeout(() => {
×
NEW
166
        reject(`Timeout after ${timeout}ms`);
×
167
      }, timeout);
168
    });
169

170
    try {
×
171
      await Promise.race([task, timeoutTask]);
×
172
      await this.assert(testCase);
×
173
    } catch (err: unknown) {
NEW
174
      if (typeof err === 'string' && err.startsWith('Timeout')) {
×
NEW
175
        this.fail({error: err});
×
176
      }
177
    }
178
  }
179
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc