11import AllureReporter from '@wdio/allure-reporter' ;
22import { multiremotebrowser } from '@wdio/globals' ;
33import { Buffer } from 'buffer' ;
4+ import { glob } from 'glob' ;
45import path from 'node:path' ;
56import process from 'node:process' ;
67import pretty from 'pretty' ;
78
8- import { getTestProperties } from './helpers/TestProperties' ;
9+ import { getTestProperties , loadTestFiles } from './helpers/TestProperties' ;
910import WebhookProxy from './helpers/WebhookProxy' ;
1011import { getLogs , initLogger , logInfo } from './helpers/browserLogger' ;
1112import { IContext } from './helpers/types' ;
@@ -55,15 +56,80 @@ const chromePreferences = {
5556 'intl.accept_languages' : 'en-US'
5657} ;
5758
59+ const specs = [
60+ 'specs/**/*.spec.ts'
61+ ] ;
62+
63+ /**
64+ * Analyzes test files at config construction time to determine browser requirements
65+ * and generate capabilities with appropriate exclusions.
66+ */
67+ function generateCapabilitiesFromSpecs ( ) : Record < string , any > {
68+ const allSpecFiles : string [ ] = [ ] ;
69+ const browsers = [ 'p1' , 'p2' , 'p3' , 'p4' ] ;
70+
71+ for ( const pattern of specs ) {
72+ const matches = glob . sync ( pattern , { cwd : path . join ( __dirname ) } ) ;
73+
74+ allSpecFiles . push ( ...matches . map ( f => path . resolve ( __dirname , f ) ) ) ;
75+ }
76+
77+ // Load test files to populate the testProperties registry
78+ loadTestFiles ( allSpecFiles ) ;
79+
80+ // Import TestProperties to access the populated registry
81+ const { testProperties } = require ( './helpers/TestProperties' ) ;
82+
83+ // Determine which browsers need which exclusions
84+ const browserExclusions : Record < string , Set < string > > = {
85+ p1 : new Set ( ) ,
86+ p2 : new Set ( ) ,
87+ p3 : new Set ( ) ,
88+ p4 : new Set ( )
89+ } ;
90+
91+ for ( const file of allSpecFiles ) {
92+ const props = testProperties [ file ] ;
93+ const relativeFile = path . relative ( __dirname , file ) ;
94+
95+ // If a test doesn't use a particular browser, add it to exclusions for that browser
96+ if ( props ?. usesBrowsers ) {
97+ browsers . forEach ( browser => {
98+ if ( ! props . usesBrowsers ! . includes ( browser ) ) {
99+ browserExclusions [ browser ] . add ( relativeFile ) ;
100+ }
101+ } ) ;
102+ }
103+ }
104+
105+ return Object . fromEntries (
106+ browsers . map ( browser => [
107+ browser ,
108+ {
109+ capabilities : {
110+ browserName : 'chrome' ,
111+ ...( browser === 'p1' && process . env . BROWSER_CHROME_BETA ? { browserVersion : 'beta' } : { } ) ,
112+ 'goog:chromeOptions' : {
113+ args : chromeArgs ,
114+ prefs : chromePreferences
115+ } ,
116+ 'wdio:exclude' : Array . from ( browserExclusions [ browser ] || [ ] )
117+ }
118+ }
119+ ] )
120+ ) ;
121+ }
122+
123+ const capabilities = generateCapabilitiesFromSpecs ( ) ;
124+
58125const TEST_RESULTS_DIR = 'test-results' ;
59126
60127export const config : WebdriverIO . MultiremoteConfig = {
61128
62129 runner : 'local' ,
63130
64- specs : [
65- 'specs/**/*.spec.ts'
66- ] ,
131+ specs,
132+
67133 maxInstances : parseInt ( process . env . MAX_INSTANCES || '1' , 10 ) , // if changing check onWorkerStart logic
68134
69135 baseUrl : process . env . BASE_URL || 'https://alpha.jitsi.net/torture/' ,
@@ -85,61 +151,7 @@ export const config: WebdriverIO.MultiremoteConfig = {
85151 timeout : 180_000
86152 } ,
87153
88- capabilities : {
89- // participant1
90- p1 : {
91- capabilities : {
92- browserName : 'chrome' ,
93- browserVersion : process . env . BROWSER_CHROME_BETA ? 'beta' : undefined ,
94- 'goog:chromeOptions' : {
95- args : chromeArgs ,
96- prefs : chromePreferences
97- }
98- }
99- } ,
100- // participant2
101- p2 : {
102- capabilities : {
103- browserName : 'chrome' ,
104- 'goog:chromeOptions' : {
105- args : chromeArgs ,
106- prefs : chromePreferences
107- } ,
108- 'wdio:exclude' : [
109- 'specs/alone/**'
110- ]
111- }
112- } ,
113- // participant3
114- p3 : {
115- capabilities : {
116- browserName : 'chrome' ,
117- 'goog:chromeOptions' : {
118- args : chromeArgs ,
119- prefs : chromePreferences
120- } ,
121- 'wdio:exclude' : [
122- 'specs/alone/**' ,
123- 'specs/2way/**'
124- ]
125- }
126- } ,
127- // participant4
128- p4 : {
129- capabilities : {
130- browserName : 'chrome' ,
131- 'goog:chromeOptions' : {
132- args : chromeArgs ,
133- prefs : chromePreferences
134- } ,
135- 'wdio:exclude' : [
136- 'specs/alone/**' ,
137- 'specs/2way/**' ,
138- 'specs/3way/**'
139- ]
140- }
141- }
142- } ,
154+ capabilities,
143155
144156 // Level of logging verbosity: trace | debug | info | warn | error | silent
145157 logLevel : 'trace' ,
@@ -176,12 +188,12 @@ export const config: WebdriverIO.MultiremoteConfig = {
176188 *
177189 * @returns {Promise<void> }
178190 */
179- async before ( cid , _ , specs ) {
180- if ( specs . length !== 1 ) {
191+ async before ( cid , _ , files ) {
192+ if ( files . length !== 1 ) {
181193 console . warn ( 'We expect to run a single suite, but got more than one' ) ;
182194 }
183195
184- const testFilePath = specs [ 0 ] . replace ( / ^ f i l e : \/ \/ / , '' ) ;
196+ const testFilePath = files [ 0 ] . replace ( / ^ f i l e : \/ \/ / , '' ) ;
185197 const testName = path . relative ( 'tests/specs' , testFilePath )
186198 . replace ( / .s p e c .t s $ / , '' )
187199 . replace ( / \/ / g, '-' ) ;
@@ -267,7 +279,7 @@ export const config: WebdriverIO.MultiremoteConfig = {
267279 ctx ?. keepAlive ?. forEach ( clearInterval ) ;
268280 } ,
269281
270- beforeSession ( c , capabilities , specs , cid ) {
282+ beforeSession ( c , capabilities_ , specs_ , cid ) {
271283 const originalBefore = c . before ;
272284
273285 if ( ! originalBefore || ! Array . isArray ( originalBefore ) || originalBefore . length !== 1 ) {
0 commit comments