1
+ import inspector from 'inspector' ;
2
+
3
+ let isDebuggerAttached = false ;
4
+ if ( inspector . url ( ) !== undefined && new URL ( inspector . url ( ) ! ) . port === '12016' && ! isDebuggerAttached ) {
5
+ inspector . waitForDebugger ( ) ;
6
+ isDebuggerAttached = true ;
7
+ }
8
+
9
+ // WARNING: do not install @types /jasmine as it will flood the global scope with types that are not needed
1
10
// @ts -expect-error - jasmine-core does not have a declaration file
2
11
import jasmineModule from 'jasmine-core' ;
3
12
import 'reflect-metadata' ;
@@ -13,6 +22,7 @@ import type { ConfigureFn, Method, MethodNames, ParameterlessCtor, TestFn } from
13
22
const nativeLibrary : JasmineModule = jasmineModule . noGlobals ( ) ;
14
23
const BaseTest = ServiceLocator . resolveType ( BellatrixTest ) ;
15
24
const testSettings = BellatrixSettings . get ( ) . frameworkSettings . testSettings ;
25
+ const testFilters = JSON . parse ( process . env . BELLATRIX_TEST_FILTER ! ) ;
16
26
17
27
function getSymbolMethods < T extends BellatrixTest > ( type : ParameterlessCtor < T > ) {
18
28
return {
@@ -46,6 +56,66 @@ export function SuiteDecorator<T extends BellatrixTest>(target: ParameterlessCto
46
56
const testMethods = Object . getOwnPropertyNames ( testClass ) . filter ( method => typeof testClass [ method ] === 'function' && Reflect . hasMetadata ( Symbols . TEST , testClass [ method ] ) ) ;
47
57
const title = target . name ; // or passed as @Suite ('title') or similar
48
58
59
+ const tests : Map < string , unknown > = new Map ;
60
+ for ( const testMethod of testMethods ) {
61
+ const testMetadata = getTestMetadata ( testClass [ testMethod ] , testClass ) ;
62
+
63
+ for ( const [ filterKey , filterValue ] of Object . entries ( testFilters ) ) {
64
+ if ( filterKey == 'suiteName' ) {
65
+ if ( Array . isArray ( filterValue ) ) {
66
+ throw new Error ( 'no more than one --suiteName argument allowed as it equals to AND operator, use regex' ) ;
67
+ }
68
+
69
+ if ( ! ( new RegExp ( String ( filterValue ) , 'i' ) . test ( testMetadata [ filterKey ] ) ) ) {
70
+ testMetadata . shouldSkip = true ;
71
+ break ;
72
+ }
73
+ }
74
+
75
+ if ( filterKey == 'testName' ) {
76
+ if ( Array . isArray ( filterValue ) ) {
77
+ throw new Error ( 'no more than one --testName argument allowed as it equals to AND operator, use regex' ) ;
78
+ }
79
+
80
+ if ( ! ( new RegExp ( String ( filterValue ) , 'i' ) . test ( testMetadata [ filterKey ] ) ) ) {
81
+ testMetadata . shouldSkip = true ;
82
+ break ;
83
+ }
84
+ } else {
85
+ if ( Array . isArray ( filterValue ) ) {
86
+ let remainingMatches = filterValue . length ;
87
+ filterValue . forEach ( singleFilterValue => {
88
+ if ( new RegExp ( String ( singleFilterValue ) , 'i' ) . test ( String ( testMetadata . customData . get ( filterKey ) ) ) ) {
89
+ remainingMatches -- ;
90
+ }
91
+ } ) ;
92
+
93
+ if ( remainingMatches > 0 ) {
94
+ testMetadata . shouldSkip = true ;
95
+ break ;
96
+ }
97
+ } else if ( ! ( new RegExp ( String ( filterValue ) , 'i' ) . test ( String ( testMetadata . customData . get ( filterKey ) ) ) ) ) {
98
+ testMetadata . shouldSkip = true ;
99
+ break ;
100
+ }
101
+ }
102
+ }
103
+
104
+ const currentTest = async ( ) => {
105
+ try {
106
+ await testClass [ testMethod ] . call ( testClassInstance ) ;
107
+ } catch ( error ) {
108
+ if ( error instanceof Error ) {
109
+ testMetadata . error = error ;
110
+ throw error ;
111
+ }
112
+ }
113
+ } ;
114
+
115
+ Object . defineProperty ( currentTest , 'name' , { value : testMethod } ) ; // !!! Important
116
+ tests . set ( testMethod , currentTest ) ;
117
+ }
118
+
49
119
nativeLibrary . describe ( title , ( ) => {
50
120
nativeLibrary . beforeAll ( async ( ) => await testClassSymbolMethods . beforeAll . call ( testClassInstance ) ) ;
51
121
@@ -63,18 +133,16 @@ export function SuiteDecorator<T extends BellatrixTest>(target: ParameterlessCto
63
133
64
134
nativeLibrary . afterAll ( async ( ) => await testClassSymbolMethods . afterAll . call ( testClassInstance ) ) ;
65
135
66
- for ( const testMethod of testMethods ) {
67
- nativeLibrary . it ( testMethod , async ( ) => {
68
- try {
69
- await testClass [ testMethod ] . call ( testClassInstance ) ;
70
- } catch ( error ) {
71
- if ( error instanceof Error ) {
72
- getTestMetadata ( testClass [ testMethod ] , testClass ) . error = error ;
73
- throw error ;
74
- }
75
- }
76
- } , testSettings . testTimeout ! ) ;
77
- }
136
+ tests . forEach ( ( testFunction , testName ) => {
137
+ const testMetadata = getTestMetadata ( testClass [ ( testFunction as Function ) . name ] , testClass ) ;
138
+ if ( testMetadata . shouldSkip ) {
139
+ nativeLibrary . xit ( testName , testFunction as never , testSettings . testTimeout ) ;
140
+ } else if ( testMetadata . only ) {
141
+ nativeLibrary . fit ( testName , testFunction as never , testSettings . testTimeout ) ;
142
+ } else {
143
+ nativeLibrary . it ( testName , testFunction as never , testSettings . testTimeout ) ;
144
+ }
145
+ } ) ;
78
146
} ) ;
79
147
}
80
148
@@ -172,85 +240,64 @@ export {
172
240
173
241
type JasmineModule = {
174
242
/**
175
- * Run some shared setup once before all of the specs in the {@link describe} are run.
176
- *
177
- * _Note:_ Be careful, sharing the setup from a beforeAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail.
178
- * @name beforeAll
179
- * @since 2.1.0
180
- * @function
181
- * @global
182
- * @param {implementationCallback } [function] Function that contains the code to setup your specs.
183
- * @param {Int } [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeAll.
184
- * @see async
243
+ * Run some shared setup once before all of the specs in the describe are run.
244
+ * Note: Be careful, sharing the setup from a beforeAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail.
245
+ * @param action Function that contains the code to setup your specs.
246
+ * @param timeout Custom timeout for an async beforeAll.
185
247
*/
186
- beforeAll : ( fn : ( ) => void , timeout ?: number ) => void ;
248
+ beforeAll : ( action : ( ) => void , timeout ?: number ) => void ;
187
249
188
250
/**
189
- * Run some shared teardown once after all of the specs in the {@link describe} are run.
190
- *
191
- * _Note:_ Be careful, sharing the teardown from a afterAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail.
192
- * @name afterAll
193
- * @since 2.1.0
194
- * @function
195
- * @global
196
- * @param {implementationCallback } [function] Function that contains the code to teardown your specs.
197
- * @param {Int } [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterAll.
198
- * @see async
251
+ * Run some shared teardown once after all of the specs in the describe are run.
252
+ * Note: Be careful, sharing the teardown from a afterAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail.
253
+ * @param action Function that contains the code to teardown your specs.
254
+ * @param timeout Custom timeout for an async afterAll
199
255
*/
200
- afterAll : ( fn : ( ) => void , timeout ?: number ) => void ;
256
+ afterAll : ( action : ( ) => void , timeout ?: number ) => void ;
201
257
202
258
/**
203
259
* Create a group of specs (often called a suite).
204
- *
205
- * Calls to `describe` can be nested within other calls to compose your suite as a tree.
206
- * @name describe
207
- * @since 1.3.0
208
- * @function
209
- * @global
210
- * @param {String } description Textual description of the group
211
- * @param {Function } specDefinitions Function for Jasmine to invoke that will define inner suites and specs
260
+ * @param description Textual description of the group
261
+ * @param specDefinitions Function for Jasmine to invoke that will define inner suites a specs
212
262
*/
213
263
describe : ( description : string , specDefinitions : ( ) => void ) => void ;
214
264
215
265
/**
216
- * Run some shared setup before each of the specs in the {@link describe} in which it is called.
217
- * @name beforeEach
218
- * @since 1.3.0
219
- * @function
220
- * @global
221
- * @param {implementationCallback } [function] Function that contains the code to setup your specs.
222
- * @param {Int } [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeEach.
223
- * @see async
266
+ * Run some shared setup before each of the specs in the describe in which it is called.
267
+ * @param action Function that contains the code to setup your specs.
268
+ * @param timeout Custom timeout for an async beforeEach.
224
269
*/
225
- beforeEach : ( fn : ( ) => void , timeout ?: number ) => void ;
270
+ beforeEach : ( action : ( ) => void , timeout ?: number ) => void ;
226
271
227
272
/**
228
- * Run some shared teardown after each of the specs in the {@link describe} in which it is called.
229
- * @name afterEach
230
- * @since 1.3.0
231
- * @function
232
- * @global
233
- * @param {implementationCallback } [function] Function that contains the code to teardown your specs.
234
- * @param {Int } [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterEach.
235
- * @see async
273
+ * Run some shared teardown after each of the specs in the describe in which it is called.
274
+ * @param action Function that contains the code to teardown your specs.
275
+ * @param timeout Custom timeout for an async afterEach.
236
276
*/
237
- afterEach : ( fn : ( ) => void , timeout ?: number ) => void ;
277
+ afterEach : ( action : ( ) => void , timeout ?: number ) => void ;
238
278
239
279
/**
240
- * Define a single spec. A spec should contain one or more {@link expect|expectations} that test the state of the code.
241
- *
280
+ * Define a single spec. A spec should contain one or more expectations that test the state of the code.
242
281
* A spec whose expectations all succeed will be passing and a spec with any failures will fail.
243
- * The name `it` is a pronoun for the test target, not an abbreviation of anything. It makes the
244
- * spec more readable by connecting the function name `it` and the argument `description` as a
245
- * complete sentence.
246
- * @name it
247
- * @since 1.3.0
248
- * @function
249
- * @global
250
- * @param {String } description Textual description of what this spec is checking
251
- * @param {implementationCallback } [testFunction] Function that contains the code of your test. If not provided the test will be `pending`.
252
- * @param {Int } [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async spec.
253
- * @see async
282
+ * @param expectation Textual description of what this spec is checking
283
+ * @param assertion Function that contains the code of your test. If not provided the test will be pending.
284
+ * @param timeout Custom timeout for an async spec.
285
+ */
286
+ it : ( expectation : string , assertion ?: ( ) => void , timeout ?: number ) => void ;
287
+
288
+ /**
289
+ * A focused `it`. If suites or specs are focused, only those that are focused will be executed.
290
+ * @param expectation Textual description of what this spec is checking
291
+ * @param assertion Function that contains the code of your test. If not provided the test will be pending.
292
+ * @param timeout Custom timeout for an async spec.
293
+ */
294
+ fit : ( expectation : string , assertion ?: ( ) => void , timeout ?: number ) => void ;
295
+
296
+ /**
297
+ * A temporarily disabled `it`. The spec will report as pending and will not be executed.
298
+ * @param expectation Textual description of what this spec is checking
299
+ * @param assertion Function that contains the code of your test. If not provided the test will be pending.
300
+ * @param timeout Custom timeout for an async spec.
254
301
*/
255
- it : ( description : string , testFunction ?: ( ) => void , timeout ?: number ) => void ;
302
+ xit : ( expectation : string , assertion ?: ( ) => void , timeout ?: number ) => void ;
256
303
} ;
0 commit comments