@ingissa/navcore-simulator 1.0.8 → 1.0.9
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/README.md +2 -0
- package/dist/index.d.mts +87 -0
- package/dist/{simulator/src/react-native/useSimulator.d.ts → index.d.ts} +37 -9
- package/dist/index.js +1393 -0
- package/dist/index.mjs +1383 -0
- package/dist/node.d.mts +527 -0
- package/dist/node.d.ts +527 -0
- package/dist/node.js +957 -0
- package/dist/node.mjs +949 -0
- package/dist/react-native.d.mts +4 -0
- package/dist/react-native.d.ts +4 -0
- package/dist/react-native.js +1393 -0
- package/dist/react-native.mjs +1383 -0
- package/package.json +19 -16
- package/dist/core/src/NavCore.d.ts +0 -142
- package/dist/core/src/NavCore.d.ts.map +0 -1
- package/dist/core/src/NavCore.js +0 -390
- package/dist/core/src/bearing/BearingEngine.d.ts +0 -24
- package/dist/core/src/bearing/BearingEngine.d.ts.map +0 -1
- package/dist/core/src/bearing/BearingEngine.js +0 -50
- package/dist/core/src/constants.d.ts +0 -34
- package/dist/core/src/constants.d.ts.map +0 -1
- package/dist/core/src/constants.js +0 -41
- package/dist/core/src/corridor/DeviationDetector.d.ts +0 -33
- package/dist/core/src/corridor/DeviationDetector.d.ts.map +0 -1
- package/dist/core/src/corridor/DeviationDetector.js +0 -83
- package/dist/core/src/corridor/DynamicCorridor.d.ts +0 -13
- package/dist/core/src/corridor/DynamicCorridor.d.ts.map +0 -1
- package/dist/core/src/corridor/DynamicCorridor.js +0 -26
- package/dist/core/src/dead-reckoning/DeadReckoning.d.ts +0 -35
- package/dist/core/src/dead-reckoning/DeadReckoning.d.ts.map +0 -1
- package/dist/core/src/dead-reckoning/DeadReckoning.js +0 -49
- package/dist/core/src/directions/DirectionsProvider.d.ts +0 -70
- package/dist/core/src/directions/DirectionsProvider.d.ts.map +0 -1
- package/dist/core/src/directions/DirectionsProvider.js +0 -7
- package/dist/core/src/directions/OSRMDirectionsProvider.d.ts +0 -26
- package/dist/core/src/directions/OSRMDirectionsProvider.d.ts.map +0 -1
- package/dist/core/src/directions/OSRMDirectionsProvider.js +0 -90
- package/dist/core/src/directions/OpenRouteServiceProvider.d.ts +0 -30
- package/dist/core/src/directions/OpenRouteServiceProvider.d.ts.map +0 -1
- package/dist/core/src/directions/OpenRouteServiceProvider.js +0 -111
- package/dist/core/src/directions/ValhallaDirectionsProvider.d.ts +0 -33
- package/dist/core/src/directions/ValhallaDirectionsProvider.d.ts.map +0 -1
- package/dist/core/src/directions/ValhallaDirectionsProvider.js +0 -155
- package/dist/core/src/eta/ETAEngine.d.ts +0 -61
- package/dist/core/src/eta/ETAEngine.d.ts.map +0 -1
- package/dist/core/src/eta/ETAEngine.js +0 -74
- package/dist/core/src/features.d.ts +0 -76
- package/dist/core/src/features.d.ts.map +0 -1
- package/dist/core/src/features.js +0 -76
- package/dist/core/src/geo/bearing.d.ts +0 -11
- package/dist/core/src/geo/bearing.d.ts.map +0 -1
- package/dist/core/src/geo/bearing.js +0 -25
- package/dist/core/src/geo/cumulative.d.ts +0 -9
- package/dist/core/src/geo/cumulative.d.ts.map +0 -1
- package/dist/core/src/geo/cumulative.js +0 -20
- package/dist/core/src/geo/haversine.d.ts +0 -13
- package/dist/core/src/geo/haversine.d.ts.map +0 -1
- package/dist/core/src/geo/haversine.js +0 -39
- package/dist/core/src/geo/projection.d.ts +0 -7
- package/dist/core/src/geo/projection.d.ts.map +0 -1
- package/dist/core/src/geo/projection.js +0 -17
- package/dist/core/src/geofencing/GeofencingEngine.d.ts +0 -93
- package/dist/core/src/geofencing/GeofencingEngine.d.ts.map +0 -1
- package/dist/core/src/geofencing/GeofencingEngine.js +0 -154
- package/dist/core/src/index.d.ts +0 -66
- package/dist/core/src/index.d.ts.map +0 -1
- package/dist/core/src/index.js +0 -62
- package/dist/core/src/kalman/KalmanFilter2D.d.ts +0 -46
- package/dist/core/src/kalman/KalmanFilter2D.d.ts.map +0 -1
- package/dist/core/src/kalman/KalmanFilter2D.js +0 -77
- package/dist/core/src/license/LicenseManager.d.ts +0 -40
- package/dist/core/src/license/LicenseManager.d.ts.map +0 -1
- package/dist/core/src/license/LicenseManager.js +0 -119
- package/dist/core/src/license/verifyP256Signature.d.ts +0 -2
- package/dist/core/src/license/verifyP256Signature.d.ts.map +0 -1
- package/dist/core/src/license/verifyP256Signature.js +0 -26
- package/dist/core/src/off-route/NavigationFSM.d.ts +0 -42
- package/dist/core/src/off-route/NavigationFSM.d.ts.map +0 -1
- package/dist/core/src/off-route/NavigationFSM.js +0 -56
- package/dist/core/src/off-route/OffRouteFSM.d.ts +0 -70
- package/dist/core/src/off-route/OffRouteFSM.d.ts.map +0 -1
- package/dist/core/src/off-route/OffRouteFSM.js +0 -151
- package/dist/core/src/predictor/RouteOffsetPredictor.d.ts +0 -24
- package/dist/core/src/predictor/RouteOffsetPredictor.d.ts.map +0 -1
- package/dist/core/src/predictor/RouteOffsetPredictor.js +0 -55
- package/dist/core/src/progress/InstructionEditor.d.ts +0 -77
- package/dist/core/src/progress/InstructionEditor.d.ts.map +0 -1
- package/dist/core/src/progress/InstructionEditor.js +0 -151
- package/dist/core/src/progress/InstructionResolver.d.ts +0 -25
- package/dist/core/src/progress/InstructionResolver.d.ts.map +0 -1
- package/dist/core/src/progress/InstructionResolver.js +0 -78
- package/dist/core/src/progress/ProgressTracker.d.ts +0 -12
- package/dist/core/src/progress/ProgressTracker.d.ts.map +0 -1
- package/dist/core/src/progress/ProgressTracker.js +0 -22
- package/dist/core/src/renderer/MapRendererAdapter.d.ts +0 -72
- package/dist/core/src/renderer/MapRendererAdapter.d.ts.map +0 -1
- package/dist/core/src/renderer/MapRendererAdapter.js +0 -19
- package/dist/core/src/route-builder/CustomRouteBuilder.d.ts +0 -83
- package/dist/core/src/route-builder/CustomRouteBuilder.d.ts.map +0 -1
- package/dist/core/src/route-builder/CustomRouteBuilder.js +0 -160
- package/dist/core/src/route-plan/RoutePlan.d.ts +0 -38
- package/dist/core/src/route-plan/RoutePlan.d.ts.map +0 -1
- package/dist/core/src/route-plan/RoutePlan.js +0 -102
- package/dist/core/src/session/NavigationSession.d.ts +0 -81
- package/dist/core/src/session/NavigationSession.d.ts.map +0 -1
- package/dist/core/src/session/NavigationSession.js +0 -115
- package/dist/core/src/snapper/ParallelRoadResolver.d.ts +0 -86
- package/dist/core/src/snapper/ParallelRoadResolver.d.ts.map +0 -1
- package/dist/core/src/snapper/ParallelRoadResolver.js +0 -83
- package/dist/core/src/snapper/RouteSnapper.d.ts +0 -38
- package/dist/core/src/snapper/RouteSnapper.d.ts.map +0 -1
- package/dist/core/src/snapper/RouteSnapper.js +0 -80
- package/dist/core/src/voice/VoiceTriggerEngine.d.ts +0 -80
- package/dist/core/src/voice/VoiceTriggerEngine.d.ts.map +0 -1
- package/dist/core/src/voice/VoiceTriggerEngine.js +0 -108
- package/dist/simulator/src/core/NoiseEngine.d.ts +0 -46
- package/dist/simulator/src/core/NoiseEngine.d.ts.map +0 -1
- package/dist/simulator/src/core/NoiseEngine.js +0 -106
- package/dist/simulator/src/core/RouteWalker.d.ts +0 -78
- package/dist/simulator/src/core/RouteWalker.d.ts.map +0 -1
- package/dist/simulator/src/core/RouteWalker.js +0 -180
- package/dist/simulator/src/core/SimulatorEngine.d.ts +0 -53
- package/dist/simulator/src/core/SimulatorEngine.d.ts.map +0 -1
- package/dist/simulator/src/core/SimulatorEngine.js +0 -298
- package/dist/simulator/src/core/types.d.ts +0 -157
- package/dist/simulator/src/core/types.d.ts.map +0 -1
- package/dist/simulator/src/core/types.js +0 -7
- package/dist/simulator/src/fleet/FleetSimulator.d.ts +0 -60
- package/dist/simulator/src/fleet/FleetSimulator.d.ts.map +0 -1
- package/dist/simulator/src/fleet/FleetSimulator.js +0 -114
- package/dist/simulator/src/index.d.ts +0 -28
- package/dist/simulator/src/index.d.ts.map +0 -1
- package/dist/simulator/src/index.js +0 -29
- package/dist/simulator/src/node.d.ts +0 -26
- package/dist/simulator/src/node.d.ts.map +0 -1
- package/dist/simulator/src/node.js +0 -25
- package/dist/simulator/src/react-native/SimulatorControls.d.ts +0 -35
- package/dist/simulator/src/react-native/SimulatorControls.d.ts.map +0 -1
- package/dist/simulator/src/react-native/SimulatorControls.js +0 -254
- package/dist/simulator/src/react-native/useSimulator.d.ts.map +0 -1
- package/dist/simulator/src/react-native/useSimulator.js +0 -100
- package/dist/simulator/src/replay/GpxParser.d.ts +0 -40
- package/dist/simulator/src/replay/GpxParser.d.ts.map +0 -1
- package/dist/simulator/src/replay/GpxParser.js +0 -95
- package/dist/simulator/src/replay/SessionRecorder.d.ts +0 -37
- package/dist/simulator/src/replay/SessionRecorder.d.ts.map +0 -1
- package/dist/simulator/src/replay/SessionRecorder.js +0 -120
- package/dist/simulator/src/scenarios/ScenarioInjector.d.ts +0 -55
- package/dist/simulator/src/scenarios/ScenarioInjector.d.ts.map +0 -1
- package/dist/simulator/src/scenarios/ScenarioInjector.js +0 -150
- package/src/__tests__/integration/simulator-pipeline.test.ts +0 -233
- package/src/core/NoiseEngine.ts +0 -137
- package/src/core/RouteWalker.ts +0 -227
- package/src/core/SimulatorEngine.ts +0 -364
- package/src/core/__tests__/NoiseEngine.test.ts +0 -131
- package/src/core/__tests__/RouteWalker.test.ts +0 -139
- package/src/core/__tests__/SimulatorEngine.test.ts +0 -317
- package/src/core/types.ts +0 -191
- package/src/fleet/FleetSimulator.ts +0 -162
- package/src/index.ts +0 -54
- package/src/node.ts +0 -48
- package/src/react-native/SimulatorControls.tsx +0 -473
- package/src/react-native/useSimulator.ts +0 -155
- package/src/replay/GpxParser.ts +0 -122
- package/src/replay/SessionRecorder.ts +0 -138
- package/src/replay/__tests__/GpxParser.test.ts +0 -136
- package/src/scenarios/ScenarioInjector.ts +0 -170
- package/src/scenarios/__tests__/ScenarioInjector.test.ts +0 -171
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ScenarioInjector — Registers and fires Scenario objects at geometry indices.
|
|
3
|
-
*
|
|
4
|
-
* Called internally by SimulatorEngine on each tick.
|
|
5
|
-
* Also provides static factory methods for the built-in scenario types.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { Scenario } from '../core/types';
|
|
9
|
-
|
|
10
|
-
export type ScenarioFireCallback = (scenario: Scenario) => void;
|
|
11
|
-
export type ScenarioEndCallback = (scenario: Scenario) => void;
|
|
12
|
-
|
|
13
|
-
export class ScenarioInjector {
|
|
14
|
-
/** Map from triggerIndex → Scenario */
|
|
15
|
-
private readonly scenarios = new Map<number, Scenario>();
|
|
16
|
-
/** Tracks which scenarios have already fired (by name) to avoid double-fire */
|
|
17
|
-
private readonly fired = new Set<string>();
|
|
18
|
-
/** Currently active scenario, if any */
|
|
19
|
-
private _activeScenario: Scenario | null = null;
|
|
20
|
-
private _activeEndTimer: ReturnType<typeof setTimeout> | null = null;
|
|
21
|
-
|
|
22
|
-
private onStart: ScenarioFireCallback;
|
|
23
|
-
private onEnd: ScenarioEndCallback;
|
|
24
|
-
|
|
25
|
-
constructor(onStart?: ScenarioFireCallback, onEnd?: ScenarioEndCallback) {
|
|
26
|
-
this.onStart = onStart ?? (() => undefined);
|
|
27
|
-
this.onEnd = onEnd ?? (() => undefined);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// ── Registration ────────────────────────────────────────────────────────────
|
|
31
|
-
|
|
32
|
-
register(scenario: Scenario): void {
|
|
33
|
-
this.scenarios.set(scenario.triggerIndex, scenario);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
remove(name: string): void {
|
|
37
|
-
for (const [idx, s] of this.scenarios) {
|
|
38
|
-
if (s.name === name) {
|
|
39
|
-
this.scenarios.delete(idx);
|
|
40
|
-
break;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
clear(): void {
|
|
46
|
-
this.scenarios.clear();
|
|
47
|
-
this.fired.clear();
|
|
48
|
-
this._clearActiveTimer();
|
|
49
|
-
this._activeScenario = null;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// ── Tick ────────────────────────────────────────────────────────────────────
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Check and fire any scenario whose triggerIndex matches (or was passed) by
|
|
56
|
-
* currentIndex. Called by SimulatorEngine on every tick.
|
|
57
|
-
*
|
|
58
|
-
* Returns the name of the active scenario (if any), for metadata injection.
|
|
59
|
-
*/
|
|
60
|
-
tick(currentIndex: number): string | undefined {
|
|
61
|
-
const floorIdx = Math.floor(currentIndex);
|
|
62
|
-
|
|
63
|
-
for (const [triggerIdx, scenario] of this.scenarios) {
|
|
64
|
-
if (floorIdx >= triggerIdx && !this.fired.has(scenario.name)) {
|
|
65
|
-
this.fired.add(scenario.name);
|
|
66
|
-
this._fire(scenario);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return this._activeScenario?.name;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
get activeScenario(): Scenario | null {
|
|
74
|
-
return this._activeScenario;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/** Clean up any pending timers */
|
|
78
|
-
destroy(): void {
|
|
79
|
-
this._clearActiveTimer();
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// ── Static factories ────────────────────────────────────────────────────────
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* GPS blackout: no position updates for `durationMs`.
|
|
86
|
-
* Engine handles signal loss; this scenario signals the blackout period.
|
|
87
|
-
*/
|
|
88
|
-
static gpsBlackout(atIndex: number, durationMs: number): Scenario {
|
|
89
|
-
return {
|
|
90
|
-
name: `gps-blackout-@${atIndex}`,
|
|
91
|
-
triggerIndex: atIndex,
|
|
92
|
-
type: 'GPS_BLACKOUT',
|
|
93
|
-
durationMs,
|
|
94
|
-
params: { durationMs },
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Wrong-side road: offset the simulated position by `offsetM` metres
|
|
100
|
-
* perpendicular to the route to stress-test the parallel road resolver.
|
|
101
|
-
*/
|
|
102
|
-
static wrongSideRoad(atIndex: number, offsetM: number): Scenario {
|
|
103
|
-
return {
|
|
104
|
-
name: `wrong-side-@${atIndex}`,
|
|
105
|
-
triggerIndex: atIndex,
|
|
106
|
-
type: 'WRONG_SIDE_ROAD',
|
|
107
|
-
params: { offsetM },
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/** U-turn at the given index — stress-tests U-turn protection. */
|
|
112
|
-
static uTurn(atIndex: number): Scenario {
|
|
113
|
-
return {
|
|
114
|
-
name: `uturn-@${atIndex}`,
|
|
115
|
-
triggerIndex: atIndex,
|
|
116
|
-
type: 'UTURN',
|
|
117
|
-
params: {},
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/** Speed spike: briefly report spikeKmh instead of the configured speed. */
|
|
122
|
-
static speedSpike(atIndex: number, spikeKmh: number, durationMs = 2000): Scenario {
|
|
123
|
-
return {
|
|
124
|
-
name: `speed-spike-@${atIndex}`,
|
|
125
|
-
triggerIndex: atIndex,
|
|
126
|
-
type: 'SPEED_SPIKE',
|
|
127
|
-
durationMs,
|
|
128
|
-
params: { spikeKmh },
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Accuracy drop: GPS accuracy degrades to newAccuracyM for durationMs.
|
|
134
|
-
*/
|
|
135
|
-
static accuracyDrop(atIndex: number, newAccuracyM: number, durationMs: number): Scenario {
|
|
136
|
-
return {
|
|
137
|
-
name: `accuracy-drop-@${atIndex}`,
|
|
138
|
-
triggerIndex: atIndex,
|
|
139
|
-
type: 'ACCURACY_DROP',
|
|
140
|
-
durationMs,
|
|
141
|
-
params: { newAccuracyM },
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// ── Private ─────────────────────────────────────────────────────────────────
|
|
146
|
-
|
|
147
|
-
private _fire(scenario: Scenario): void {
|
|
148
|
-
this._activeScenario = scenario;
|
|
149
|
-
try { this.onStart(scenario); } catch (_) { /* never throw from callback */ }
|
|
150
|
-
|
|
151
|
-
if (scenario.durationMs != null && scenario.durationMs > 0) {
|
|
152
|
-
this._clearActiveTimer();
|
|
153
|
-
this._activeEndTimer = setTimeout(() => {
|
|
154
|
-
this._activeScenario = null;
|
|
155
|
-
try { this.onEnd(scenario); } catch (_) { /* never throw */ }
|
|
156
|
-
}, scenario.durationMs);
|
|
157
|
-
} else {
|
|
158
|
-
// Instantaneous scenario — end immediately
|
|
159
|
-
this._activeScenario = null;
|
|
160
|
-
try { this.onEnd(scenario); } catch (_) { /* never throw */ }
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
private _clearActiveTimer(): void {
|
|
165
|
-
if (this._activeEndTimer !== null) {
|
|
166
|
-
clearTimeout(this._activeEndTimer);
|
|
167
|
-
this._activeEndTimer = null;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ScenarioInjector unit tests
|
|
3
|
-
*/
|
|
4
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
5
|
-
import { ScenarioInjector } from '@ingissa/navcore-simulator';
|
|
6
|
-
|
|
7
|
-
describe('ScenarioInjector', () => {
|
|
8
|
-
describe('register + tick', () => {
|
|
9
|
-
it('fires callback at the correct index', () => {
|
|
10
|
-
const onStart = vi.fn();
|
|
11
|
-
const injector = new ScenarioInjector(onStart);
|
|
12
|
-
const scenario = ScenarioInjector.gpsBlackout(5, 1000);
|
|
13
|
-
injector.register(scenario);
|
|
14
|
-
|
|
15
|
-
// Not yet
|
|
16
|
-
injector.tick(3);
|
|
17
|
-
expect(onStart).not.toHaveBeenCalled();
|
|
18
|
-
|
|
19
|
-
// At trigger index
|
|
20
|
-
injector.tick(5);
|
|
21
|
-
expect(onStart).toHaveBeenCalledOnce();
|
|
22
|
-
expect(onStart.mock.calls[0]![0].type).toBe('GPS_BLACKOUT');
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('fires when index passes the trigger (skipped frame)', () => {
|
|
26
|
-
const onStart = vi.fn();
|
|
27
|
-
const injector = new ScenarioInjector(onStart);
|
|
28
|
-
injector.register(ScenarioInjector.gpsBlackout(10, 500));
|
|
29
|
-
|
|
30
|
-
// Jump from 5 to 15 — trigger at 10 should still fire
|
|
31
|
-
injector.tick(15);
|
|
32
|
-
expect(onStart).toHaveBeenCalledOnce();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('does NOT double-fire the same scenario', () => {
|
|
36
|
-
const onStart = vi.fn();
|
|
37
|
-
const injector = new ScenarioInjector(onStart);
|
|
38
|
-
injector.register(ScenarioInjector.gpsBlackout(3, 500));
|
|
39
|
-
|
|
40
|
-
injector.tick(3);
|
|
41
|
-
injector.tick(3);
|
|
42
|
-
injector.tick(5);
|
|
43
|
-
expect(onStart).toHaveBeenCalledTimes(1);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('fires onEnd after durationMs (via setTimeout)', () => {
|
|
47
|
-
vi.useFakeTimers();
|
|
48
|
-
const onEnd = vi.fn();
|
|
49
|
-
const injector = new ScenarioInjector(undefined, onEnd);
|
|
50
|
-
injector.register(ScenarioInjector.gpsBlackout(0, 2000));
|
|
51
|
-
|
|
52
|
-
injector.tick(0);
|
|
53
|
-
expect(onEnd).not.toHaveBeenCalled();
|
|
54
|
-
|
|
55
|
-
vi.advanceTimersByTime(2000);
|
|
56
|
-
expect(onEnd).toHaveBeenCalledOnce();
|
|
57
|
-
vi.useRealTimers();
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('fires onEnd immediately for instantaneous scenario (no durationMs)', () => {
|
|
61
|
-
const onEnd = vi.fn();
|
|
62
|
-
const injector = new ScenarioInjector(undefined, onEnd);
|
|
63
|
-
injector.register(ScenarioInjector.uTurn(5));
|
|
64
|
-
|
|
65
|
-
injector.tick(5);
|
|
66
|
-
expect(onEnd).toHaveBeenCalledOnce();
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe('remove', () => {
|
|
71
|
-
it('removes a scenario by name before it fires', () => {
|
|
72
|
-
const onStart = vi.fn();
|
|
73
|
-
const injector = new ScenarioInjector(onStart);
|
|
74
|
-
const s = ScenarioInjector.gpsBlackout(4, 1000);
|
|
75
|
-
injector.register(s);
|
|
76
|
-
injector.remove(s.name);
|
|
77
|
-
|
|
78
|
-
injector.tick(4);
|
|
79
|
-
expect(onStart).not.toHaveBeenCalled();
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
describe('clear', () => {
|
|
84
|
-
it('removes all scenarios', () => {
|
|
85
|
-
const onStart = vi.fn();
|
|
86
|
-
const injector = new ScenarioInjector(onStart);
|
|
87
|
-
injector.register(ScenarioInjector.gpsBlackout(1, 500));
|
|
88
|
-
injector.register(ScenarioInjector.uTurn(2));
|
|
89
|
-
injector.clear();
|
|
90
|
-
|
|
91
|
-
injector.tick(5);
|
|
92
|
-
expect(onStart).not.toHaveBeenCalled();
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
describe('activeScenario', () => {
|
|
97
|
-
it('is null before firing', () => {
|
|
98
|
-
const injector = new ScenarioInjector();
|
|
99
|
-
injector.register(ScenarioInjector.gpsBlackout(5, 5000));
|
|
100
|
-
expect(injector.activeScenario).toBeNull();
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it('is set after firing (while durationMs pending)', () => {
|
|
104
|
-
vi.useFakeTimers();
|
|
105
|
-
const injector = new ScenarioInjector();
|
|
106
|
-
injector.register(ScenarioInjector.gpsBlackout(0, 5000));
|
|
107
|
-
injector.tick(0);
|
|
108
|
-
expect(injector.activeScenario?.type).toBe('GPS_BLACKOUT');
|
|
109
|
-
vi.useRealTimers();
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
describe('tick returns active scenario name', () => {
|
|
114
|
-
it('returns undefined when no scenario is active', () => {
|
|
115
|
-
const injector = new ScenarioInjector();
|
|
116
|
-
injector.register(ScenarioInjector.gpsBlackout(10, 1000));
|
|
117
|
-
const result = injector.tick(0);
|
|
118
|
-
expect(result).toBeUndefined();
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it('returns scenario name after it fires', () => {
|
|
122
|
-
vi.useFakeTimers();
|
|
123
|
-
const injector = new ScenarioInjector();
|
|
124
|
-
const s = ScenarioInjector.gpsBlackout(0, 5000);
|
|
125
|
-
injector.register(s);
|
|
126
|
-
injector.tick(0);
|
|
127
|
-
const name = injector.tick(1);
|
|
128
|
-
expect(name).toBe(s.name);
|
|
129
|
-
vi.useRealTimers();
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
describe('Static factories', () => {
|
|
134
|
-
it('gpsBlackout returns GPS_BLACKOUT type', () => {
|
|
135
|
-
const s = ScenarioInjector.gpsBlackout(10, 3000);
|
|
136
|
-
expect(s.type).toBe('GPS_BLACKOUT');
|
|
137
|
-
expect(s.triggerIndex).toBe(10);
|
|
138
|
-
expect(s.durationMs).toBe(3000);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it('wrongSideRoad returns WRONG_SIDE_ROAD type', () => {
|
|
142
|
-
const s = ScenarioInjector.wrongSideRoad(20, 18);
|
|
143
|
-
expect(s.type).toBe('WRONG_SIDE_ROAD');
|
|
144
|
-
expect(s.params?.['offsetM']).toBe(18);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('uTurn returns UTURN type', () => {
|
|
148
|
-
const s = ScenarioInjector.uTurn(15);
|
|
149
|
-
expect(s.type).toBe('UTURN');
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it('speedSpike returns SPEED_SPIKE type with spikeKmh', () => {
|
|
153
|
-
const s = ScenarioInjector.speedSpike(5, 120);
|
|
154
|
-
expect(s.type).toBe('SPEED_SPIKE');
|
|
155
|
-
expect(s.params?.['spikeKmh']).toBe(120);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it('accuracyDrop returns ACCURACY_DROP type', () => {
|
|
159
|
-
const s = ScenarioInjector.accuracyDrop(8, 50, 4000);
|
|
160
|
-
expect(s.type).toBe('ACCURACY_DROP');
|
|
161
|
-
expect(s.durationMs).toBe(4000);
|
|
162
|
-
expect(s.params?.['newAccuracyM']).toBe(50);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('all factories produce unique names for different indices', () => {
|
|
166
|
-
const a = ScenarioInjector.gpsBlackout(1, 1000);
|
|
167
|
-
const b = ScenarioInjector.gpsBlackout(2, 1000);
|
|
168
|
-
expect(a.name).not.toBe(b.name);
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
});
|