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
110// @ts -expect-error - jasmine-core does not have a declaration file
211import jasmineModule from 'jasmine-core' ;
312import 'reflect-metadata' ;
@@ -13,6 +22,7 @@ import type { ConfigureFn, Method, MethodNames, ParameterlessCtor, TestFn } from
1322const nativeLibrary : JasmineModule = jasmineModule . noGlobals ( ) ;
1423const BaseTest = ServiceLocator . resolveType ( BellatrixTest ) ;
1524const testSettings = BellatrixSettings . get ( ) . frameworkSettings . testSettings ;
25+ const testFilters = JSON . parse ( process . env . BELLATRIX_TEST_FILTER ! ) ;
1626
1727function getSymbolMethods < T extends BellatrixTest > ( type : ParameterlessCtor < T > ) {
1828 return {
@@ -46,6 +56,66 @@ export function SuiteDecorator<T extends BellatrixTest>(target: ParameterlessCto
4656 const testMethods = Object . getOwnPropertyNames ( testClass ) . filter ( method => typeof testClass [ method ] === 'function' && Reflect . hasMetadata ( Symbols . TEST , testClass [ method ] ) ) ;
4757 const title = target . name ; // or passed as @Suite ('title') or similar
4858
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+
49119 nativeLibrary . describe ( title , ( ) => {
50120 nativeLibrary . beforeAll ( async ( ) => await testClassSymbolMethods . beforeAll . call ( testClassInstance ) ) ;
51121
@@ -63,18 +133,16 @@ export function SuiteDecorator<T extends BellatrixTest>(target: ParameterlessCto
63133
64134 nativeLibrary . afterAll ( async ( ) => await testClassSymbolMethods . afterAll . call ( testClassInstance ) ) ;
65135
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+ } ) ;
78146 } ) ;
79147}
80148
@@ -172,85 +240,64 @@ export {
172240
173241type JasmineModule = {
174242 /**
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.
185247 */
186- beforeAll : ( fn : ( ) => void , timeout ?: number ) => void ;
248+ beforeAll : ( action : ( ) => void , timeout ?: number ) => void ;
187249
188250 /**
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
199255 */
200- afterAll : ( fn : ( ) => void , timeout ?: number ) => void ;
256+ afterAll : ( action : ( ) => void , timeout ?: number ) => void ;
201257
202258 /**
203259 * 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
212262 */
213263 describe : ( description : string , specDefinitions : ( ) => void ) => void ;
214264
215265 /**
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.
224269 */
225- beforeEach : ( fn : ( ) => void , timeout ?: number ) => void ;
270+ beforeEach : ( action : ( ) => void , timeout ?: number ) => void ;
226271
227272 /**
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.
236276 */
237- afterEach : ( fn : ( ) => void , timeout ?: number ) => void ;
277+ afterEach : ( action : ( ) => void , timeout ?: number ) => void ;
238278
239279 /**
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.
242281 * 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.
254301 */
255- it : ( description : string , testFunction ?: ( ) => void , timeout ?: number ) => void ;
302+ xit : ( expectation : string , assertion ?: ( ) => void , timeout ?: number ) => void ;
256303} ;
0 commit comments