]> git.r.bdr.sh - rbdr/serpentity/blame - test/integration.js
Update changelog
[rbdr/serpentity] / test / integration.js
CommitLineData
3db7d198
BB
1'use strict';
2
b3b840f8
RBR
3const Code = require('code'); // assertion library
4const Lab = require('lab');
5const Serpentity = require('..');
3db7d198 6
b3b840f8
RBR
7const internals = {
8 system: class TestSystem extends Serpentity.System {
9 added(engine) {
3db7d198 10
b3b840f8
RBR
11 this.testNodes = engine.getNodes(internals.node);
12 this.addedCalled = true;
13 this.addedEngine = engine;
3db7d198
BB
14 }
15
b3b840f8
RBR
16 removed(engine) {
17
3db7d198 18 this.testNodes = null;
b3b840f8
RBR
19 this.removedCalled = true;
20 this.removedEngine = engine;
3db7d198
BB
21 }
22
b3b840f8 23 update(dt) {
3db7d198 24
b3b840f8
RBR
25 this.updateCalled = Date.now();
26 this.updateDt = dt;
3db7d198 27
b3b840f8
RBR
28 for (const node of this.testNodes) {
29 node.test.called = true;
30 node.entity.called = true;
31 }
3db7d198 32
b3b840f8
RBR
33 while (Date.now() === this.updateCalled) { /* pass some time */ }
34 }
35 },
36 component: class TestComponent extends Serpentity.Component {
37 constructor(config) {
3db7d198 38
3db7d198
BB
39 super(config);
40
b3b840f8 41 this.called = false;
3db7d198 42 }
b3b840f8
RBR
43 },
44 node: class TestNode extends Serpentity.Node {},
45 delta: 10
46};
3db7d198 47
b3b840f8
RBR
48// adds a component to the node
49internals.node.types = {
50 test: internals.component
51};
3db7d198 52
b3b840f8 53const lab = exports.lab = Lab.script();
3db7d198 54
b3b840f8 55lab.experiment('loading', () => {
3db7d198 56
b3b840f8 57 lab.test('Serpentity should be exported', (done) => {
3db7d198 58
b3b840f8
RBR
59 Code.expect(typeof Serpentity).to.not.be.undefined();
60 done();
61 });
3db7d198 62
b3b840f8 63 lab.test('Serpentity should include the Entity class', (done) => {
3db7d198 64
b3b840f8
RBR
65 Code.expect(typeof Serpentity.Entity).to.not.be.undefined();
66 done();
67 });
3db7d198 68
b3b840f8 69 lab.test('Serpentity should include the Component class', (done) => {
3db7d198 70
b3b840f8
RBR
71 Code.expect(typeof Serpentity.Component).to.not.be.undefined();
72 done();
73 });
3db7d198 74
b3b840f8 75 lab.test('Serpentity should include the System class', (done) => {
3db7d198 76
b3b840f8
RBR
77 Code.expect(typeof Serpentity.System).to.not.be.undefined();
78 done();
79 });
3db7d198 80
b3b840f8 81 lab.test('Serpentity should include the Node class', (done) => {
3db7d198 82
b3b840f8
RBR
83 Code.expect(typeof Serpentity.Node).to.not.be.undefined();
84 done();
85 });
86
87 lab.test('Serpentity should include the NodeCollection class', (done) => {
88
89 Code.expect(typeof Serpentity.NodeCollection).to.not.be.undefined();
90 done();
91 });
92});
93
94lab.experiment('Engine Tests', () => {
95
96 lab.beforeEach((done) => {
97
98 this.engine = new Serpentity();
99
100 this.regularSystem = new internals.system();
101 this.highPrioritySystem = new internals.system();
102 this.lowPrioritySystem = new internals.system();
103
104 this.firstEntity = new Serpentity.Entity();
105 this.firstEntity.addComponent(new internals.component());
106 this.secondEntity = new Serpentity.Entity();
107 this.secondEntity.addComponent(new internals.component());
108 this.emptyEntity = new Serpentity.Entity();
109
110 // Add entity before the systems
111 this.engine.addEntity(this.firstEntity);
112
113 this.engine.addSystem(this.regularSystem, 100);
114 this.engine.addSystem(this.highPrioritySystem, 0);
115 this.engine.addSystem(this.lowPrioritySystem, 1000);
116
117 // Add entity after the systems
118 this.engine.addEntity(this.secondEntity);
119 this.engine.addEntity(this.emptyEntity);
120
121 done();
122 });
123
124 lab.test('Engine should call added callback on added systems', (done) => {
125
126 // Ensure the added callback is being called
127 Code.expect(this.regularSystem.addedCalled).to.be.true();
128 Code.expect(this.highPrioritySystem.addedCalled).to.be.true();
129 Code.expect(this.lowPrioritySystem.addedCalled).to.be.true();
130
131 done();
132 });
133
134 lab.test('Engine should send the engine instance in added callback', (done) => {
135
136 // Ensure the added callback is sending the engine
137 Code.expect(this.regularSystem.addedEngine instanceof Serpentity).to.be.true();
138 Code.expect(this.highPrioritySystem.addedEngine instanceof Serpentity).to.be.true();
139 Code.expect(this.lowPrioritySystem.addedEngine instanceof Serpentity).to.be.true();
140
141 done();
142 });
143
144 lab.test('Engine should not add duplicate systems', (done) => {
145
146 const originalSystemsLength = this.engine.systems.length;
147 const added = this.engine.addSystem(this.regularSystem, 0);
148 const newSystemsLength = this.engine.systems.length;
149
150 // Ensure we don't add the same system twice
151 Code.expect(added).to.be.false();
152 Code.expect(originalSystemsLength).to.be.equal(newSystemsLength);
153
154 done();
155 });
156
157 lab.test('Engine should call update callback on added systems', (done) => {
158
159 this.engine.update(internals.delta);
160
161 // Ensure update function called
162 Code.expect(!!this.regularSystem.updateCalled).to.be.true();
163 Code.expect(!!this.highPrioritySystem.updateCalled).to.be.true();
164 Code.expect(!!this.lowPrioritySystem.updateCalled).to.be.true();
165
166 done();
167 });
168
169 lab.test('Engine should call update callback in the order of priorities', (done) => {
170
171 this.engine.update(internals.delta);
172
173 // Ensure order of priorities
174 Code.expect(this.regularSystem.updateCalled).to.be.lessThan(this.lowPrioritySystem.updateCalled);
175 Code.expect(this.regularSystem.updateCalled).to.be.greaterThan(this.highPrioritySystem.updateCalled);
176
177 done();
178 });
179
180 lab.test('Engine should send the delta in the update callback', (done) => {
181
182 this.engine.update(internals.delta);
183
184 // Ensure delta is being sent
185 Code.expect(this.regularSystem.updateDt).to.be.equal(internals.delta);
186 Code.expect(this.highPrioritySystem.updateDt).to.be.equal(internals.delta);
187 Code.expect(this.lowPrioritySystem.updateDt).to.be.equal(internals.delta);
188
189 done();
190 });
191
192 lab.test('System remove callback', (done) => {
193
194 const originalSystemLength = this.engine.systems.length;
195 const originalRemoved = this.engine.removeSystem(this.lowPrioritySystem);
196 const intermediateSystemLength = this.engine.systems.length;
197 const finalRemoved = this.engine.removeSystem(this.lowPrioritySystem);
198 const finalSystemLength = this.engine.systems.length;
199 this.engine.update(internals.delta);
200
201 // Check for return value
202 Code.expect(originalRemoved).to.be.true();
203 Code.expect(finalRemoved).to.be.false();
204
205 // Confirm that only removed if found by checking length of systems
206 // array
207 Code.expect(originalSystemLength).to.be.above(intermediateSystemLength);
208 Code.expect(finalSystemLength).to.be.equal(intermediateSystemLength);
209
210 // Ensure callback is sent
211 Code.expect(!!this.regularSystem.removedCalled).to.be.false();
212 Code.expect(!!this.highPrioritySystem.removedCalled).to.be.false();
213 Code.expect(!!this.lowPrioritySystem.removedCalled).to.be.true();
214
215 // Ensure update is no longer sent
216 Code.expect(!!this.regularSystem.updateCalled).to.be.true();
217 Code.expect(!!this.highPrioritySystem.updateCalled).to.be.true();
218 Code.expect(!!this.lowPrioritySystem.updateCalled).to.be.false();
219
220 done();
221 });
222
223 lab.test('Entity node selection', (done) => {
224
225 this.engine.update(internals.delta);
226
227 // Ensure component is called for each entity
228 Code.expect(!!this.firstEntity._components[0].called).to.be.true();
229 Code.expect(!!this.secondEntity._components[0].called).to.be.true();
230
231 // Ensure entity not in node collection not called
232 Code.expect(!!this.firstEntity.called).to.be.true();
233 Code.expect(!!this.secondEntity.called).to.be.true();
234 Code.expect(!!this.emptyEntity.called).to.be.false();
235
236 done();
237 });
238
239 lab.test('Entity node removal', (done) => {
240
241 this.engine.removeEntity(this.secondEntity);
242 this.engine.update(internals.delta);
243
244 Code.expect(!!this.firstEntity._components[0].called).to.be.true();
245 Code.expect(!!this.secondEntity._components[0].called).to.be.false();
246
247 Code.expect(!!this.firstEntity.called).to.be.true();
248 Code.expect(!!this.secondEntity.called).to.be.false();
249 Code.expect(!!this.emptyEntity.called).to.be.false();
250
251 done();
252 });
253
254 lab.test('Entity should not add duplicate components', (done) => {
255 const originalComponentsLength = this.secondEntity._components.length;
256 const result = this.secondEntity.addComponent(new internals.component());
257 const newComponentsLength = this.secondEntity._components.length;
258
259 Code.expect(result).to.be.false();
260 Code.expect(originalComponentsLength).to.be.equal(newComponentsLength);
261
262 done();
263 });
264
265 lab.test('Entity should allow access to components by class', (done) => {
266 const firstComponent = this.firstEntity.getComponent(internals.component);
267 const emptyComponent = this.emptyEntity.getComponent(internals.component);
268
269 Code.expect(firstComponent instanceof internals.component).to.be.true();
270 Code.expect(emptyComponent).to.be.equal(undefined);
271
272 done();
273 });
274
275 lab.test('Engine should not add duplicate entities', (done) => {
276 const originalEntitiesLength = this.engine.entities.length;
277 const added = this.engine.addEntity(this.firstEntity);
278 const finalEntitiesLength = this.engine.entities.length;
279
280 Code.expect(added).to.be.false();
281
282 Code.expect(originalEntitiesLength).to.be.equal(finalEntitiesLength);
283 done();
284 });
285
286 lab.test('Engine should remove entities', (done) => {
287
288 const originalEntityLength = this.engine.entities.length;
289 const originalRemoved = this.engine.removeEntity(this.firstEntity);
290 const intermediateEntityLength = this.engine.entities.length;
291 const finalRemoved = this.engine.removeEntity(this.firstEntity);
292 const finalEntityLength = this.engine.entities.length;
293 this.engine.update(internals.delta);
294
295 // Check for return value
296 Code.expect(originalRemoved).to.be.true();
297 Code.expect(finalRemoved).to.be.false();
298
299 // Confirm that only removed if found by checking length of systems
300 // array
301 Code.expect(originalEntityLength).to.be.above(intermediateEntityLength);
302 Code.expect(finalEntityLength).to.be.equal(intermediateEntityLength);
303
304 // Ensure callback is sent
305 Code.expect(!!this.firstEntity.called).to.be.false();
306 Code.expect(!!this.secondEntity.called).to.be.true();
3db7d198 307
b3b840f8 308 done();
3db7d198 309 });
b3b840f8 310});