@avimate/msfs-jest-utils 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +170 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +24 -0
- package/dist/mocks/CoherentMock.d.ts +74 -0
- package/dist/mocks/CoherentMock.js +148 -0
- package/dist/mocks/GarminSDKAdapter.d.ts +79 -0
- package/dist/mocks/GarminSDKAdapter.js +127 -0
- package/dist/mocks/MSFSGlobals.d.ts +6 -0
- package/dist/mocks/MSFSGlobals.js +514 -0
- package/dist/mocks/SDKAdapter.d.ts +126 -0
- package/dist/mocks/SDKAdapter.js +696 -0
- package/dist/mocks/SDKClasses.d.ts +32 -0
- package/dist/mocks/SDKClasses.js +118 -0
- package/dist/mocks/SimVarMock.d.ts +97 -0
- package/dist/mocks/SimVarMock.js +215 -0
- package/dist/mocks/index.d.ts +9 -0
- package/dist/mocks/index.js +25 -0
- package/dist/setupTests.d.ts +13 -0
- package/dist/setupTests.js +109 -0
- package/dist/test-utils/ComponentTestHelper.d.ts +73 -0
- package/dist/test-utils/ComponentTestHelper.js +558 -0
- package/dist/test-utils/ObservableTestHelper.d.ts +25 -0
- package/dist/test-utils/ObservableTestHelper.js +75 -0
- package/dist/test-utils/TestEnvironment.d.ts +76 -0
- package/dist/test-utils/TestEnvironment.js +227 -0
- package/dist/test-utils/index.d.ts +6 -0
- package/dist/test-utils/index.js +22 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ivan Slepchenko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# MSFS Unit Test Framework
|
|
2
|
+
|
|
3
|
+
Unit testing framework for MSFS HTML/JS instruments (Jest + JSDOM).
|
|
4
|
+
|
|
5
|
+
Фреймворк для unit-тестирования MSFS инструментов с поддержкой DOM через jsdom.
|
|
6
|
+
|
|
7
|
+
## Особенности
|
|
8
|
+
|
|
9
|
+
- ✅ **Полная поддержка DOM** - использует jsdom для рендеринга компонентов
|
|
10
|
+
- ✅ **FSComponent.render()** - можно рендерить компоненты и тестировать DOM элементы
|
|
11
|
+
- ✅ **Моки SimVar и Coherent** - полная эмуляция API симулятора
|
|
12
|
+
- ✅ **Jest интеграция** - готовые утилиты для тестирования
|
|
13
|
+
- ✅ **TypeScript поддержка** - полная типизация
|
|
14
|
+
|
|
15
|
+
## Установка
|
|
16
|
+
|
|
17
|
+
### As a library (recommended)
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install --save-dev @avimate/msfs-jest-utils
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Local development
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install
|
|
27
|
+
npm run build
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Использование
|
|
31
|
+
|
|
32
|
+
### Базовый пример
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { TestEnvironment, ComponentTestHelper } from './msfs-unit-test-framework';
|
|
36
|
+
import { MyComponent } from '../html_ui/MyComponent';
|
|
37
|
+
|
|
38
|
+
describe('MyComponent', () => {
|
|
39
|
+
let env: TestEnvironment;
|
|
40
|
+
let helper: ComponentTestHelper;
|
|
41
|
+
|
|
42
|
+
beforeEach(() => {
|
|
43
|
+
env = new TestEnvironment();
|
|
44
|
+
env.setup();
|
|
45
|
+
helper = new ComponentTestHelper(env);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
afterEach(() => {
|
|
49
|
+
helper.cleanup();
|
|
50
|
+
env.teardown();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('should render component', () => {
|
|
54
|
+
const { element } = helper.renderComponent(MyComponent, {
|
|
55
|
+
value: 42
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
expect(element).toBeTruthy();
|
|
59
|
+
expect(element.textContent).toContain('42');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('should update when SimVar changes', () => {
|
|
63
|
+
env.setSimVar('L:MY_VALUE', 'number', 10);
|
|
64
|
+
|
|
65
|
+
const { element } = helper.renderComponent(MyComponent, {
|
|
66
|
+
valueSource: env.getSubject('L:MY_VALUE', 'number')
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
expect(helper.getTextContent('.value')).toBe('10');
|
|
70
|
+
|
|
71
|
+
env.setSimVar('L:MY_VALUE', 'number', 20);
|
|
72
|
+
// Wait for subscription update
|
|
73
|
+
await helper.waitForUpdate(50);
|
|
74
|
+
|
|
75
|
+
expect(helper.getTextContent('.value')).toBe('20');
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Тестирование DOM элементов
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
test('should have correct CSS classes', () => {
|
|
84
|
+
const { element } = helper.renderComponent(MyComponent, {});
|
|
85
|
+
|
|
86
|
+
expect(helper.hasClass('.my-component', 'active')).toBe(true);
|
|
87
|
+
expect(helper.getAttribute('.my-component', 'data-state')).toBe('ready');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('should apply styles correctly', () => {
|
|
91
|
+
const { element } = helper.renderComponent(MyComponent, {
|
|
92
|
+
width: 100,
|
|
93
|
+
height: 200
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
expect(helper.getStyle('.my-component', 'width')).toBe('100px');
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Работа с SimVar
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
test('should read SimVar values', () => {
|
|
104
|
+
env.setSimVar('L:TEST_VALUE', 'number', 42);
|
|
105
|
+
|
|
106
|
+
const value = env.getSimVar('L:TEST_VALUE', 'number');
|
|
107
|
+
expect(value).toBe(42);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test('should track SimVar access', () => {
|
|
111
|
+
env.setSimVar('L:TEST', 'number', 10);
|
|
112
|
+
SimVar.GetSimVarValue('L:TEST', 'number');
|
|
113
|
+
|
|
114
|
+
const log = env.getSimVarAccessLog();
|
|
115
|
+
expect(log).toHaveLength(1);
|
|
116
|
+
expect(log[0].operation).toBe('get');
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## API
|
|
121
|
+
|
|
122
|
+
### TestEnvironment
|
|
123
|
+
|
|
124
|
+
- `setup()` - настройка тестового окружения
|
|
125
|
+
- `teardown()` - очистка после тестов
|
|
126
|
+
- `reset()` - сброс моков
|
|
127
|
+
- `setSimVar(name, unit, value)` - установить SimVar
|
|
128
|
+
- `getSimVar(name, unit)` - получить SimVar
|
|
129
|
+
- `getDocument()` - получить jsdom document
|
|
130
|
+
- `getWindow()` - получить jsdom window
|
|
131
|
+
|
|
132
|
+
### ComponentTestHelper
|
|
133
|
+
|
|
134
|
+
- `renderComponent(ComponentClass, props)` - рендерить компонент
|
|
135
|
+
- `querySelector(selector)` - найти элемент
|
|
136
|
+
- `getTextContent(selector)` - получить текст
|
|
137
|
+
- `hasClass(selector, className)` - проверить класс
|
|
138
|
+
- `getAttribute(selector, attrName)` - получить атрибут
|
|
139
|
+
- `getStyle(selector, property)` - получить стиль
|
|
140
|
+
- `waitForUpdate(ms)` - подождать обновления
|
|
141
|
+
- `cleanup()` - очистка
|
|
142
|
+
|
|
143
|
+
## Структура
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
msfs-unit-test-framework/
|
|
147
|
+
├── src/
|
|
148
|
+
│ ├── mocks/
|
|
149
|
+
│ │ ├── SimVarMock.ts # Мок SimVar API
|
|
150
|
+
│ │ ├── CoherentMock.ts # Мок Coherent API
|
|
151
|
+
│ │ └── index.ts
|
|
152
|
+
│ ├── test-utils/
|
|
153
|
+
│ │ ├── TestEnvironment.ts # Настройка окружения
|
|
154
|
+
│ │ ├── ComponentTestHelper.ts # Утилиты для компонентов
|
|
155
|
+
│ │ └── index.ts
|
|
156
|
+
│ ├── setupTests.ts # Jest setup
|
|
157
|
+
│ └── index.ts # Главный экспорт
|
|
158
|
+
├── tests/ # Примеры тестов
|
|
159
|
+
├── jest.config.js
|
|
160
|
+
├── tsconfig.json
|
|
161
|
+
└── package.json
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Примеры
|
|
165
|
+
|
|
166
|
+
Смотрите папку `tests/` для примеров использования.
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MSFS Unit Test Framework
|
|
4
|
+
*
|
|
5
|
+
* A comprehensive testing framework for MSFS HTML/JS instruments.
|
|
6
|
+
* Supports DOM testing via jsdom and FSComponent.render()
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
__exportStar(require("./mocks"), exports);
|
|
24
|
+
__exportStar(require("./test-utils"), exports);
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock implementation of Coherent Browser API for testing MSFS instruments.
|
|
3
|
+
*
|
|
4
|
+
* Coherent is the embedded browser used by MSFS. This mock provides:
|
|
5
|
+
* - Coherent.call() for calling simulator functions
|
|
6
|
+
* - Event system simulation
|
|
7
|
+
* - Browser API compatibility
|
|
8
|
+
*/
|
|
9
|
+
export interface CoherentCall {
|
|
10
|
+
method: string;
|
|
11
|
+
args: any[];
|
|
12
|
+
timestamp: number;
|
|
13
|
+
resolve?: (value: any) => void;
|
|
14
|
+
reject?: (error: any) => void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Mock Coherent Browser implementation
|
|
18
|
+
*/
|
|
19
|
+
export declare class CoherentMock {
|
|
20
|
+
private static instance;
|
|
21
|
+
private callHistory;
|
|
22
|
+
private eventListeners;
|
|
23
|
+
private callHandlers;
|
|
24
|
+
private maxHistorySize;
|
|
25
|
+
private constructor();
|
|
26
|
+
/**
|
|
27
|
+
* Get singleton instance
|
|
28
|
+
*/
|
|
29
|
+
static getInstance(): CoherentMock;
|
|
30
|
+
/**
|
|
31
|
+
* Initialize default call handlers for common MSFS functions
|
|
32
|
+
*/
|
|
33
|
+
private initializeDefaultHandlers;
|
|
34
|
+
/**
|
|
35
|
+
* Mock Coherent.call() - calls a function in the simulator
|
|
36
|
+
*/
|
|
37
|
+
call(method: string, ...args: any[]): Promise<any>;
|
|
38
|
+
/**
|
|
39
|
+
* Register a handler for a specific Coherent call
|
|
40
|
+
*/
|
|
41
|
+
registerHandler(method: string, handler: (...args: any[]) => any): void;
|
|
42
|
+
/**
|
|
43
|
+
* Trigger an event (simulates simulator events)
|
|
44
|
+
*/
|
|
45
|
+
triggerEvent(eventName: string, data: any): void;
|
|
46
|
+
/**
|
|
47
|
+
* Add event listener
|
|
48
|
+
*/
|
|
49
|
+
on(eventName: string, callback: (data: any) => void): void;
|
|
50
|
+
/**
|
|
51
|
+
* Remove event listener
|
|
52
|
+
*/
|
|
53
|
+
off(eventName: string, callback: (data: any) => void): void;
|
|
54
|
+
/**
|
|
55
|
+
* Get call history
|
|
56
|
+
*/
|
|
57
|
+
getCallHistory(): CoherentCall[];
|
|
58
|
+
/**
|
|
59
|
+
* Get calls for a specific method
|
|
60
|
+
*/
|
|
61
|
+
getCallsForMethod(method: string): CoherentCall[];
|
|
62
|
+
/**
|
|
63
|
+
* Clear call history
|
|
64
|
+
*/
|
|
65
|
+
clearHistory(): void;
|
|
66
|
+
/**
|
|
67
|
+
* Reset all handlers and history
|
|
68
|
+
*/
|
|
69
|
+
reset(): void;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Global Coherent mock instance
|
|
73
|
+
*/
|
|
74
|
+
export declare const coherentMock: CoherentMock;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Mock implementation of Coherent Browser API for testing MSFS instruments.
|
|
4
|
+
*
|
|
5
|
+
* Coherent is the embedded browser used by MSFS. This mock provides:
|
|
6
|
+
* - Coherent.call() for calling simulator functions
|
|
7
|
+
* - Event system simulation
|
|
8
|
+
* - Browser API compatibility
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.coherentMock = exports.CoherentMock = void 0;
|
|
12
|
+
/**
|
|
13
|
+
* Mock Coherent Browser implementation
|
|
14
|
+
*/
|
|
15
|
+
class CoherentMock {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.callHistory = [];
|
|
18
|
+
this.eventListeners = new Map();
|
|
19
|
+
this.callHandlers = new Map();
|
|
20
|
+
this.maxHistorySize = 10000;
|
|
21
|
+
this.initializeDefaultHandlers();
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get singleton instance
|
|
25
|
+
*/
|
|
26
|
+
static getInstance() {
|
|
27
|
+
if (!CoherentMock.instance) {
|
|
28
|
+
CoherentMock.instance = new CoherentMock();
|
|
29
|
+
}
|
|
30
|
+
return CoherentMock.instance;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Initialize default call handlers for common MSFS functions
|
|
34
|
+
*/
|
|
35
|
+
initializeDefaultHandlers() {
|
|
36
|
+
// SimVar set handlers - will be connected to SimVarMock in setup
|
|
37
|
+
this.registerHandler('setValueReg_Number', (id, value) => {
|
|
38
|
+
// This will be connected to SimVarMock in TestEnvironment
|
|
39
|
+
return Promise.resolve();
|
|
40
|
+
});
|
|
41
|
+
this.registerHandler('setValueReg_String', (id, value) => {
|
|
42
|
+
return Promise.resolve();
|
|
43
|
+
});
|
|
44
|
+
this.registerHandler('setValueReg_Bool', (id, value) => {
|
|
45
|
+
return Promise.resolve();
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Mock Coherent.call() - calls a function in the simulator
|
|
50
|
+
*/
|
|
51
|
+
call(method, ...args) {
|
|
52
|
+
const call = {
|
|
53
|
+
method,
|
|
54
|
+
args,
|
|
55
|
+
timestamp: Date.now()
|
|
56
|
+
};
|
|
57
|
+
this.callHistory.push(call);
|
|
58
|
+
// Keep history size manageable
|
|
59
|
+
if (this.callHistory.length > this.maxHistorySize) {
|
|
60
|
+
this.callHistory = this.callHistory.slice(-this.maxHistorySize);
|
|
61
|
+
}
|
|
62
|
+
// Check if we have a registered handler
|
|
63
|
+
const handler = this.callHandlers.get(method);
|
|
64
|
+
if (handler) {
|
|
65
|
+
try {
|
|
66
|
+
const result = handler(...args);
|
|
67
|
+
return Promise.resolve(result);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
return Promise.reject(error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Default: return resolved promise
|
|
74
|
+
return Promise.resolve(null);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Register a handler for a specific Coherent call
|
|
78
|
+
*/
|
|
79
|
+
registerHandler(method, handler) {
|
|
80
|
+
this.callHandlers.set(method, handler);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Trigger an event (simulates simulator events)
|
|
84
|
+
*/
|
|
85
|
+
triggerEvent(eventName, data) {
|
|
86
|
+
const listeners = this.eventListeners.get(eventName);
|
|
87
|
+
if (listeners) {
|
|
88
|
+
listeners.forEach(listener => {
|
|
89
|
+
try {
|
|
90
|
+
listener(data);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error(`Error in event listener for ${eventName}:`, error);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Add event listener
|
|
100
|
+
*/
|
|
101
|
+
on(eventName, callback) {
|
|
102
|
+
if (!this.eventListeners.has(eventName)) {
|
|
103
|
+
this.eventListeners.set(eventName, new Set());
|
|
104
|
+
}
|
|
105
|
+
this.eventListeners.get(eventName).add(callback);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Remove event listener
|
|
109
|
+
*/
|
|
110
|
+
off(eventName, callback) {
|
|
111
|
+
const listeners = this.eventListeners.get(eventName);
|
|
112
|
+
if (listeners) {
|
|
113
|
+
listeners.delete(callback);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get call history
|
|
118
|
+
*/
|
|
119
|
+
getCallHistory() {
|
|
120
|
+
return [...this.callHistory];
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get calls for a specific method
|
|
124
|
+
*/
|
|
125
|
+
getCallsForMethod(method) {
|
|
126
|
+
return this.callHistory.filter(call => call.method === method);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Clear call history
|
|
130
|
+
*/
|
|
131
|
+
clearHistory() {
|
|
132
|
+
this.callHistory = [];
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Reset all handlers and history
|
|
136
|
+
*/
|
|
137
|
+
reset() {
|
|
138
|
+
this.callHistory = [];
|
|
139
|
+
this.eventListeners.clear();
|
|
140
|
+
this.callHandlers.clear();
|
|
141
|
+
this.initializeDefaultHandlers();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
exports.CoherentMock = CoherentMock;
|
|
145
|
+
/**
|
|
146
|
+
* Global Coherent mock instance
|
|
147
|
+
*/
|
|
148
|
+
exports.coherentMock = CoherentMock.getInstance();
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Garmin SDK Adapter for Jest testing
|
|
3
|
+
*
|
|
4
|
+
* Minimal mocks for @microsoft/msfs-garminsdk required by StormScope components.
|
|
5
|
+
* Goal: exercise the unit-test framework, not re-implement Garmin SDK.
|
|
6
|
+
*/
|
|
7
|
+
import { DisplayComponent, Subject } from './SDKAdapter';
|
|
8
|
+
export declare enum WeatherRadarOperatingMode {
|
|
9
|
+
Weather = "Weather"
|
|
10
|
+
}
|
|
11
|
+
export declare enum WeatherRadarScanMode {
|
|
12
|
+
Horizontal = "Horizontal"
|
|
13
|
+
}
|
|
14
|
+
export declare enum MapTerrainMode {
|
|
15
|
+
None = "None",
|
|
16
|
+
Absolute = "Absolute",
|
|
17
|
+
Relative = "Relative",
|
|
18
|
+
Ground = "Ground"
|
|
19
|
+
}
|
|
20
|
+
export declare enum MapOrientation {
|
|
21
|
+
NorthUp = "NorthUp"
|
|
22
|
+
}
|
|
23
|
+
export declare enum UnitsDistanceSettingMode {
|
|
24
|
+
Nautical = "Nautical"
|
|
25
|
+
}
|
|
26
|
+
export declare const GarminMapKeys: {
|
|
27
|
+
readonly Units: "Units";
|
|
28
|
+
readonly Range: "Range";
|
|
29
|
+
readonly Terrain: "Terrain";
|
|
30
|
+
readonly Declutter: "Declutter";
|
|
31
|
+
readonly Orientation: "Orientation";
|
|
32
|
+
readonly Nexrad: "Nexrad";
|
|
33
|
+
};
|
|
34
|
+
export declare class MapUnitsModule {
|
|
35
|
+
constructor(_settingManager?: any);
|
|
36
|
+
}
|
|
37
|
+
export declare class MapDeclutterModule {
|
|
38
|
+
}
|
|
39
|
+
export declare class MapNexradModule {
|
|
40
|
+
readonly showNexrad: Subject<boolean>;
|
|
41
|
+
}
|
|
42
|
+
export declare class MapOrientationModule {
|
|
43
|
+
readonly orientation: Subject<MapOrientation>;
|
|
44
|
+
}
|
|
45
|
+
export type MapTerrainColorsDefinition = any;
|
|
46
|
+
export declare class MapTerrainModule {
|
|
47
|
+
readonly terrainMode: Subject<MapTerrainMode>;
|
|
48
|
+
}
|
|
49
|
+
export type MapWxrControllerModules = any;
|
|
50
|
+
export declare class MapWxrController {
|
|
51
|
+
constructor(_context: any);
|
|
52
|
+
}
|
|
53
|
+
export declare class MapRangeController {
|
|
54
|
+
private readonly rangeValues;
|
|
55
|
+
private readonly nominalRange;
|
|
56
|
+
private rangeIndex;
|
|
57
|
+
constructor(rangeValues: any[] | undefined, nominalRange: Subject<any>);
|
|
58
|
+
changeRangeIndex(delta: number): void;
|
|
59
|
+
setRangeIndex(index: number): void;
|
|
60
|
+
}
|
|
61
|
+
export declare const GarminMapBuilder: {
|
|
62
|
+
readonly range: symbol;
|
|
63
|
+
readonly orientation: symbol;
|
|
64
|
+
readonly declutter: symbol;
|
|
65
|
+
readonly terrainColors: symbol;
|
|
66
|
+
};
|
|
67
|
+
export interface WeatherRadarProps {
|
|
68
|
+
bingId: string;
|
|
69
|
+
bus: any;
|
|
70
|
+
ref?: any;
|
|
71
|
+
[key: string]: any;
|
|
72
|
+
}
|
|
73
|
+
export declare class WeatherRadar extends DisplayComponent<WeatherRadarProps> {
|
|
74
|
+
rootElement: any;
|
|
75
|
+
update: jest.Mock<any, any, any>;
|
|
76
|
+
wake: jest.Mock<any, any, any>;
|
|
77
|
+
sleep: jest.Mock<any, any, any>;
|
|
78
|
+
render(): any;
|
|
79
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Garmin SDK Adapter for Jest testing
|
|
4
|
+
*
|
|
5
|
+
* Minimal mocks for @microsoft/msfs-garminsdk required by StormScope components.
|
|
6
|
+
* Goal: exercise the unit-test framework, not re-implement Garmin SDK.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.WeatherRadar = exports.GarminMapBuilder = exports.MapRangeController = exports.MapWxrController = exports.MapTerrainModule = exports.MapOrientationModule = exports.MapNexradModule = exports.MapDeclutterModule = exports.MapUnitsModule = exports.GarminMapKeys = exports.UnitsDistanceSettingMode = exports.MapOrientation = exports.MapTerrainMode = exports.WeatherRadarScanMode = exports.WeatherRadarOperatingMode = void 0;
|
|
10
|
+
// IMPORTANT: This adapter is part of the test framework and should not depend on
|
|
11
|
+
// the real SDK runtime/types. Import from our own SDKAdapter instead.
|
|
12
|
+
const SDKAdapter_1 = require("./SDKAdapter");
|
|
13
|
+
// -----------------------------
|
|
14
|
+
// Enums / constants
|
|
15
|
+
// -----------------------------
|
|
16
|
+
var WeatherRadarOperatingMode;
|
|
17
|
+
(function (WeatherRadarOperatingMode) {
|
|
18
|
+
WeatherRadarOperatingMode["Weather"] = "Weather";
|
|
19
|
+
})(WeatherRadarOperatingMode || (exports.WeatherRadarOperatingMode = WeatherRadarOperatingMode = {}));
|
|
20
|
+
var WeatherRadarScanMode;
|
|
21
|
+
(function (WeatherRadarScanMode) {
|
|
22
|
+
WeatherRadarScanMode["Horizontal"] = "Horizontal";
|
|
23
|
+
})(WeatherRadarScanMode || (exports.WeatherRadarScanMode = WeatherRadarScanMode = {}));
|
|
24
|
+
var MapTerrainMode;
|
|
25
|
+
(function (MapTerrainMode) {
|
|
26
|
+
MapTerrainMode["None"] = "None";
|
|
27
|
+
MapTerrainMode["Absolute"] = "Absolute";
|
|
28
|
+
MapTerrainMode["Relative"] = "Relative";
|
|
29
|
+
MapTerrainMode["Ground"] = "Ground";
|
|
30
|
+
})(MapTerrainMode || (exports.MapTerrainMode = MapTerrainMode = {}));
|
|
31
|
+
var MapOrientation;
|
|
32
|
+
(function (MapOrientation) {
|
|
33
|
+
MapOrientation["NorthUp"] = "NorthUp";
|
|
34
|
+
})(MapOrientation || (exports.MapOrientation = MapOrientation = {}));
|
|
35
|
+
var UnitsDistanceSettingMode;
|
|
36
|
+
(function (UnitsDistanceSettingMode) {
|
|
37
|
+
UnitsDistanceSettingMode["Nautical"] = "Nautical";
|
|
38
|
+
})(UnitsDistanceSettingMode || (exports.UnitsDistanceSettingMode = UnitsDistanceSettingMode = {}));
|
|
39
|
+
exports.GarminMapKeys = {
|
|
40
|
+
Units: 'Units',
|
|
41
|
+
Range: 'Range',
|
|
42
|
+
Terrain: 'Terrain',
|
|
43
|
+
Declutter: 'Declutter',
|
|
44
|
+
Orientation: 'Orientation',
|
|
45
|
+
Nexrad: 'Nexrad',
|
|
46
|
+
};
|
|
47
|
+
// -----------------------------
|
|
48
|
+
// Module stubs used by map manager
|
|
49
|
+
// -----------------------------
|
|
50
|
+
class MapUnitsModule {
|
|
51
|
+
constructor(_settingManager) { }
|
|
52
|
+
}
|
|
53
|
+
exports.MapUnitsModule = MapUnitsModule;
|
|
54
|
+
class MapDeclutterModule {
|
|
55
|
+
}
|
|
56
|
+
exports.MapDeclutterModule = MapDeclutterModule;
|
|
57
|
+
class MapNexradModule {
|
|
58
|
+
constructor() {
|
|
59
|
+
this.showNexrad = SDKAdapter_1.Subject.create(false);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.MapNexradModule = MapNexradModule;
|
|
63
|
+
class MapOrientationModule {
|
|
64
|
+
constructor() {
|
|
65
|
+
this.orientation = SDKAdapter_1.Subject.create(MapOrientation.NorthUp);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.MapOrientationModule = MapOrientationModule;
|
|
69
|
+
class MapTerrainModule {
|
|
70
|
+
constructor() {
|
|
71
|
+
this.terrainMode = SDKAdapter_1.Subject.create(MapTerrainMode.Absolute);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.MapTerrainModule = MapTerrainModule;
|
|
75
|
+
class MapWxrController {
|
|
76
|
+
constructor(_context) { }
|
|
77
|
+
}
|
|
78
|
+
exports.MapWxrController = MapWxrController;
|
|
79
|
+
// -----------------------------
|
|
80
|
+
// Range controller used by StormScopeMapManager
|
|
81
|
+
// -----------------------------
|
|
82
|
+
class MapRangeController {
|
|
83
|
+
constructor(rangeValues = [], nominalRange) {
|
|
84
|
+
this.rangeValues = rangeValues;
|
|
85
|
+
this.nominalRange = nominalRange;
|
|
86
|
+
this.rangeIndex = 0;
|
|
87
|
+
}
|
|
88
|
+
changeRangeIndex(delta) {
|
|
89
|
+
this.setRangeIndex(this.rangeIndex + delta);
|
|
90
|
+
}
|
|
91
|
+
setRangeIndex(index) {
|
|
92
|
+
const clamped = Math.max(0, Math.min(index, this.rangeValues.length - 1));
|
|
93
|
+
this.rangeIndex = clamped;
|
|
94
|
+
const val = this.rangeValues[clamped];
|
|
95
|
+
if (val !== undefined) {
|
|
96
|
+
this.nominalRange.set(val);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.MapRangeController = MapRangeController;
|
|
101
|
+
// -----------------------------
|
|
102
|
+
// GarminMapBuilder tokens (consumed by MapSystemBuilder.with())
|
|
103
|
+
// -----------------------------
|
|
104
|
+
exports.GarminMapBuilder = {
|
|
105
|
+
range: Symbol('GarminMapBuilder.range'),
|
|
106
|
+
orientation: Symbol('GarminMapBuilder.orientation'),
|
|
107
|
+
declutter: Symbol('GarminMapBuilder.declutter'),
|
|
108
|
+
terrainColors: Symbol('GarminMapBuilder.terrainColors'),
|
|
109
|
+
};
|
|
110
|
+
class WeatherRadar extends SDKAdapter_1.DisplayComponent {
|
|
111
|
+
constructor() {
|
|
112
|
+
super(...arguments);
|
|
113
|
+
this.rootElement = null;
|
|
114
|
+
this.update = jest.fn();
|
|
115
|
+
this.wake = jest.fn();
|
|
116
|
+
this.sleep = jest.fn();
|
|
117
|
+
}
|
|
118
|
+
render() {
|
|
119
|
+
const vnode = SDKAdapter_1.FSComponent.buildComponent('div', {
|
|
120
|
+
id: `weather-radar-${this.props.bingId}`,
|
|
121
|
+
class: 'weather-radar',
|
|
122
|
+
});
|
|
123
|
+
this.rootElement = vnode?.instance ?? null;
|
|
124
|
+
return vnode;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
exports.WeatherRadar = WeatherRadar;
|