@dcl/sdk 7.1.4-4578951400.commit-3810356 → 7.1.4-4598967522.commit-538c49d

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/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@dcl/sdk",
3
3
  "description": "",
4
- "version": "7.1.4-4578951400.commit-3810356",
4
+ "version": "7.1.4-4598967522.commit-538c49d",
5
5
  "author": "Decentraland",
6
6
  "dependencies": {
7
- "@dcl/ecs": "7.1.4-4578951400.commit-3810356",
7
+ "@dcl/ecs": "7.1.4-4598967522.commit-538c49d",
8
8
  "@dcl/ecs-math": "2.0.1-20221129185242.commit-40495c1",
9
9
  "@dcl/explorer": "1.0.92953-20230320185045.commit-aed694a",
10
- "@dcl/js-runtime": "7.1.4-4578951400.commit-3810356",
11
- "@dcl/react-ecs": "7.1.4-4578951400.commit-3810356",
12
- "@dcl/sdk-commands": "7.1.4-4578951400.commit-3810356"
10
+ "@dcl/js-runtime": "7.1.4-4598967522.commit-538c49d",
11
+ "@dcl/react-ecs": "7.1.4-4598967522.commit-538c49d",
12
+ "@dcl/sdk-commands": "7.1.4-4598967522.commit-538c49d"
13
13
  },
14
14
  "keywords": [],
15
15
  "license": "Apache-2.0",
@@ -30,5 +30,5 @@
30
30
  },
31
31
  "types": "./index.d.ts",
32
32
  "typings": "./index.d.ts",
33
- "commit": "3810356217029030ea170aba0c9e95f43a422252"
33
+ "commit": "538c49d420ba1bf75ad9e6d821aec3c4afe26c69"
34
34
  }
@@ -0,0 +1,134 @@
1
+ // VERBATIM COPY OF https://github.com/LemonPi/deep-close-to
2
+
3
+ import type { Entity, LastWriteWinElementSetComponentDefinition } from '@dcl/ecs'
4
+
5
+ const pSlice = Array.prototype.slice
6
+
7
+ const floatEpsilon = 0.0000001
8
+
9
+ type Options = { strict: boolean; comp: typeof closeTo }
10
+
11
+ export function assertEquals(a: any, b: any, message: string = 'Values are not equal') {
12
+ if (!deepCloseTo(a, b)) throw new Error(`${message} - ${JSON.stringify(a)} != ${JSON.stringify(b)}`)
13
+ }
14
+
15
+ export function assert(a: any, message: string = 'assertion failed') {
16
+ if (!a) throw new Error(message)
17
+ }
18
+
19
+ export function assertComponentValue<T>(
20
+ entity: Entity,
21
+ component: LastWriteWinElementSetComponentDefinition<T>,
22
+ value: T
23
+ ) {
24
+ assert(component.has(entity), `The entity doesn't have a ${component.componentName} component`)
25
+ assertEquals(component.get(entity)!, value, `Invalid ${component.componentName} values`)
26
+ }
27
+
28
+ export function deepCloseTo(actual: any, expected: any, options: Partial<Options> = {}): boolean {
29
+ const opts = Object.assign({}, { comp: closeTo }, options)
30
+ // 7.1. All identical values are equivalent, as determined by ===.
31
+ if (actual === expected) {
32
+ return true
33
+ } else if (actual instanceof Date && expected instanceof Date) {
34
+ return opts.comp!(actual, expected)
35
+
36
+ // 7.3. Other pairs that do not both pass typeof value == 'object',
37
+ // equivalence is determined by ==.
38
+ } else if (!actual || !expected || (typeof actual !== 'object' && typeof expected !== 'object')) {
39
+ if (opts.strict) {
40
+ if (!actual && !expected) {
41
+ return actual === expected
42
+ }
43
+
44
+ if (typeof actual !== typeof expected) {
45
+ return false
46
+ }
47
+ }
48
+ if (!actual && !expected) {
49
+ return actual === expected
50
+ }
51
+ return opts.comp!(actual, expected)
52
+
53
+ // 7.4. For all other Object pairs, including Array objects, equivalence is
54
+ // determined by having the same number of owned properties (as verified
55
+ // with Object.prototype.hasOwnProperty.call), the same set of keys
56
+ // (although not necessarily the same order), equivalent values for every
57
+ // corresponding key, and an identical 'prototype' property. Note: this
58
+ // accounts for both named and indexed properties on Arrays.
59
+ } else {
60
+ return objEquiv(actual, expected, opts as any)
61
+ }
62
+ }
63
+
64
+ function isUndefinedOrNull(value: any) {
65
+ return value === null || value === undefined
66
+ }
67
+
68
+ function isBuffer(x: any) {
69
+ if (!x || typeof x !== 'object' || typeof x.length !== 'number') return false
70
+ if (typeof x.copy !== 'function' || typeof x.slice !== 'function') {
71
+ return false
72
+ }
73
+ if (x.length > 0 && typeof x[0] !== 'number') return false
74
+ return true
75
+ }
76
+
77
+ function objEquiv(a: any, b: any, opts: Options) {
78
+ let i, key
79
+ if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) return false
80
+ // an identical 'prototype' property.
81
+ if (a.prototype !== b.prototype) return false
82
+ //~~~I've managed to break Object.keys through screwy arguments passing.
83
+ // Converting to array solves the problem.
84
+ if (isArguments(a)) {
85
+ if (!isArguments(b)) {
86
+ return false
87
+ }
88
+ return deepCloseTo(pSlice.call(a), pSlice.call(b), opts)
89
+ }
90
+ if (isBuffer(a)) {
91
+ if (!isBuffer(b)) {
92
+ return false
93
+ }
94
+ if (a.length !== b.length) return false
95
+ for (i = 0; i < a.length; i++) {
96
+ if (a[i] !== b[i]) return false
97
+ }
98
+ return true
99
+ }
100
+
101
+ try {
102
+ const ka = Object.keys(a)
103
+ const kb = Object.keys(b)
104
+
105
+ // having the same number of owned properties (keys incorporates
106
+ // hasOwnProperty)
107
+ if (ka.length !== kb.length) return false
108
+ //the same set of keys (although not necessarily the same order),
109
+ ka.sort()
110
+ kb.sort()
111
+ //~~~cheap key test
112
+ for (i = ka.length - 1; i >= 0; i--) {
113
+ if (ka[i] !== kb[i]) return false
114
+ }
115
+ //equivalent values for every corresponding key, and
116
+ //~~~possibly expensive deep test
117
+ for (i = ka.length - 1; i >= 0; i--) {
118
+ key = ka[i]
119
+ if (!deepCloseTo(a[key], b[key], opts)) return false
120
+ }
121
+ } catch (e) {
122
+ //happens when one is a string literal and the other isn't
123
+ return false
124
+ }
125
+
126
+ return typeof a === typeof b
127
+ }
128
+
129
+ function isArguments(object: any) {
130
+ return Object.prototype.toString.call(object) === '[object Arguments]'
131
+ }
132
+ function closeTo(actual: any, expected: any, delta: number = floatEpsilon) {
133
+ return Math.abs(actual - expected) < delta
134
+ }
@@ -0,0 +1,42 @@
1
+ import { engine } from '@dcl/ecs'
2
+ import { createTestRuntime } from './runtime'
3
+ import { TestDefinitionFunction, TestingModule } from './types'
4
+
5
+ declare let require: any
6
+
7
+ /**
8
+ * In development builds, this function serves as test runner for automated test scenarios
9
+ * if the runtime accepts the `~system/Testing` module
10
+ * @public
11
+ */
12
+ /* @__PURE__ */
13
+ export const test: TestDefinitionFunction = DEBUG ? /* @__PURE__ */ createTestFunction() : /* @__PURE__ */ () => {}
14
+
15
+ function createTestFunction() {
16
+ let testingModule: TestingModule
17
+ try {
18
+ testingModule = /* @__PURE__ */ require('~system/Testing')
19
+ } catch (err) {
20
+ console.error(err)
21
+
22
+ console.error(`🔴🚨‼️ WARNING: The test runner is not available. The test runner will be mocked. ‼️🚨🔴`)
23
+
24
+ testingModule = {
25
+ async logTestResult(data) {
26
+ console.log(`🧪 mocked '~system/Testing'.logResult`, data)
27
+ return {}
28
+ },
29
+ async plan(data) {
30
+ console.log(`🧪 mocked '~system/Testing'.plan`, data)
31
+ return {}
32
+ },
33
+ async setCameraTransform(transform) {
34
+ console.log(`🧪 mocked '~system/Testing'.setCameraTransform`, transform)
35
+ return {}
36
+ }
37
+ }
38
+ }
39
+
40
+ const runtime = createTestRuntime(testingModule, engine)
41
+ return runtime.test
42
+ }
@@ -0,0 +1,223 @@
1
+ /**
2
+ * This module provides a createTestRuntime function that returns an object with a test function that can be used to define tests.
3
+ */
4
+
5
+ import { IEngine, Transform } from '@dcl/ecs'
6
+ import { assertEquals } from './assert'
7
+ import type { TestingModule, TestFunction, TestHelpers } from './types'
8
+
9
+ // This function creates a test runtime that can be used to define and run tests.
10
+ // It takes a `TestingModule` instance (loaded from require('~system/Testing')) and an `IEngine` instance (from Decentraland's SDK).
11
+ // It returns an object with a `test` function that can be used to define tests.
12
+ /* @__PURE__ */
13
+ export function createTestRuntime(testingModule: TestingModule, engine: IEngine) {
14
+ type TestPlanEntry = { name: string; fn: TestFunction }
15
+ type RunnerEnvironment = {
16
+ resolve: () => void
17
+ reject: (error: any) => void
18
+ helpers: TestHelpers
19
+ generator: Generator
20
+ }
21
+
22
+ // this flag ensures no tests are added asynchronously
23
+ let runtimeFrozen = false
24
+
25
+ let currentFrameCounter = 0
26
+ let currentFrameTime = 0
27
+
28
+ // array to hold the scheduled tests
29
+ const scheduledTests: TestPlanEntry[] = []
30
+
31
+ // an array of promises that are resolved on the next frame (after the current frame is finished)
32
+ const nextTickFuture: Array<(dt: number) => void> = []
33
+
34
+ // this function returns a promise that resolves on the next frame
35
+ async function nextTick() {
36
+ return new Promise<number>((resolve) => {
37
+ nextTickFuture.push(resolve)
38
+ })
39
+ }
40
+
41
+ // add a system to the engine that resolves all promises in the `nextTickFuture` array
42
+ engine.addSystem(function TestingFrameworkCoroutineRunner(dt) {
43
+ currentFrameCounter++
44
+ currentFrameTime += dt
45
+ // resolve all nextTick futures.
46
+ nextTickFuture.splice(0, nextTickFuture.length).forEach((_) => _(dt))
47
+ })
48
+
49
+ // this function schedules a value to be processed on the next frame, the test runner will
50
+ // continue to run until it reaches a yield point
51
+ function scheduleValue(value: any, env: RunnerEnvironment) {
52
+ if (value && typeof value === 'object' && typeof value.then === 'function') {
53
+ console.log('⏱️ yield promise')
54
+ // if the value is a promise, schedule it to be awaited after the current frame is finished
55
+ nextTickFuture.push(async () => {
56
+ try {
57
+ scheduleValue(await value, env)
58
+ } catch (err) {
59
+ env.reject(err)
60
+ }
61
+ })
62
+ } else if (typeof value === 'function') {
63
+ console.log('⏱️ yield function')
64
+ // if the value is a function, schedule it to be called on the next frame
65
+ nextTickFuture.push(() => {
66
+ scheduleValue(value(), env)
67
+ })
68
+ return
69
+ } else if (typeof value === 'undefined' || value === null) {
70
+ console.log('⏱️ yield')
71
+ // if the value is undefined or null, continue processing the generator the next frame
72
+ nextTickFuture.push(() => {
73
+ consumeGenerator(env)
74
+ })
75
+ } else throw new Error(`Unexpected value from test generator: ${value}`)
76
+ }
77
+
78
+ // this function processes a generator function by scheduling its values to be processed on the next frame
79
+ function consumeGenerator(env: RunnerEnvironment) {
80
+ try {
81
+ const ret = env.generator.next()
82
+ if (!ret.done) {
83
+ scheduleValue(ret.value, env)
84
+ } else {
85
+ env.resolve()
86
+ }
87
+ } catch (err) {
88
+ env.reject(err)
89
+ }
90
+ }
91
+
92
+ // this function schedules a test run on the next frame
93
+ function scheduleNextRun() {
94
+ if (scheduledTests.length) {
95
+ nextTickFuture.push(runTests)
96
+ }
97
+ }
98
+
99
+ // this function runs the scheduled tests
100
+ function runTests() {
101
+ if (scheduledTests.length) {
102
+ const entry = scheduledTests.shift()!
103
+ const initialFrame = currentFrameCounter
104
+ const startTime = currentFrameTime
105
+
106
+ let resolved = false
107
+
108
+ // this function should be called only once. it makes the current test pass
109
+ const resolve = () => {
110
+ if (resolved) throw new Error('resolved twice')
111
+ resolved = true
112
+
113
+ console.log(`🟢 Test passed ${entry.name}`)
114
+
115
+ testingModule
116
+ .logTestResult({
117
+ name: entry.name,
118
+ ok: true,
119
+ totalFrames: currentFrameCounter - initialFrame,
120
+ totalTime: currentFrameTime - startTime
121
+ })
122
+ .finally(scheduleNextRun)
123
+ }
124
+
125
+ const reject = (err: any) => {
126
+ if (resolved) throw new Error('resolved twice')
127
+ resolved = true
128
+
129
+ console.log(`🔴 Test failed ${entry.name}`)
130
+ console.error(err)
131
+
132
+ testingModule
133
+ .logTestResult({
134
+ name: entry.name,
135
+ ok: false,
136
+ error: err.toString(),
137
+ stack: err && typeof err === 'object' && err.stack,
138
+ totalFrames: currentFrameCounter - initialFrame,
139
+ totalTime: currentFrameTime - startTime
140
+ })
141
+ .finally(scheduleNextRun)
142
+ }
143
+
144
+ try {
145
+ console.log(`🧪 Running test ${entry.name}`)
146
+
147
+ const testHelpers: TestHelpers = {
148
+ async setCameraTransform(transform) {
149
+ await testingModule.setCameraTransform(transform)
150
+ await nextTick()
151
+
152
+ const TransformComponent = engine.getComponent(Transform.componentId) as typeof Transform
153
+ const actualTransform = TransformComponent.get(engine.CameraEntity)
154
+
155
+ assertEquals(actualTransform.position, transform.position, "positions don't match")
156
+ assertEquals(actualTransform.rotation, transform.rotation, "rotations don't match")
157
+ }
158
+ }
159
+
160
+ const returnValue = entry.fn(testHelpers)
161
+
162
+ if (returnValue && typeof returnValue === 'object') {
163
+ if (isGenerator(returnValue)) {
164
+ const env: RunnerEnvironment = {
165
+ generator: returnValue,
166
+ helpers: testHelpers,
167
+ resolve,
168
+ reject
169
+ }
170
+ consumeGenerator(env)
171
+ } else if (isPromise(returnValue)) {
172
+ returnValue.then(resolve).catch(reject)
173
+ } else {
174
+ throw new Error(`Unknown test result type: ${returnValue}`)
175
+ }
176
+ } else {
177
+ resolve()
178
+ }
179
+ } catch (err: any) {
180
+ reject(err)
181
+ }
182
+ }
183
+ }
184
+
185
+ // schedule the test runner start for the next frame
186
+ nextTickFuture.push(() => {
187
+ // once we run the next tick, the test runtime becomes frozen. that means no new
188
+ // test definitions are accepted
189
+ runtimeFrozen = true
190
+
191
+ if (!scheduledTests.length) return
192
+
193
+ // inform the test runner about the plans for this test run
194
+ testingModule.plan({ tests: scheduledTests }).then(scheduleNextRun).catch(globalFail)
195
+ })
196
+
197
+ // this is the function that is used to plan a test functionn
198
+ /* @__PURE__ */
199
+ function test(name: string, fn: TestFunction) {
200
+ if (runtimeFrozen) throw new Error("New tests can't be added at this stage.")
201
+
202
+ if (scheduledTests.some(($) => $.name === name)) throw new Error(`Test with name ${name} already exists`)
203
+
204
+ scheduledTests.push({ fn, name })
205
+ }
206
+
207
+ return {
208
+ test
209
+ }
210
+ }
211
+
212
+ function isGenerator(t: any): t is Generator {
213
+ return t && typeof t === 'object' && typeof t[Symbol.iterator] === 'function'
214
+ }
215
+
216
+ function isPromise(t: any): t is Promise<unknown> {
217
+ return t && typeof t === 'object' && typeof t.then === 'function'
218
+ }
219
+
220
+ function globalFail(error: any) {
221
+ // for now, the failure is only writing to the console.error.
222
+ console.error(error)
223
+ }
@@ -0,0 +1,21 @@
1
+ import type { TransformType } from '@dcl/ecs'
2
+ import type { logTestResult, plan, setCameraTransform } from '~system/Testing'
3
+
4
+ export type TestHelpers = {
5
+ /**
6
+ * Instructs the renderer to set the camera transform to the provided argument.
7
+ * This function resolves the next frame and fails if the CameraTransform is not
8
+ * equal to the provided argument.
9
+ */
10
+ setCameraTransform(transform: Pick<TransformType, 'position' | 'rotation'>): Promise<void>
11
+ }
12
+
13
+ export type TestFunction = (helpers: TestHelpers) => Generator | Promise<any>
14
+
15
+ export type TestDefinitionFunction = (name: string, fn: TestFunction) => void
16
+
17
+ export type TestingModule = {
18
+ logTestResult: typeof logTestResult
19
+ plan: typeof plan
20
+ setCameraTransform: typeof setCameraTransform
21
+ }
@@ -0,0 +1,11 @@
1
+ import type { Entity, LastWriteWinElementSetComponentDefinition } from '@dcl/ecs';
2
+ type Options = {
3
+ strict: boolean;
4
+ comp: typeof closeTo;
5
+ };
6
+ export declare function assertEquals(a: any, b: any, message?: string): void;
7
+ export declare function assert(a: any, message?: string): void;
8
+ export declare function assertComponentValue<T>(entity: Entity, component: LastWriteWinElementSetComponentDefinition<T>, value: T): void;
9
+ export declare function deepCloseTo(actual: any, expected: any, options?: Partial<Options>): boolean;
10
+ declare function closeTo(actual: any, expected: any, delta?: number): boolean;
11
+ export {};
@@ -0,0 +1,106 @@
1
+ const pSlice = Array.prototype.slice;
2
+ const floatEpsilon = 0.0000001;
3
+ export function assertEquals(a, b, message = 'Values are not equal') {
4
+ if (!deepCloseTo(a, b))
5
+ throw new Error(`${message} - ${JSON.stringify(a)} != ${JSON.stringify(b)}`);
6
+ }
7
+ export function assert(a, message = 'assertion failed') {
8
+ if (!a)
9
+ throw new Error(message);
10
+ }
11
+ export function assertComponentValue(entity, component, value) {
12
+ assert(component.has(entity), `The entity doesn't have a ${component.componentName} component`);
13
+ assertEquals(component.get(entity), value, `Invalid ${component.componentName} values`);
14
+ }
15
+ export function deepCloseTo(actual, expected, options = {}) {
16
+ const opts = Object.assign({}, { comp: closeTo }, options);
17
+ if (actual === expected) {
18
+ return true;
19
+ }
20
+ else if (actual instanceof Date && expected instanceof Date) {
21
+ return opts.comp(actual, expected);
22
+ }
23
+ else if (!actual || !expected || (typeof actual !== 'object' && typeof expected !== 'object')) {
24
+ if (opts.strict) {
25
+ if (!actual && !expected) {
26
+ return actual === expected;
27
+ }
28
+ if (typeof actual !== typeof expected) {
29
+ return false;
30
+ }
31
+ }
32
+ if (!actual && !expected) {
33
+ return actual === expected;
34
+ }
35
+ return opts.comp(actual, expected);
36
+ }
37
+ else {
38
+ return objEquiv(actual, expected, opts);
39
+ }
40
+ }
41
+ function isUndefinedOrNull(value) {
42
+ return value === null || value === undefined;
43
+ }
44
+ function isBuffer(x) {
45
+ if (!x || typeof x !== 'object' || typeof x.length !== 'number')
46
+ return false;
47
+ if (typeof x.copy !== 'function' || typeof x.slice !== 'function') {
48
+ return false;
49
+ }
50
+ if (x.length > 0 && typeof x[0] !== 'number')
51
+ return false;
52
+ return true;
53
+ }
54
+ function objEquiv(a, b, opts) {
55
+ let i, key;
56
+ if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
57
+ return false;
58
+ if (a.prototype !== b.prototype)
59
+ return false;
60
+ if (isArguments(a)) {
61
+ if (!isArguments(b)) {
62
+ return false;
63
+ }
64
+ return deepCloseTo(pSlice.call(a), pSlice.call(b), opts);
65
+ }
66
+ if (isBuffer(a)) {
67
+ if (!isBuffer(b)) {
68
+ return false;
69
+ }
70
+ if (a.length !== b.length)
71
+ return false;
72
+ for (i = 0; i < a.length; i++) {
73
+ if (a[i] !== b[i])
74
+ return false;
75
+ }
76
+ return true;
77
+ }
78
+ try {
79
+ const ka = Object.keys(a);
80
+ const kb = Object.keys(b);
81
+ if (ka.length !== kb.length)
82
+ return false;
83
+ ka.sort();
84
+ kb.sort();
85
+ for (i = ka.length - 1; i >= 0; i--) {
86
+ if (ka[i] !== kb[i])
87
+ return false;
88
+ }
89
+ for (i = ka.length - 1; i >= 0; i--) {
90
+ key = ka[i];
91
+ if (!deepCloseTo(a[key], b[key], opts))
92
+ return false;
93
+ }
94
+ }
95
+ catch (e) {
96
+ return false;
97
+ }
98
+ return typeof a === typeof b;
99
+ }
100
+ function isArguments(object) {
101
+ return Object.prototype.toString.call(object) === '[object Arguments]';
102
+ }
103
+ function closeTo(actual, expected, delta = floatEpsilon) {
104
+ return Math.abs(actual - expected) < delta;
105
+ }
106
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzZXJ0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3Rlc3RpbmcvYXNzZXJ0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUlBLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFBO0FBRXBDLE1BQU0sWUFBWSxHQUFHLFNBQVMsQ0FBQTtBQUk5QixNQUFNLFVBQVUsWUFBWSxDQUFDLENBQU0sRUFBRSxDQUFNLEVBQUUsVUFBa0Isc0JBQXNCO0lBQ25GLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxPQUFPLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtBQUN0RyxDQUFDO0FBRUQsTUFBTSxVQUFVLE1BQU0sQ0FBQyxDQUFNLEVBQUUsVUFBa0Isa0JBQWtCO0lBQ2pFLElBQUksQ0FBQyxDQUFDO1FBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQTtBQUNsQyxDQUFDO0FBRUQsTUFBTSxVQUFVLG9CQUFvQixDQUNsQyxNQUFjLEVBQ2QsU0FBdUQsRUFDdkQsS0FBUTtJQUVSLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLDZCQUE2QixTQUFTLENBQUMsYUFBYSxZQUFZLENBQUMsQ0FBQTtJQUMvRixZQUFZLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUUsRUFBRSxLQUFLLEVBQUUsV0FBVyxTQUFTLENBQUMsYUFBYSxTQUFTLENBQUMsQ0FBQTtBQUMxRixDQUFDO0FBRUQsTUFBTSxVQUFVLFdBQVcsQ0FBQyxNQUFXLEVBQUUsUUFBYSxFQUFFLFVBQTRCLEVBQUU7SUFDcEYsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVB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QUFFRCxTQUFTLFdBQVcsQ0FBQyxNQUFXO0lBQzlCLE9BQU8sTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLG9CQUFvQixDQUFBO0FBQ3hFLENBQUM7QUFDRCxTQUFTLE9BQU8sQ0FBQyxNQUFXLEVBQUUsUUFBYSxFQUFFLFFBQWdCLFlBQVk7SUFDdkUsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxRQUFRLENBQUMsR0FBRyxLQUFLLENBQUE7QUFDNUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIFZFUkJBVElNIENPUFkgT0YgaHR0cHM6Ly9naXRodWIuY29tL0xlbW9uUGkvZGVlcC1jbG9zZS10b1xuXG5pbXBvcnQgdHlwZSB7IEVudGl0eSwgTGFzdFdyaXRlV2luRWxlbWVudFNldENvbXBvbmVudERlZmluaXRpb24gfSBmcm9tICdAZGNsL2VjcydcblxuY29uc3QgcFNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlXG5cbmNvbnN0IGZsb2F0RXBzaWxvbiA9IDAuMDAwMDAwMVxuXG50eXBlIE9wdGlvbnMgPSB7IHN0cmljdDogYm9vbGVhbjsgY29tcDogdHlwZW9mIGNsb3NlVG8gfVxuXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0RXF1YWxzKGE6IGFueSwgYjogYW55LCBtZXNzYWdlOiBzdHJpbmcgPSAnVmFsdWVzIGFyZSBub3QgZXF1YWwnKSB7XG4gIGlmICghZGVlcENsb3NlVG8oYSwgYikpIHRocm93IG5ldyBFcnJvcihgJHttZXNzYWdlfSAtICR7SlNPTi5zdHJpbmdpZnkoYSl9ICE9ICR7SlNPTi5zdHJpbmdpZnkoYil9YClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydChhOiBhbnksIG1lc3NhZ2U6IHN0cmluZyA9ICdhc3NlcnRpb24gZmFpbGVkJykge1xuICBpZiAoIWEpIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0Q29tcG9uZW50VmFsdWU8VD4oXG4gIGVudGl0eTogRW50aXR5LFxuICBjb21wb25lbnQ6IExhc3RXcml0ZVdpbkVsZW1lbnRTZXRDb21wb25lbnREZWZpbml0aW9uPFQ+LFxuICB2YWx1ZTogVFxuKSB7XG4gIGFzc2VydChjb21wb25lbnQuaGFzKGVudGl0eSksIGBUaGUgZW50aXR5IGRvZXNuJ3QgaGF2ZSBhICR7Y29tcG9uZW50LmNvbXBvbmVudE5hbWV9IGNvbXBvbmVudGApXG4gIGFzc2VydEVxdWFscyhjb21wb25lbnQuZ2V0KGVudGl0eSkhLCB2YWx1ZSwgYEludmFsaWQgJHtjb21wb25lbnQuY29tcG9uZW50TmFtZX0gdmFsdWVzYClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlZXBDbG9zZVRvKGFjdHVhbDogYW55LCBleHBlY3RlZDogYW55LCBvcHRpb25zOiBQYXJ0aWFsPE9wdGlvbnM+ID0ge30pOiBib29sZWFuIHtcbiAgY29uc3Qgb3B0cyA9IE9iamVjdC5hc3NpZ24oe30sIHsgY29tcDogY2xvc2VUbyB9LCBvcHRpb25zKVxuICAvLyA3LjEuIEFsbCBpZGVudGljYWwgdmFsdWVzIGFyZSBlcXVpdmFsZW50LCBhcyBkZXRlcm1pbmVkIGJ5ID09PS5cbiAgaWYgKGFjdHVhbCA9PT0gZXhwZWN0ZWQpIHtcbiAgICByZXR1cm4gdHJ1ZVxuICB9IGVsc2UgaWYgKGFjdHVhbCBpbnN0YW5jZW9mIERhdGUgJiYgZXhwZWN0ZWQgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgcmV0dXJuIG9wdHMuY29tcCEoYWN0dWFsLCBleHBlY3RlZClcblxuICAgIC8vIDcuMy4gT3RoZXIgcGFpcnMgdGhhdCBkbyBub3QgYm90aCBwYXNzIHR5cGVvZiB2YWx1ZSA9PSAnb2JqZWN0JyxcbiAgICAvLyBlcXVpdmFsZW5jZSBpcyBkZXRlcm1pbmVkIGJ5ID09LlxuICB9IGVsc2UgaWYgKCFhY3R1YWwgfHwgIWV4cGVjdGVkIHx8ICh0eXBlb2YgYWN0dWFsICE9PSAnb2JqZWN0JyAmJiB0eXBlb2YgZXhwZWN0ZWQgIT09ICdvYmplY3QnKSkge1xuICAgIGlmIChvcHRzLnN0cmljdCkge1xuICAgICAgaWYgKCFhY3R1YWwgJiYgIWV4cGVjdGVkKSB7XG4gICAgICAgIHJldHVybiBhY3R1YWwgPT09IGV4cGVjdGVkXG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgYWN0dWFsICE9PSB0eXBlb2YgZXhwZWN0ZWQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICB9XG4gICAgfVxuICAgIGlmICghYWN0dWFsICYmICFleHBlY3RlZCkge1xuICAgICAgcmV0dXJuIGFjdHVhbCA9PT0gZXhwZWN0ZWRcbiAgICB9XG4gICAgcmV0dXJuIG9wdHMuY29tcCEoYWN0dWFsLCBleHBlY3RlZClcblxuICAgIC8vIDcuNC4gRm9yIGFsbCBvdGhlciBPYmplY3QgcGFpcnMsIGluY2x1ZGluZyBBcnJheSBvYmplY3RzLCBlcXVpdmFsZW5jZSBpc1xuICAgIC8vIGRldGVybWluZWQgYnkgaGF2aW5nIHRoZSBzYW1lIG51bWJlciBvZiBvd25lZCBwcm9wZXJ0aWVzIChhcyB2ZXJpZmllZFxuICAgIC8vIHdpdGggT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKSwgdGhlIHNhbWUgc2V0IG9mIGtleXNcbiAgICAvLyAoYWx0aG91Z2ggbm90IG5lY2Vzc2FyaWx5IHRoZSBzYW1lIG9yZGVyKSwgZXF1aXZhbGVudCB2YWx1ZXMgZm9yIGV2ZXJ5XG4gICAgLy8gY29ycmVzcG9uZGluZyBrZXksIGFuZCBhbiBpZGVudGljYWwgJ3Byb3RvdHlwZScgcHJvcGVydHkuIE5vdGU6IHRoaXNcbiAgICAvLyBhY2NvdW50cyBmb3IgYm90aCBuYW1lZCBhbmQgaW5kZXhlZCBwcm9wZXJ0aWVzIG9uIEFycmF5cy5cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gb2JqRXF1aXYoYWN0dWFsLCBleHBlY3RlZCwgb3B0cyBhcyBhbnkpXG4gIH1cbn1cblxuZnVuY3Rpb24gaXNVbmRlZmluZWRPck51bGwodmFsdWU6IGFueSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZFxufVxuXG5mdW5jdGlvbiBpc0J1ZmZlcih4OiBhbnkpIHtcbiAgaWYgKCF4IHx8IHR5cGVvZiB4ICE9PSAnb2JqZWN0JyB8fCB0eXBlb2YgeC5sZW5ndGggIT09ICdudW1iZXInKSByZXR1cm4gZmFsc2VcbiAgaWYgKHR5cGVvZiB4LmNvcHkgIT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIHguc2xpY2UgIT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuICBpZiAoeC5sZW5ndGggPiAwICYmIHR5cGVvZiB4WzBdICE9PSAnbnVtYmVyJykgcmV0dXJuIGZhbHNlXG4gIHJldHVybiB0cnVlXG59XG5cbmZ1bmN0aW9uIG9iakVxdWl2KGE6IGFueSwgYjogYW55LCBvcHRzOiBPcHRpb25zKSB7XG4gIGxldCBpLCBrZXlcbiAgaWYgKGlzVW5kZWZpbmVkT3JOdWxsKGEpIHx8IGlzVW5kZWZpbmVkT3JOdWxsKGIpKSByZXR1cm4gZmFsc2VcbiAgLy8gYW4gaWRlbnRpY2FsICdwcm90b3R5cGUnIHByb3BlcnR5LlxuICBpZiAoYS5wcm90b3R5cGUgIT09IGIucHJvdG90eXBlKSByZXR1cm4gZmFsc2VcbiAgLy9+fn5JJ3ZlIG1hbmFnZWQgdG8gYnJlYWsgT2JqZWN0LmtleXMgdGhyb3VnaCBzY3Jld3kgYXJndW1lbnRzIHBhc3NpbmcuXG4gIC8vICAgQ29udmVydGluZyB0byBhcnJheSBzb2x2ZXMgdGhlIHByb2JsZW0uXG4gIGlmIChpc0FyZ3VtZW50cyhhKSkge1xuICAgIGlmICghaXNBcmd1bWVudHMoYikpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICByZXR1cm4gZGVlcENsb3NlVG8ocFNsaWNlLmNhbGwoYSksIHBTbGljZS5jYWxsKGIpLCBvcHRzKVxuICB9XG4gIGlmIChpc0J1ZmZlcihhKSkge1xuICAgIGlmICghaXNCdWZmZXIoYikpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICBpZiAoYS5sZW5ndGggIT09IGIubGVuZ3RoKSByZXR1cm4gZmFsc2VcbiAgICBmb3IgKGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGFbaV0gIT09IGJbaV0pIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZVxuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBrYSA9IE9iamVjdC5rZXlzKGEpXG4gICAgY29uc3Qga2IgPSBPYmplY3Qua2V5cyhiKVxuXG4gICAgLy8gaGF2aW5nIHRoZSBzYW1lIG51bWJlciBvZiBvd25lZCBwcm9wZXJ0aWVzIChrZXlzIGluY29ycG9yYXRlc1xuICAgIC8vIGhhc093blByb3BlcnR5KVxuICAgIGlmIChrYS5sZW5ndGggIT09IGtiLmxlbmd0aCkgcmV0dXJuIGZhbHNlXG4gICAgLy90aGUgc2FtZSBzZXQgb2Yga2V5cyAoYWx0aG91Z2ggbm90IG5lY2Vzc2FyaWx5IHRoZSBzYW1lIG9yZGVyKSxcbiAgICBrYS5zb3J0KClcbiAgICBrYi5zb3J0KClcbiAgICAvL35+fmNoZWFwIGtleSB0ZXN0XG4gICAgZm9yIChpID0ga2EubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIGlmIChrYVtpXSAhPT0ga2JbaV0pIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICAvL2VxdWl2YWxlbnQgdmFsdWVzIGZvciBldmVyeSBjb3JyZXNwb25kaW5nIGtleSwgYW5kXG4gICAgLy9+fn5wb3NzaWJseSBleHBlbnNpdmUgZGVlcCB0ZXN0XG4gICAgZm9yIChpID0ga2EubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIGtleSA9IGthW2ldXG4gICAgICBpZiAoIWRlZXBDbG9zZVRvKGFba2V5XSwgYltrZXldLCBvcHRzKSkgcmV0dXJuIGZhbHNlXG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgLy9oYXBwZW5zIHdoZW4gb25lIGlzIGEgc3RyaW5nIGxpdGVyYWwgYW5kIHRoZSBvdGhlciBpc24ndFxuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgcmV0dXJuIHR5cGVvZiBhID09PSB0eXBlb2YgYlxufVxuXG5mdW5jdGlvbiBpc0FyZ3VtZW50cyhvYmplY3Q6IGFueSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iamVjdCkgPT09ICdbb2JqZWN0IEFyZ3VtZW50c10nXG59XG5mdW5jdGlvbiBjbG9zZVRvKGFjdHVhbDogYW55LCBleHBlY3RlZDogYW55LCBkZWx0YTogbnVtYmVyID0gZmxvYXRFcHNpbG9uKSB7XG4gIHJldHVybiBNYXRoLmFicyhhY3R1YWwgLSBleHBlY3RlZCkgPCBkZWx0YVxufVxuIl19
@@ -0,0 +1,2 @@
1
+ import { TestDefinitionFunction } from './types';
2
+ export declare const test: TestDefinitionFunction;
@@ -0,0 +1,30 @@
1
+ import { engine } from '@dcl/ecs';
2
+ import { createTestRuntime } from './runtime';
3
+ export const test = DEBUG ? createTestFunction() : () => { };
4
+ function createTestFunction() {
5
+ let testingModule;
6
+ try {
7
+ testingModule = require('~system/Testing');
8
+ }
9
+ catch (err) {
10
+ console.error(err);
11
+ console.error(`🔴🚨‼️ WARNING: The test runner is not available. The test runner will be mocked. ‼️🚨🔴`);
12
+ testingModule = {
13
+ async logTestResult(data) {
14
+ console.log(`🧪 mocked '~system/Testing'.logResult`, data);
15
+ return {};
16
+ },
17
+ async plan(data) {
18
+ console.log(`🧪 mocked '~system/Testing'.plan`, data);
19
+ return {};
20
+ },
21
+ async setCameraTransform(transform) {
22
+ console.log(`🧪 mocked '~system/Testing'.setCameraTransform`, transform);
23
+ return {};
24
+ }
25
+ };
26
+ }
27
+ const runtime = createTestRuntime(testingModule, engine);
28
+ return runtime.test;
29
+ }
30
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdGVzdGluZy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBQ2pDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQVc3QyxNQUFNLENBQUMsTUFBTSxJQUFJLEdBQTJCLEtBQUssQ0FBQyxDQUFDLENBQWlCLGtCQUFrQixFQUFFLENBQUMsQ0FBQyxDQUFpQixHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUE7QUFFbkgsU0FBUyxrQkFBa0I7SUFDekIsSUFBSSxhQUE0QixDQUFBO0lBQ2hDLElBQUk7UUFDRixhQUFhLEdBQW1CLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO0tBQzNEO0lBQUMsT0FBTyxHQUFHLEVBQUU7UUFDWixPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBRWxCLE9BQU8sQ0FBQyxLQUFLLENBQUMsMEZBQTBGLENBQUMsQ0FBQTtRQUV6RyxhQUFhLEdBQUc7WUFDZCxLQUFLLENBQUMsYUFBYSxDQUFDLElBQUk7Z0JBQ3RCLE9BQU8sQ0FBQyxHQUFHLENBQUMsdUNBQXVDLEVBQUUsSUFBSSxDQUFDLENBQUE7Z0JBQzFELE9BQU8sRUFBRSxDQUFBO1lBQ1gsQ0FBQztZQUNELEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSTtnQkFDYixPQUFPLENBQUMsR0FBRyxDQUFDLGtDQUFrQyxFQUFFLElBQUksQ0FBQyxDQUFBO2dCQUNyRCxPQUFPLEVBQUUsQ0FBQTtZQUNYLENBQUM7WUFDRCxLQUFLLENBQUMsa0JBQWtCLENBQUMsU0FBUztnQkFDaEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnREFBZ0QsRUFBRSxTQUFTLENBQUMsQ0FBQTtnQkFDeEUsT0FBTyxFQUFFLENBQUE7WUFDWCxDQUFDO1NBQ0YsQ0FBQTtLQUNGO0lBRUQsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLENBQUMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxDQUFBO0lBQ3hELE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQTtBQUNyQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZW5naW5lIH0gZnJvbSAnQGRjbC9lY3MnXG5pbXBvcnQgeyBjcmVhdGVUZXN0UnVudGltZSB9IGZyb20gJy4vcnVudGltZSdcbmltcG9ydCB7IFRlc3REZWZpbml0aW9uRnVuY3Rpb24sIFRlc3RpbmdNb2R1bGUgfSBmcm9tICcuL3R5cGVzJ1xuXG5kZWNsYXJlIGxldCByZXF1aXJlOiBhbnlcblxuLyoqXG4gKiBJbiBkZXZlbG9wbWVudCBidWlsZHMsIHRoaXMgZnVuY3Rpb24gc2VydmVzIGFzIHRlc3QgcnVubmVyIGZvciBhdXRvbWF0ZWQgdGVzdCBzY2VuYXJpb3NcbiAqIGlmIHRoZSBydW50aW1lIGFjY2VwdHMgdGhlIGB+c3lzdGVtL1Rlc3RpbmdgIG1vZHVsZVxuICogQHB1YmxpY1xuICovXG4vKiBAX19QVVJFX18gKi9cbmV4cG9ydCBjb25zdCB0ZXN0OiBUZXN0RGVmaW5pdGlvbkZ1bmN0aW9uID0gREVCVUcgPyAvKiBAX19QVVJFX18gKi8gY3JlYXRlVGVzdEZ1bmN0aW9uKCkgOiAvKiBAX19QVVJFX18gKi8gKCkgPT4ge31cblxuZnVuY3Rpb24gY3JlYXRlVGVzdEZ1bmN0aW9uKCkge1xuICBsZXQgdGVzdGluZ01vZHVsZTogVGVzdGluZ01vZHVsZVxuICB0cnkge1xuICAgIHRlc3RpbmdNb2R1bGUgPSAvKiBAX19QVVJFX18gKi8gcmVxdWlyZSgnfnN5c3RlbS9UZXN0aW5nJylcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgY29uc29sZS5lcnJvcihlcnIpXG5cbiAgICBjb25zb2xlLmVycm9yKGDwn5S08J+aqOKAvO+4jyBXQVJOSU5HOiBUaGUgdGVzdCBydW5uZXIgaXMgbm90IGF2YWlsYWJsZS4gVGhlIHRlc3QgcnVubmVyIHdpbGwgYmUgbW9ja2VkLiDigLzvuI/wn5qo8J+UtGApXG5cbiAgICB0ZXN0aW5nTW9kdWxlID0ge1xuICAgICAgYXN5bmMgbG9nVGVzdFJlc3VsdChkYXRhKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGDwn6eqIG1vY2tlZCAnfnN5c3RlbS9UZXN0aW5nJy5sb2dSZXN1bHRgLCBkYXRhKVxuICAgICAgICByZXR1cm4ge31cbiAgICAgIH0sXG4gICAgICBhc3luYyBwbGFuKGRhdGEpIHtcbiAgICAgICAgY29uc29sZS5sb2coYPCfp6ogbW9ja2VkICd+c3lzdGVtL1Rlc3RpbmcnLnBsYW5gLCBkYXRhKVxuICAgICAgICByZXR1cm4ge31cbiAgICAgIH0sXG4gICAgICBhc3luYyBzZXRDYW1lcmFUcmFuc2Zvcm0odHJhbnNmb3JtKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGDwn6eqIG1vY2tlZCAnfnN5c3RlbS9UZXN0aW5nJy5zZXRDYW1lcmFUcmFuc2Zvcm1gLCB0cmFuc2Zvcm0pXG4gICAgICAgIHJldHVybiB7fVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHJ1bnRpbWUgPSBjcmVhdGVUZXN0UnVudGltZSh0ZXN0aW5nTW9kdWxlLCBlbmdpbmUpXG4gIHJldHVybiBydW50aW1lLnRlc3Rcbn1cbiJdfQ==
@@ -0,0 +1,5 @@
1
+ import { IEngine } from '@dcl/ecs';
2
+ import type { TestingModule, TestFunction } from './types';
3
+ export declare function createTestRuntime(testingModule: TestingModule, engine: IEngine): {
4
+ test: (name: string, fn: TestFunction) => void;
5
+ };
@@ -0,0 +1,168 @@
1
+ import { Transform } from '@dcl/ecs';
2
+ import { assertEquals } from './assert';
3
+ export function createTestRuntime(testingModule, engine) {
4
+ let runtimeFrozen = false;
5
+ let currentFrameCounter = 0;
6
+ let currentFrameTime = 0;
7
+ const scheduledTests = [];
8
+ const nextTickFuture = [];
9
+ async function nextTick() {
10
+ return new Promise((resolve) => {
11
+ nextTickFuture.push(resolve);
12
+ });
13
+ }
14
+ engine.addSystem(function TestingFrameworkCoroutineRunner(dt) {
15
+ currentFrameCounter++;
16
+ currentFrameTime += dt;
17
+ nextTickFuture.splice(0, nextTickFuture.length).forEach((_) => _(dt));
18
+ });
19
+ function scheduleValue(value, env) {
20
+ if (value && typeof value === 'object' && typeof value.then === 'function') {
21
+ console.log('⏱️ yield promise');
22
+ nextTickFuture.push(async () => {
23
+ try {
24
+ scheduleValue(await value, env);
25
+ }
26
+ catch (err) {
27
+ env.reject(err);
28
+ }
29
+ });
30
+ }
31
+ else if (typeof value === 'function') {
32
+ console.log('⏱️ yield function');
33
+ nextTickFuture.push(() => {
34
+ scheduleValue(value(), env);
35
+ });
36
+ return;
37
+ }
38
+ else if (typeof value === 'undefined' || value === null) {
39
+ console.log('⏱️ yield');
40
+ nextTickFuture.push(() => {
41
+ consumeGenerator(env);
42
+ });
43
+ }
44
+ else
45
+ throw new Error(`Unexpected value from test generator: ${value}`);
46
+ }
47
+ function consumeGenerator(env) {
48
+ try {
49
+ const ret = env.generator.next();
50
+ if (!ret.done) {
51
+ scheduleValue(ret.value, env);
52
+ }
53
+ else {
54
+ env.resolve();
55
+ }
56
+ }
57
+ catch (err) {
58
+ env.reject(err);
59
+ }
60
+ }
61
+ function scheduleNextRun() {
62
+ if (scheduledTests.length) {
63
+ nextTickFuture.push(runTests);
64
+ }
65
+ }
66
+ function runTests() {
67
+ if (scheduledTests.length) {
68
+ const entry = scheduledTests.shift();
69
+ const initialFrame = currentFrameCounter;
70
+ const startTime = currentFrameTime;
71
+ let resolved = false;
72
+ const resolve = () => {
73
+ if (resolved)
74
+ throw new Error('resolved twice');
75
+ resolved = true;
76
+ console.log(`🟢 Test passed ${entry.name}`);
77
+ testingModule
78
+ .logTestResult({
79
+ name: entry.name,
80
+ ok: true,
81
+ totalFrames: currentFrameCounter - initialFrame,
82
+ totalTime: currentFrameTime - startTime
83
+ })
84
+ .finally(scheduleNextRun);
85
+ };
86
+ const reject = (err) => {
87
+ if (resolved)
88
+ throw new Error('resolved twice');
89
+ resolved = true;
90
+ console.log(`🔴 Test failed ${entry.name}`);
91
+ console.error(err);
92
+ testingModule
93
+ .logTestResult({
94
+ name: entry.name,
95
+ ok: false,
96
+ error: err.toString(),
97
+ stack: err && typeof err === 'object' && err.stack,
98
+ totalFrames: currentFrameCounter - initialFrame,
99
+ totalTime: currentFrameTime - startTime
100
+ })
101
+ .finally(scheduleNextRun);
102
+ };
103
+ try {
104
+ console.log(`🧪 Running test ${entry.name}`);
105
+ const testHelpers = {
106
+ async setCameraTransform(transform) {
107
+ await testingModule.setCameraTransform(transform);
108
+ await nextTick();
109
+ const TransformComponent = engine.getComponent(Transform.componentId);
110
+ const actualTransform = TransformComponent.get(engine.CameraEntity);
111
+ assertEquals(actualTransform.position, transform.position, "positions don't match");
112
+ assertEquals(actualTransform.rotation, transform.rotation, "rotations don't match");
113
+ }
114
+ };
115
+ const returnValue = entry.fn(testHelpers);
116
+ if (returnValue && typeof returnValue === 'object') {
117
+ if (isGenerator(returnValue)) {
118
+ const env = {
119
+ generator: returnValue,
120
+ helpers: testHelpers,
121
+ resolve,
122
+ reject
123
+ };
124
+ consumeGenerator(env);
125
+ }
126
+ else if (isPromise(returnValue)) {
127
+ returnValue.then(resolve).catch(reject);
128
+ }
129
+ else {
130
+ throw new Error(`Unknown test result type: ${returnValue}`);
131
+ }
132
+ }
133
+ else {
134
+ resolve();
135
+ }
136
+ }
137
+ catch (err) {
138
+ reject(err);
139
+ }
140
+ }
141
+ }
142
+ nextTickFuture.push(() => {
143
+ runtimeFrozen = true;
144
+ if (!scheduledTests.length)
145
+ return;
146
+ testingModule.plan({ tests: scheduledTests }).then(scheduleNextRun).catch(globalFail);
147
+ });
148
+ function test(name, fn) {
149
+ if (runtimeFrozen)
150
+ throw new Error("New tests can't be added at this stage.");
151
+ if (scheduledTests.some(($) => $.name === name))
152
+ throw new Error(`Test with name ${name} already exists`);
153
+ scheduledTests.push({ fn, name });
154
+ }
155
+ return {
156
+ test
157
+ };
158
+ }
159
+ function isGenerator(t) {
160
+ return t && typeof t === 'object' && typeof t[Symbol.iterator] === 'function';
161
+ }
162
+ function isPromise(t) {
163
+ return t && typeof t === 'object' && typeof t.then === 'function';
164
+ }
165
+ function globalFail(error) {
166
+ console.error(error);
167
+ }
168
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90ZXN0aW5nL3J1bnRpbWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBSUEsT0FBTyxFQUFXLFNBQVMsRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUM3QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBT3ZDLE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxhQUE0QixFQUFFLE1BQWU7SUFVN0UsSUFBSSxhQUFhLEdBQUcsS0FBSyxDQUFBO0lBRXpCLElBQUksbUJBQW1CLEdBQUcsQ0FBQyxDQUFBO0lBQzNCLElBQUksZ0JBQWdCLEdBQUcsQ0FBQyxDQUFBO0lBR3hCLE1BQU0sY0FBYyxHQUFvQixFQUFFLENBQUE7SUFHMUMsTUFBTSxjQUFjLEdBQWdDLEVBQUUsQ0FBQTtJQUd0RCxLQUFLLFVBQVUsUUFBUTtRQUNyQixPQUFPLElBQUksT0FBTyxDQUFTLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDckMsY0FBYyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUM5QixDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFHRCxNQUFNLENBQUMsU0FBUyxDQUFDLFNBQVMsK0JBQStCLENBQUMsRUFBRTtRQUMxRCxtQkFBbUIsRUFBRSxDQUFBO1FBQ3JCLGdCQUFnQixJQUFJLEVBQUUsQ0FBQTtRQUV0QixjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUN2RSxDQUFDLENBQUMsQ0FBQTtJQUlGLFNBQVMsYUFBYSxDQUFDLEtBQVUsRUFBRSxHQUFzQjtRQUN2RCxJQUFJLEtBQUssSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksT0FBTyxLQUFLLENBQUMsSUFBSSxLQUFLLFVBQVUsRUFBRTtZ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YTtZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMseUNBQXlDLENBQUMsQ0FBQTtRQUU3RSxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSxpQkFBaUIsQ0FBQyxDQUFBO1FBRXpHLGNBQWMsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUNuQyxDQUFDO0lBRUQsT0FBTztRQUNMLElBQUk7S0FDTCxDQUFBO0FBQ0gsQ0FBQztBQUVELFNBQVMsV0FBVyxDQUFDLENBQU07SUFDekIsT0FBTyxDQUFDLElBQUksT0FBTyxDQUFDLEtBQUssUUFBUSxJQUFJLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxVQUFVLENBQUE7QUFDL0UsQ0FBQztBQUVELFNBQVMsU0FBUyxDQUFDLENBQU07SUFDdkIsT0FBTyxDQUFDLElBQUksT0FBTyxDQUFDLEtBQUssUUFBUSxJQUFJLE9BQU8sQ0FBQyxDQUFDLElBQUksS0FBSyxVQUFVLENBQUE7QUFDbkUsQ0FBQztBQUVELFNBQVMsVUFBVSxDQUFDLEtBQVU7SUFFNUIsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQTtBQUN0QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGlzIG1vZHVsZSBwcm92aWRlcyBhIGNyZWF0ZVRlc3RSdW50aW1lIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhbiBvYmplY3Qgd2l0aCBhIHRlc3QgZnVuY3Rpb24gdGhhdCBjYW4gYmUgdXNlZCB0byBkZWZpbmUgdGVzdHMuXG4gKi9cblxuaW1wb3J0IHsgSUVuZ2luZSwgVHJhbnNmb3JtIH0gZnJvbSAnQGRjbC9lY3MnXG5pbXBvcnQgeyBhc3NlcnRFcXVhbHMgfSBmcm9tICcuL2Fzc2VydCdcbmltcG9ydCB0eXBlIHsgVGVzdGluZ01vZHVsZSwgVGVzdEZ1bmN0aW9uLCBUZXN0SGVscGVycyB9IGZyb20gJy4vdHlwZXMnXG5cbi8vIFRoaXMgZnVuY3Rpb24gY3JlYXRlcyBhIHRlc3QgcnVudGltZSB0aGF0IGNhbiBiZSB1c2VkIHRvIGRlZmluZSBhbmQgcnVuIHRlc3RzLlxuLy8gSXQgdGFrZXMgYSBgVGVzdGluZ01vZHVsZWAgaW5zdGFuY2UgKGxvYWRlZCBmcm9tIHJlcXVpcmUoJ35zeXN0ZW0vVGVzdGluZycpKSBhbmQgYW4gYElFbmdpbmVgIGluc3RhbmNlIChmcm9tIERlY2VudHJhbGFuZCdzIFNESykuXG4vLyBJdCByZXR1cm5zIGFuIG9iamVjdCB3aXRoIGEgYHRlc3RgIGZ1bmN0aW9uIHRoYXQgY2FuIGJlIHVzZWQgdG8gZGVmaW5lIHRlc3RzLlxuLyogQF9fUFVSRV9fICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlVGVzdFJ1bnRpbWUodGVzdGluZ01vZHVsZTogVGVzdGluZ01vZHVsZSwgZW5naW5lOiBJRW5naW5lKSB7XG4gIHR5cGUgVGVzdFBsYW5FbnRyeSA9IHsgbmFtZTogc3RyaW5nOyBmbjogVGVzdEZ1bmN0aW9uIH1cbiAgdHlwZSBSdW5uZXJFbnZpcm9ubWVudCA9IHtcbiAgICByZXNvbHZlOiAoKSA9PiB2b2lkXG4gICAgcmVqZWN0OiAoZXJyb3I6IGFueSkgPT4gdm9pZFxuICAgIGhlbHBlcnM6IFRlc3RIZWxwZXJzXG4gICAgZ2VuZXJhdG9yOiBHZW5lcmF0b3JcbiAgfVxuXG4gIC8vIHRoaXMgZmxhZyBlbnN1cmVzIG5vIHRlc3RzIGFyZSBhZGRlZCBhc3luY2hyb25vdXNseVxuICBsZXQgcnVudGltZUZyb3plbiA9IGZhbHNlXG5cbiAgbGV0IGN1cnJlbnRGcmFtZUNvdW50ZXIgPSAwXG4gIGxldCBjdXJyZW50RnJhbWVUaW1lID0gMFxuXG4gIC8vIGFycmF5IHRvIGhvbGQgdGhlIHNjaGVkdWxlZCB0ZXN0c1xuICBjb25zdCBzY2hlZHVsZWRUZXN0czogVGVzdFBsYW5FbnRyeVtdID0gW11cblxuICAvLyBhbiBhcnJheSBvZiBwcm9taXNlcyB0aGF0IGFyZSByZXNvbHZlZCBvbiB0aGUgbmV4dCBmcmFtZSAoYWZ0ZXIgdGhlIGN1cnJlbnQgZnJhbWUgaXMgZmluaXNoZWQpXG4gIGNvbnN0IG5leHRUaWNrRnV0dXJlOiBBcnJheTwoZHQ6IG51bWJlcikgPT4gdm9pZD4gPSBbXVxuXG4gIC8vIHRoaXMgZnVuY3Rpb24gcmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBvbiB0aGUgbmV4dCBmcmFtZVxuICBhc3luYyBmdW5jdGlvbiBuZXh0VGljaygpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8bnVtYmVyPigocmVzb2x2ZSkgPT4ge1xuICAgICAgbmV4dFRpY2tGdXR1cmUucHVzaChyZXNvbHZlKVxuICAgIH0pXG4gIH1cblxuICAvLyBhZGQgYSBzeXN0ZW0gdG8gdGhlIGVuZ2luZSB0aGF0IHJlc29sdmVzIGFsbCBwcm9taXNlcyBpbiB0aGUgYG5leHRUaWNrRnV0dXJlYCBhcnJheVxuICBlbmdpbmUuYWRkU3lzdGVtKGZ1bmN0aW9uIFRlc3RpbmdGcmFtZXdvcmtDb3JvdXRpbmVSdW5uZXIoZHQpIHtcbiAgICBjdXJyZW50RnJhbWVDb3VudGVyKytcbiAgICBjdXJyZW50RnJhbWVUaW1lICs9IGR0XG4gICAgLy8gcmVzb2x2ZSBhbGwgbmV4dFRpY2sgZnV0dXJlcy5cbiAgICBuZXh0VGlja0Z1dHVyZS5zcGxpY2UoMCwgbmV4dFRpY2tGdXR1cmUubGVuZ3RoKS5mb3JFYWNoKChfKSA9PiBfKGR0KSlcbiAgfSlcblxuICAvLyB0aGlzIGZ1bmN0aW9uIHNjaGVkdWxlcyBhIHZhbHVlIHRvIGJlIHByb2Nlc3NlZCBvbiB0aGUgbmV4dCBmcmFtZSwgdGhlIHRlc3QgcnVubmVyIHdpbGxcbiAgLy8gY29udGludWUgdG8gcnVuIHVudGlsIGl0IHJlYWNoZXMgYSB5aWVsZCBwb2ludFxuICBmdW5jdGlvbiBzY2hlZHVsZVZhbHVlKHZhbHVlOiBhbnksIGVudjogUnVubmVyRW52aXJvbm1lbnQpIHtcbiAgICBpZiAodmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgdmFsdWUudGhlbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY29uc29sZS5sb2coJ+KPse+4jyB5aWVsZCBwcm9taXNlJylcbiAgICAgIC8vIGlmIHRoZSB2YWx1ZSBpcyBhIHByb21pc2UsIHNjaGVkdWxlIGl0IHRvIGJlIGF3YWl0ZWQgYWZ0ZXIgdGhlIGN1cnJlbnQgZnJhbWUgaXMgZmluaXNoZWRcbiAgICAgIG5leHRUaWNrRnV0dXJlLnB1c2goYXN5bmMgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHNjaGVkdWxlVmFsdWUoYXdhaXQgdmFsdWUsIGVudilcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgZW52LnJlamVjdChlcnIpXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGNvbnNvbGUubG9nKCfij7HvuI8geWllbGQgZnVuY3Rpb24nKVxuICAgICAgLy8gaWYgdGhlIHZhbHVlIGlzIGEgZnVuY3Rpb24sIHNjaGVkdWxlIGl0IHRvIGJlIGNhbGxlZCBvbiB0aGUgbmV4dCBmcmFtZVxuICAgICAgbmV4dFRpY2tGdXR1cmUucHVzaCgoKSA9PiB7XG4gICAgICAgIHNjaGVkdWxlVmFsdWUodmFsdWUoKSwgZW52KVxuICAgICAgfSlcbiAgICAgIHJldHVyblxuICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJyB8fCB2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgY29uc29sZS5sb2coJ+KPse+4jyB5aWVsZCcpXG4gICAgICAvLyBpZiB0aGUgdmFsdWUgaXMgdW5kZWZpbmVkIG9yIG51bGwsIGNvbnRpbnVlIHByb2Nlc3NpbmcgdGhlIGdlbmVyYXRvciB0aGUgbmV4dCBmcmFtZVxuICAgICAgbmV4dFRpY2tGdXR1cmUucHVzaCgoKSA9PiB7XG4gICAgICAgIGNvbnN1bWVHZW5lcmF0b3IoZW52KVxuICAgICAgfSlcbiAgICB9IGVsc2UgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkIHZhbHVlIGZyb20gdGVzdCBnZW5lcmF0b3I6ICR7dmFsdWV9YClcbiAgfVxuXG4gIC8vIHRoaXMgZnVuY3Rpb24gcHJvY2Vzc2VzIGEgZ2VuZXJhdG9yIGZ1bmN0aW9uIGJ5IHNjaGVkdWxpbmcgaXRzIHZhbHVlcyB0byBiZSBwcm9jZXNzZWQgb24gdGhlIG5leHQgZnJhbWVcbiAgZnVuY3Rpb24gY29uc3VtZUdlbmVyYXRvcihlbnY6IFJ1bm5lckVudmlyb25tZW50KSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJldCA9IGVudi5nZW5lcmF0b3IubmV4dCgpXG4gICAgICBpZiAoIXJldC5kb25lKSB7XG4gICAgICAgIHNjaGVkdWxlVmFsdWUocmV0LnZhbHVlLCBlbnYpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlbnYucmVzb2x2ZSgpXG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBlbnYucmVqZWN0KGVycilcbiAgICB9XG4gIH1cblxuICAvLyB0aGlzIGZ1bmN0aW9uIHNjaGVkdWxlcyBhIHRlc3QgcnVuIG9uIHRoZSBuZXh0IGZyYW1lXG4gIGZ1bmN0aW9uIHNjaGVkdWxlTmV4dFJ1bigpIHtcbiAgICBpZiAoc2NoZWR1bGVkVGVzdHMubGVuZ3RoKSB7XG4gICAgICBuZXh0VGlja0Z1dHVyZS5wdXNoKHJ1blRlc3RzKVxuICAgIH1cbiAgfVxuXG4gIC8vIHRoaXMgZnVuY3Rpb24gcnVucyB0aGUgc2NoZWR1bGVkIHRlc3RzXG4gIGZ1bmN0aW9uIHJ1blRlc3RzKCkge1xuICAgIGlmIChzY2hlZHVsZWRUZXN0cy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IGVudHJ5ID0gc2NoZWR1bGVkVGVzdHMuc2hpZnQoKSFcbiAgICAgIGNvbnN0IGluaXRpYWxGcmFtZSA9IGN1cnJlbnRGcmFtZUNvdW50ZXJcbiAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IGN1cnJlbnRGcmFtZVRpbWVcblxuICAgICAgbGV0IHJlc29sdmVkID0gZmFsc2VcblxuICAgICAgLy8gdGhpcyBmdW5jdGlvbiBzaG91bGQgYmUgY2FsbGVkIG9ubHkgb25jZS4gaXQgbWFrZXMgdGhlIGN1cnJlbnQgdGVzdCBwYXNzXG4gICAgICBjb25zdCByZXNvbHZlID0gKCkgPT4ge1xuICAgICAgICBpZiAocmVzb2x2ZWQpIHRocm93IG5ldyBFcnJvcigncmVzb2x2ZWQgdHdpY2UnKVxuICAgICAgICByZXNvbHZlZCA9IHRydWVcblxuICAgICAgICBjb25zb2xlLmxvZyhg8J+foiBUZXN0IHBhc3NlZCAke2VudHJ5Lm5hbWV9YClcblxuICAgICAgICB0ZXN0aW5nTW9kdWxlXG4gICAgICAgICAgLmxvZ1Rlc3RSZXN1bHQoe1xuICAgICAgICAgICAgbmFtZTogZW50cnkubmFtZSxcbiAgICAgICAgICAgIG9rOiB0cnVlLFxuICAgICAgICAgICAgdG90YWxGcmFtZXM6IGN1cnJlbnRGcmFtZUNvdW50ZXIgLSBpbml0aWFsRnJhbWUsXG4gICAgICAgICAgICB0b3RhbFRpbWU6IGN1cnJlbnRGcmFtZVRpbWUgLSBzdGFydFRpbWVcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5maW5hbGx5KHNjaGVkdWxlTmV4dFJ1bilcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVqZWN0ID0gKGVycjogYW55KSA9PiB7XG4gICAgICAgIGlmIChyZXNvbHZlZCkgdGhyb3cgbmV3IEVycm9yKCdyZXNvbHZlZCB0d2ljZScpXG4gICAgICAgIHJlc29sdmVkID0gdHJ1ZVxuXG4gICAgICAgIGNvbnNvbGUubG9nKGDwn5S0IFRlc3QgZmFpbGVkICR7ZW50cnkubmFtZX1gKVxuICAgICAgICBjb25zb2xlLmVycm9yKGVycilcblxuICAgICAgICB0ZXN0aW5nTW9kdWxlXG4gICAgICAgICAgLmxvZ1Rlc3RSZXN1bHQoe1xuICAgICAgICAgICAgbmFtZTogZW50cnkubmFtZSxcbiAgICAgICAgICAgIG9rOiBmYWxzZSxcbiAgICAgICAgICAgIGVycm9yOiBlcnIudG9TdHJpbmcoKSxcbiAgICAgICAgICAgIHN0YWNrOiBlcnIgJiYgdHlwZW9mIGVyciA9PT0gJ29iamVjdCcgJiYgZXJyLnN0YWNrLFxuICAgICAgICAgICAgdG90YWxGcmFtZXM6IGN1cnJlbnRGcmFtZUNvdW50ZXIgLSBpbml0aWFsRnJhbWUsXG4gICAgICAgICAgICB0b3RhbFRpbWU6IGN1cnJlbnRGcmFtZVRpbWUgLSBzdGFydFRpbWVcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5maW5hbGx5KHNjaGVkdWxlTmV4dFJ1bilcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc29sZS5sb2coYPCfp6ogUnVubmluZyB0ZXN0ICR7ZW50cnkubmFtZX1gKVxuXG4gICAgICAgIGNvbnN0IHRlc3RIZWxwZXJzOiBUZXN0SGVscGVycyA9IHtcbiAgICAgICAgICBhc3luYyBzZXRDYW1lcmFUcmFuc2Zvcm0odHJhbnNmb3JtKSB7XG4gICAgICAgICAgICBhd2FpdCB0ZXN0aW5nTW9kdWxlLnNldENhbWVyYVRyYW5zZm9ybSh0cmFuc2Zvcm0pXG4gICAgICAgICAgICBhd2FpdCBuZXh0VGljaygpXG5cbiAgICAgICAgICAgIGNvbnN0IFRyYW5zZm9ybUNvbXBvbmVudCA9IGVuZ2luZS5nZXRDb21wb25lbnQoVHJhbnNmb3JtLmNvbXBvbmVudElkKSBhcyB0eXBlb2YgVHJhbnNmb3JtXG4gICAgICAgICAgICBjb25zdCBhY3R1YWxUcmFuc2Zvcm0gPSBUcmFuc2Zvcm1Db21wb25lbnQuZ2V0KGVuZ2luZS5DYW1lcmFFbnRpdHkpXG5cbiAgICAgICAgICAgIGFzc2VydEVxdWFscyhhY3R1YWxUcmFuc2Zvcm0ucG9zaXRpb24sIHRyYW5zZm9ybS5wb3NpdGlvbiwgXCJwb3NpdGlvbnMgZG9uJ3QgbWF0Y2hcIilcbiAgICAgICAgICAgIGFzc2VydEVxdWFscyhhY3R1YWxUcmFuc2Zvcm0ucm90YXRpb24sIHRyYW5zZm9ybS5yb3RhdGlvbiwgXCJyb3RhdGlvbnMgZG9uJ3QgbWF0Y2hcIilcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXR1cm5WYWx1ZSA9IGVudHJ5LmZuKHRlc3RIZWxwZXJzKVxuXG4gICAgICAgIGlmIChyZXR1cm5WYWx1ZSAmJiB0eXBlb2YgcmV0dXJuVmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgaWYgKGlzR2VuZXJhdG9yKHJldHVyblZhbHVlKSkge1xuICAgICAgICAgICAgY29uc3QgZW52OiBSdW5uZXJFbnZpcm9ubWVudCA9IHtcbiAgICAgICAgICAgICAgZ2VuZXJhdG9yOiByZXR1cm5WYWx1ZSxcbiAgICAgICAgICAgICAgaGVscGVyczogdGVzdEhlbHBlcnMsXG4gICAgICAgICAgICAgIHJlc29sdmUsXG4gICAgICAgICAgICAgIHJlamVjdFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3VtZUdlbmVyYXRvcihlbnYpXG4gICAgICAgICAgfSBlbHNlIGlmIChpc1Byb21pc2UocmV0dXJuVmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZS50aGVuKHJlc29sdmUpLmNhdGNoKHJlamVjdClcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHRlc3QgcmVzdWx0IHR5cGU6ICR7cmV0dXJuVmFsdWV9YClcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzb2x2ZSgpXG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgIHJlamVjdChlcnIpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gc2NoZWR1bGUgdGhlIHRlc3QgcnVubmVyIHN0YXJ0IGZvciB0aGUgbmV4dCBmcmFtZVxuICBuZXh0VGlja0Z1dHVyZS5wdXNoKCgpID0+IHtcbiAgICAvLyBvbmNlIHdlIHJ1biB0aGUgbmV4dCB0aWNrLCB0aGUgdGVzdCBydW50aW1lIGJlY29tZXMgZnJvemVuLiB0aGF0IG1lYW5zIG5vIG5ld1xuICAgIC8vIHRlc3QgZGVmaW5pdGlvbnMgYXJlIGFjY2VwdGVkXG4gICAgcnVudGltZUZyb3plbiA9IHRydWVcblxuICAgIGlmICghc2NoZWR1bGVkVGVzdHMubGVuZ3RoKSByZXR1cm5cblxuICAgIC8vIGluZm9ybSB0aGUgdGVzdCBydW5uZXIgYWJvdXQgdGhlIHBsYW5zIGZvciB0aGlzIHRlc3QgcnVuXG4gICAgdGVzdGluZ01vZHVsZS5wbGFuKHsgdGVzdHM6IHNjaGVkdWxlZFRlc3RzIH0pLnRoZW4oc2NoZWR1bGVOZXh0UnVuKS5jYXRjaChnbG9iYWxGYWlsKVxuICB9KVxuXG4gIC8vIHRoaXMgaXMgdGhlIGZ1bmN0aW9uIHRoYXQgaXMgdXNlZCB0byBwbGFuIGEgdGVzdCBmdW5jdGlvbm5cbiAgLyogQF9fUFVSRV9fICovXG4gIGZ1bmN0aW9uIHRlc3QobmFtZTogc3RyaW5nLCBmbjogVGVzdEZ1bmN0aW9uKSB7XG4gICAgaWYgKHJ1bnRpbWVGcm96ZW4pIHRocm93IG5ldyBFcnJvcihcIk5ldyB0ZXN0cyBjYW4ndCBiZSBhZGRlZCBhdCB0aGlzIHN0YWdlLlwiKVxuXG4gICAgaWYgKHNjaGVkdWxlZFRlc3RzLnNvbWUoKCQpID0+ICQubmFtZSA9PT0gbmFtZSkpIHRocm93IG5ldyBFcnJvcihgVGVzdCB3aXRoIG5hbWUgJHtuYW1lfSBhbHJlYWR5IGV4aXN0c2ApXG5cbiAgICBzY2hlZHVsZWRUZXN0cy5wdXNoKHsgZm4sIG5hbWUgfSlcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgdGVzdFxuICB9XG59XG5cbmZ1bmN0aW9uIGlzR2VuZXJhdG9yKHQ6IGFueSk6IHQgaXMgR2VuZXJhdG9yIHtcbiAgcmV0dXJuIHQgJiYgdHlwZW9mIHQgPT09ICdvYmplY3QnICYmIHR5cGVvZiB0W1N5bWJvbC5pdGVyYXRvcl0gPT09ICdmdW5jdGlvbidcbn1cblxuZnVuY3Rpb24gaXNQcm9taXNlKHQ6IGFueSk6IHQgaXMgUHJvbWlzZTx1bmtub3duPiB7XG4gIHJldHVybiB0ICYmIHR5cGVvZiB0ID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgdC50aGVuID09PSAnZnVuY3Rpb24nXG59XG5cbmZ1bmN0aW9uIGdsb2JhbEZhaWwoZXJyb3I6IGFueSkge1xuICAvLyBmb3Igbm93LCB0aGUgZmFpbHVyZSBpcyBvbmx5IHdyaXRpbmcgdG8gdGhlIGNvbnNvbGUuZXJyb3IuXG4gIGNvbnNvbGUuZXJyb3IoZXJyb3IpXG59XG4iXX0=
@@ -0,0 +1,13 @@
1
+ /// <reference types="@dcl/js-runtime" />
2
+ import type { TransformType } from '@dcl/ecs';
3
+ import type { logTestResult, plan, setCameraTransform } from '~system/Testing';
4
+ export type TestHelpers = {
5
+ setCameraTransform(transform: Pick<TransformType, 'position' | 'rotation'>): Promise<void>;
6
+ };
7
+ export type TestFunction = (helpers: TestHelpers) => Generator | Promise<any>;
8
+ export type TestDefinitionFunction = (name: string, fn: TestFunction) => void;
9
+ export type TestingModule = {
10
+ logTestResult: typeof logTestResult;
11
+ plan: typeof plan;
12
+ setCameraTransform: typeof setCameraTransform;
13
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdGVzdGluZy90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBUcmFuc2Zvcm1UeXBlIH0gZnJvbSAnQGRjbC9lY3MnXG5pbXBvcnQgdHlwZSB7IGxvZ1Rlc3RSZXN1bHQsIHBsYW4sIHNldENhbWVyYVRyYW5zZm9ybSB9IGZyb20gJ35zeXN0ZW0vVGVzdGluZydcblxuZXhwb3J0IHR5cGUgVGVzdEhlbHBlcnMgPSB7XG4gIC8qKlxuICAgKiBJbnN0cnVjdHMgdGhlIHJlbmRlcmVyIHRvIHNldCB0aGUgY2FtZXJhIHRyYW5zZm9ybSB0byB0aGUgcHJvdmlkZWQgYXJndW1lbnQuXG4gICAqIFRoaXMgZnVuY3Rpb24gcmVzb2x2ZXMgdGhlIG5leHQgZnJhbWUgYW5kIGZhaWxzIGlmIHRoZSBDYW1lcmFUcmFuc2Zvcm0gaXMgbm90XG4gICAqIGVxdWFsIHRvIHRoZSBwcm92aWRlZCBhcmd1bWVudC5cbiAgICovXG4gIHNldENhbWVyYVRyYW5zZm9ybSh0cmFuc2Zvcm06IFBpY2s8VHJhbnNmb3JtVHlwZSwgJ3Bvc2l0aW9uJyB8ICdyb3RhdGlvbic+KTogUHJvbWlzZTx2b2lkPlxufVxuXG5leHBvcnQgdHlwZSBUZXN0RnVuY3Rpb24gPSAoaGVscGVyczogVGVzdEhlbHBlcnMpID0+IEdlbmVyYXRvciB8IFByb21pc2U8YW55PlxuXG5leHBvcnQgdHlwZSBUZXN0RGVmaW5pdGlvbkZ1bmN0aW9uID0gKG5hbWU6IHN0cmluZywgZm46IFRlc3RGdW5jdGlvbikgPT4gdm9pZFxuXG5leHBvcnQgdHlwZSBUZXN0aW5nTW9kdWxlID0ge1xuICBsb2dUZXN0UmVzdWx0OiB0eXBlb2YgbG9nVGVzdFJlc3VsdFxuICBwbGFuOiB0eXBlb2YgcGxhblxuICBzZXRDYW1lcmFUcmFuc2Zvcm06IHR5cGVvZiBzZXRDYW1lcmFUcmFuc2Zvcm1cbn1cbiJdfQ==
@@ -1,6 +1,4 @@
1
1
  {
2
- "compilerOptions": {
3
-
4
- },
2
+ "compilerOptions": {},
5
3
  "extends": "./tsconfig.ecs7.json"
6
4
  }
package/README.md DELETED
File without changes
package/tsconfig.cli.json DELETED
@@ -1,24 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2017",
4
- "module": "commonjs",
5
- "esModuleInterop": true,
6
- "declaration": true,
7
- "noUnusedLocals": true,
8
- "stripInternal": true,
9
- "skipLibCheck": true,
10
- "forceConsistentCasingInFileNames": true,
11
- "allowJs": true,
12
- "strict": true,
13
- "types": [
14
- "node",
15
- ],
16
- "lib": [
17
- "es2016"
18
- ],
19
- "outDir": "./cli"
20
- },
21
- "include": ["cli"],
22
- "exclude": ["dist", "**/proto"],
23
- "extends": "./types/tsconfig.ecs7.strict.json"
24
- }