bard-legends-framework 1.11.3 → 1.11.4
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/AGENTS.md +61 -4
- package/dist/index.d.mts +18 -6
- package/dist/index.d.ts +18 -6
- package/dist/index.js +3 -3
- package/dist/index.mjs +3 -3
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -324,10 +324,67 @@ Resolve via constructor injection or `Service.get(X)`:
|
|
|
324
324
|
|
|
325
325
|
## Testing
|
|
326
326
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
327
|
+
All testing utilities live on `BardLegendsTestingHelper`.
|
|
328
|
+
|
|
329
|
+
### Concepts
|
|
330
|
+
|
|
331
|
+
- **`BardLegendsTestingHelper.hardReset()`** — call it first thing in `beforeEach`. It calls
|
|
332
|
+
`ActionLib.hardReset()` itself (no separate call needed) and resets all per-test state: DI
|
|
333
|
+
service instances, entity instances, singleton creation latches, and mock gateway bindings.
|
|
334
|
+
**Import-time registrations survive the reset** — `@ServiceDecorator`/`@EntityDecorator`
|
|
335
|
+
metadata and real controller→gateway bindings stay valid, so modules imported once at the top
|
|
336
|
+
of a test file keep working across tests.
|
|
337
|
+
- **Module-level (gateway) tests** — a module's public surface is its gateway. Test through
|
|
338
|
+
`Service.get(TheGateway)`: side-effect-import the module's own `*.controller.ts` (this registers
|
|
339
|
+
the real controller and pulls in its services/entities), and do **not** import any `*.view.ts`
|
|
340
|
+
(unimported views never activate, so entities render nothing).
|
|
341
|
+
- **`BardLegendsTestingHelper.bindMockControllerToGateway(Gateway, mock)`** — fills a foreign
|
|
342
|
+
module's gateway with a mock controller, exactly like `@ControllerDecorator` does for a real
|
|
343
|
+
one. Since the foreign module's controller file is never imported in the test, its gateway
|
|
344
|
+
prototype is empty; the mock's prototype methods fill it. Colliding with an already registered
|
|
345
|
+
method throws. All mock bindings are removed on the next `hardReset()`, so bind them in every
|
|
346
|
+
test's setup, after the reset.
|
|
347
|
+
- Mocks are plain classes matching the foreign controller's shape (`implements
|
|
348
|
+
Partial<TheController>`): mutable public fields for state, regular class methods reading them.
|
|
349
|
+
Methods must live on the prototype — arrow-function fields are not bound.
|
|
350
|
+
|
|
351
|
+
### Sample (module test with a mocked neighbor)
|
|
352
|
+
|
|
353
|
+
```ts
|
|
354
|
+
import './sample.controller'; // registers the module under test
|
|
355
|
+
|
|
356
|
+
describe('SampleController', () => {
|
|
357
|
+
let otherGatewayMock: OtherGatewayMock;
|
|
358
|
+
let sampleGateway: InstanceType<typeof SampleGateway>;
|
|
359
|
+
|
|
360
|
+
beforeEach(() => {
|
|
361
|
+
BardLegendsTestingHelper.hardReset(); // always first
|
|
362
|
+
otherGatewayMock = new OtherGatewayMock();
|
|
363
|
+
BardLegendsTestingHelper.bindMockControllerToGateway(OtherGateway, otherGatewayMock);
|
|
364
|
+
sampleGateway = Service.get(SampleGateway);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
test('does the thing', () => {
|
|
368
|
+
otherGatewayMock.value = 42; // steer the mock through its state fields
|
|
369
|
+
expect(sampleGateway.doTheThing()).toEqual(42);
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Do / Don't
|
|
375
|
+
|
|
376
|
+
```ts
|
|
377
|
+
// DO: hardReset() first in beforeEach, then bind mocks, then Service.get(...) fresh handles.
|
|
378
|
+
// DO: test a module only through its gateway; mock every foreign gateway it reaches.
|
|
379
|
+
// DO: drive frames with UpdateCycle.triggerUpdateTick(delta); use fake timers for wait/animations.
|
|
380
|
+
// DO: assert synchronously — actions-lib delivery is synchronous, most flows need no awaiting.
|
|
381
|
+
|
|
382
|
+
// DON'T: import another module's *.controller.ts or any *.view.ts in a module test.
|
|
383
|
+
// DON'T: use arrow-function fields as mock methods — only prototype methods are bound.
|
|
384
|
+
// DON'T: hold gateway/service references across tests — re-fetch after each hardReset().
|
|
385
|
+
// DON'T: put state in services — controllers/services persist across hardReset by design;
|
|
386
|
+
// per-test state belongs in entities, which do reset.
|
|
387
|
+
```
|
|
331
388
|
|
|
332
389
|
---
|
|
333
390
|
|
package/dist/index.d.mts
CHANGED
|
@@ -79,11 +79,6 @@ declare abstract class SingletonEntity extends Entity {
|
|
|
79
79
|
*/
|
|
80
80
|
declare function Gateway<TController>(): new () => TController;
|
|
81
81
|
|
|
82
|
-
declare class BardLegendsHardReset {
|
|
83
|
-
static readonly onHardReset: actions_lib.Notifier<void>;
|
|
84
|
-
static hardReset(): void;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
82
|
type SceneClassType = new (...services: any[]) => Scene<any, any>;
|
|
88
83
|
type SceneInput<T> = T extends Scene<infer I, any> ? I : never;
|
|
89
84
|
declare function SceneDecorator(): (SceneClass: SceneClassType) => any;
|
|
@@ -113,6 +108,23 @@ declare class Service {
|
|
|
113
108
|
static get<T extends Service>(ServiceClass: new (...args: any[]) => T): T;
|
|
114
109
|
}
|
|
115
110
|
|
|
111
|
+
declare class BardLegendsTestingHelper {
|
|
112
|
+
static readonly onHardReset: actions_lib.Notifier<void>;
|
|
113
|
+
static hardReset(): void;
|
|
114
|
+
/**
|
|
115
|
+
* Binds a partial mock controller to a gateway, exactly like `@ControllerDecorator` does for a
|
|
116
|
+
* real controller — its prototype methods are installed onto the gateway prototype. Intended for
|
|
117
|
+
* tests where the module behind a gateway is not loaded: the real controller never registers
|
|
118
|
+
* (controllers load via the eager `*.controller.ts` glob, which tests skip), so the mock's
|
|
119
|
+
* methods fill the gateway.
|
|
120
|
+
*
|
|
121
|
+
* The mock's methods must be prototype methods (regular class methods, not arrow-function
|
|
122
|
+
* fields). Colliding with an already registered method throws. All mock bindings are removed on
|
|
123
|
+
* `hardReset()`, so bind mocks in each test's setup after the reset.
|
|
124
|
+
*/
|
|
125
|
+
static bindMockControllerToGateway<TController>(GatewayClass: new () => TController, mock: Partial<TController>): void;
|
|
126
|
+
}
|
|
127
|
+
|
|
116
128
|
declare class UpdateCycle {
|
|
117
129
|
static readonly beforeSceneUpdateAction: actions_lib.Notifier<{
|
|
118
130
|
time: number;
|
|
@@ -1330,4 +1342,4 @@ declare abstract class MovablePhysicsEntity extends PhysicsEntity {
|
|
|
1330
1342
|
convertToDTO(): PhysicsBodyDTO;
|
|
1331
1343
|
}
|
|
1332
1344
|
|
|
1333
|
-
export { AdvancedSound, type AdvancedSoundOptions, AnimationFlicker, AnimationInterpolationFunctions, type AnimationOptions, Animations, AnimationsCompletionHandlingType, Animator, type AnimatorAnimation, type AssetDefinition, type AudioAppearTransitionType, BORDER_MATERIAL_NAME,
|
|
1345
|
+
export { AdvancedSound, type AdvancedSoundOptions, AnimationFlicker, AnimationInterpolationFunctions, type AnimationOptions, Animations, AnimationsCompletionHandlingType, Animator, type AnimatorAnimation, type AssetDefinition, type AudioAppearTransitionType, BORDER_MATERIAL_NAME, BardLegendsTestingHelper, type BlendMode, type BorderProperties, Camera, CameraGateway, type CircleShapeData, ClosestAvailableSpaceHelper, type CollisionDetails, type CollisionReport, Container, ContainerEventType, ControllerDecorator, type CreateDashedLineOptions, type CreatePhysicsWorldRequestDTO, Cursor, DEFAULT_SHADER_RESOLUTION, DeltaTime, DisplayObjectArray, type DisplayObjectArrayOptions, type DropShadowOptions, Entity, EntityDecorator, type EntityID, type ExplosionHit, FadeInContent, type FadeInContentOptions, FocusingAnimation, Game, Gateway, type GlowEffectOptions, type GlowOptions, type GlowingShapeDefinition, Graphics, type HitTestOptions, ImmovablePhysicsEntity, type InteractingBodyGroups, type KeyboardKeyInfo, KeyboardService, type MapSizeDTO, type MaterialContactDefinition, type MaterialDefinition, MenuEntity, type MenuOptions, MenuUI, MenuView, MouseService, MouseTargetFocusService, MovableEntity, MovablePhysicsEntity, Music, MusicPlayer, type MusicPlayerOptions, type PartialTextOptions, PathFinder, type PathFinderResult, type PhysicsBodyDTO, PhysicsEntity, type PhysicsEntityDefinition, type PhysicsExplosionOptions, PhysicsGateway, PhysicsShapeType, type PhysicsWorldID, Placeholder, type PolygonDefinition, type PolygonShapeData, ROTATIONAL_SPEED_LIMIT, type RayCast, type RayCastHit, ReAnimateHandlingType, type RectangleShapeData, RichText, type RichTextOptions, type RichTextRectangleCut, type RichTextStyles, SOUND_TRANSITION_DURATION, SPEED_LIMIT, Scene, SceneDecorator, ScrollAreaUI, ScrollDirection, type ScrollInContentOptions, ScrollMaskUI, Service, ServiceDecorator, type SetParentOptions, type ShapeDefinition, SingletonEntity, SlideInContent, SlideInContentByIndex, SlideStateAnimation, SlideStateAnimationState, Sound, type SoundDefinition, type SoundID, type SoundIDRegistry, type SoundOptions, Sprite, type SpriteDefinition, type SpriteID, type SpriteIDRegistry, StateAnimation, type StateAnimationOptions, type StateAnimationState, Text, type TextAlignment, type TextOptions, ThroughEmptyStateAnimation, UpdatableContainer, UpdateCycle, VectorFieldPathFinder, VectorSet, View, ViewDecorator, type ViewDecoratorMeta };
|
package/dist/index.d.ts
CHANGED
|
@@ -79,11 +79,6 @@ declare abstract class SingletonEntity extends Entity {
|
|
|
79
79
|
*/
|
|
80
80
|
declare function Gateway<TController>(): new () => TController;
|
|
81
81
|
|
|
82
|
-
declare class BardLegendsHardReset {
|
|
83
|
-
static readonly onHardReset: actions_lib.Notifier<void>;
|
|
84
|
-
static hardReset(): void;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
82
|
type SceneClassType = new (...services: any[]) => Scene<any, any>;
|
|
88
83
|
type SceneInput<T> = T extends Scene<infer I, any> ? I : never;
|
|
89
84
|
declare function SceneDecorator(): (SceneClass: SceneClassType) => any;
|
|
@@ -113,6 +108,23 @@ declare class Service {
|
|
|
113
108
|
static get<T extends Service>(ServiceClass: new (...args: any[]) => T): T;
|
|
114
109
|
}
|
|
115
110
|
|
|
111
|
+
declare class BardLegendsTestingHelper {
|
|
112
|
+
static readonly onHardReset: actions_lib.Notifier<void>;
|
|
113
|
+
static hardReset(): void;
|
|
114
|
+
/**
|
|
115
|
+
* Binds a partial mock controller to a gateway, exactly like `@ControllerDecorator` does for a
|
|
116
|
+
* real controller — its prototype methods are installed onto the gateway prototype. Intended for
|
|
117
|
+
* tests where the module behind a gateway is not loaded: the real controller never registers
|
|
118
|
+
* (controllers load via the eager `*.controller.ts` glob, which tests skip), so the mock's
|
|
119
|
+
* methods fill the gateway.
|
|
120
|
+
*
|
|
121
|
+
* The mock's methods must be prototype methods (regular class methods, not arrow-function
|
|
122
|
+
* fields). Colliding with an already registered method throws. All mock bindings are removed on
|
|
123
|
+
* `hardReset()`, so bind mocks in each test's setup after the reset.
|
|
124
|
+
*/
|
|
125
|
+
static bindMockControllerToGateway<TController>(GatewayClass: new () => TController, mock: Partial<TController>): void;
|
|
126
|
+
}
|
|
127
|
+
|
|
116
128
|
declare class UpdateCycle {
|
|
117
129
|
static readonly beforeSceneUpdateAction: actions_lib.Notifier<{
|
|
118
130
|
time: number;
|
|
@@ -1330,4 +1342,4 @@ declare abstract class MovablePhysicsEntity extends PhysicsEntity {
|
|
|
1330
1342
|
convertToDTO(): PhysicsBodyDTO;
|
|
1331
1343
|
}
|
|
1332
1344
|
|
|
1333
|
-
export { AdvancedSound, type AdvancedSoundOptions, AnimationFlicker, AnimationInterpolationFunctions, type AnimationOptions, Animations, AnimationsCompletionHandlingType, Animator, type AnimatorAnimation, type AssetDefinition, type AudioAppearTransitionType, BORDER_MATERIAL_NAME,
|
|
1345
|
+
export { AdvancedSound, type AdvancedSoundOptions, AnimationFlicker, AnimationInterpolationFunctions, type AnimationOptions, Animations, AnimationsCompletionHandlingType, Animator, type AnimatorAnimation, type AssetDefinition, type AudioAppearTransitionType, BORDER_MATERIAL_NAME, BardLegendsTestingHelper, type BlendMode, type BorderProperties, Camera, CameraGateway, type CircleShapeData, ClosestAvailableSpaceHelper, type CollisionDetails, type CollisionReport, Container, ContainerEventType, ControllerDecorator, type CreateDashedLineOptions, type CreatePhysicsWorldRequestDTO, Cursor, DEFAULT_SHADER_RESOLUTION, DeltaTime, DisplayObjectArray, type DisplayObjectArrayOptions, type DropShadowOptions, Entity, EntityDecorator, type EntityID, type ExplosionHit, FadeInContent, type FadeInContentOptions, FocusingAnimation, Game, Gateway, type GlowEffectOptions, type GlowOptions, type GlowingShapeDefinition, Graphics, type HitTestOptions, ImmovablePhysicsEntity, type InteractingBodyGroups, type KeyboardKeyInfo, KeyboardService, type MapSizeDTO, type MaterialContactDefinition, type MaterialDefinition, MenuEntity, type MenuOptions, MenuUI, MenuView, MouseService, MouseTargetFocusService, MovableEntity, MovablePhysicsEntity, Music, MusicPlayer, type MusicPlayerOptions, type PartialTextOptions, PathFinder, type PathFinderResult, type PhysicsBodyDTO, PhysicsEntity, type PhysicsEntityDefinition, type PhysicsExplosionOptions, PhysicsGateway, PhysicsShapeType, type PhysicsWorldID, Placeholder, type PolygonDefinition, type PolygonShapeData, ROTATIONAL_SPEED_LIMIT, type RayCast, type RayCastHit, ReAnimateHandlingType, type RectangleShapeData, RichText, type RichTextOptions, type RichTextRectangleCut, type RichTextStyles, SOUND_TRANSITION_DURATION, SPEED_LIMIT, Scene, SceneDecorator, ScrollAreaUI, ScrollDirection, type ScrollInContentOptions, ScrollMaskUI, Service, ServiceDecorator, type SetParentOptions, type ShapeDefinition, SingletonEntity, SlideInContent, SlideInContentByIndex, SlideStateAnimation, SlideStateAnimationState, Sound, type SoundDefinition, type SoundID, type SoundIDRegistry, type SoundOptions, Sprite, type SpriteDefinition, type SpriteID, type SpriteIDRegistry, StateAnimation, type StateAnimationOptions, type StateAnimationState, Text, type TextAlignment, type TextOptions, ThroughEmptyStateAnimation, UpdatableContainer, UpdateCycle, VectorFieldPathFinder, VectorSet, View, ViewDecorator, type ViewDecoratorMeta };
|