Skip to content

Commit d299eda

Browse files
committed
WIP
1 parent e944fa1 commit d299eda

File tree

1 file changed

+361
-0
lines changed

1 file changed

+361
-0
lines changed

wdio.conf.ts

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
import path from 'node:path';
2+
import fs from 'node:fs';
3+
4+
const isAndroid = process.env.PLATFORM === 'android';
5+
6+
export const config: WebdriverIO.Config = {
7+
//
8+
// ====================
9+
// Runner Configuration
10+
// ====================
11+
// WebdriverIO supports running e2e tests as well as unit and component tests.
12+
runner: 'local',
13+
tsConfigPath: './tsconfig.json',
14+
15+
port: 4723,
16+
//
17+
// ==================
18+
// Specify Test Files
19+
// ==================
20+
// Define which test specs should run. The pattern is relative to the directory
21+
// of the configuration file being run.
22+
//
23+
// The specs are defined as an array of spec files (optionally using wildcards
24+
// that will be expanded). The test for each spec file will be run in a separate
25+
// worker process. In order to have a group of spec files run in the same worker
26+
// process simply enclose them in an array within the specs array.
27+
//
28+
// The path of the spec files will be resolved relative from the directory of
29+
// of the config file unless it's absolute.
30+
//
31+
// Spec in [] will be run in a separate worker process.
32+
// Running all specs sequentially for now.
33+
specs: [['./test/specs/**/*.ts']],
34+
// Patterns to exclude.
35+
exclude: [
36+
// 'path/to/excluded/files'
37+
],
38+
//
39+
// ============
40+
// Capabilities
41+
// ============
42+
// Define your capabilities here. WebdriverIO can run multiple capabilities at the same
43+
// time. Depending on the number of capabilities, WebdriverIO launches several test
44+
// sessions. Within your capabilities you can overwrite the spec and exclude options in
45+
// order to group specific specs to a specific capability.
46+
//
47+
// First, you can define how many instances should be started at the same time. Let's
48+
// say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have
49+
// set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec
50+
// files and you set maxInstances to 10, all spec files will get tested at the same time
51+
// and 30 processes will get spawned. The property handles how many capabilities
52+
// from the same test should run tests.
53+
//
54+
maxInstances: 10,
55+
//
56+
// If you have trouble getting all important capabilities together, check out the
57+
// Sauce Labs platform configurator - a great tool to configure your capabilities:
58+
// https://saucelabs.com/platform/platform-configurator
59+
//
60+
capabilities: [
61+
isAndroid
62+
? {
63+
platformName: 'Android',
64+
'appium:automationName': 'UiAutomator2',
65+
'appium:deviceName': 'Pixel_6',
66+
'appium:platformVersion': '13.0',
67+
'appium:app': path.join(__dirname, 'aut', 'bitkit_e2e.apk'),
68+
// 'appium:app': path.join(__dirname, 'aut', 'bitkit_v1.1.2.apk'),
69+
'appium:autoGrantPermissions': true,
70+
}
71+
: {
72+
platformName: 'iOS',
73+
'appium:automationName': 'XCUITest',
74+
'appium:deviceName': 'iPhone 16',
75+
'appium:platformVersion': '18.5',
76+
'appium:app': path.join(__dirname, 'aut', 'bitkit.app'),
77+
'appium:autoAcceptAlerts': true,
78+
'appium:udid': 'D1CE9A39-FD24-4854-975C-2CA4A6D41565',
79+
'appium:newCommandTimeout': 300,
80+
'appium:commandTimeouts': {"implicit": 30000},
81+
'appium:launchTimeout': 300000,
82+
'appium:deviceReadyTimeout': 300000,
83+
'appium:wdaLaunchTimeout': 300000,
84+
'appium:wdaConnectionTimeout': 300000,
85+
'appium:useNewWDA': true,
86+
'appium:autoLaunch': false,
87+
'appium:noReset': true,
88+
'appium:fullReset': false,
89+
},
90+
],
91+
92+
//
93+
// ===================
94+
// Test Configurations
95+
// ===================
96+
// Define all options that are relevant for the WebdriverIO instance here
97+
//
98+
// Level of logging verbosity: trace | debug | info | warn | error | silent
99+
logLevel: 'warn',
100+
//
101+
// Set specific log levels per logger
102+
// loggers:
103+
// - webdriver, webdriverio
104+
// - @wdio/browserstack-service, @wdio/lighthouse-service, @wdio/sauce-service
105+
// - @wdio/mocha-framework, @wdio/jasmine-framework
106+
// - @wdio/local-runner
107+
// - @wdio/sumologic-reporter
108+
// - @wdio/cli, @wdio/config, @wdio/utils
109+
// Level of logging verbosity: trace | debug | info | warn | error | silent
110+
// logLevels: {
111+
// webdriver: 'info',
112+
// '@wdio/appium-service': 'info'
113+
// },
114+
//
115+
// If you only want to run your tests until a specific amount of tests have failed use
116+
// bail (default is 0 - don't bail, run all tests).
117+
bail: 0,
118+
//
119+
// Set a base URL in order to shorten url command calls. If your `url` parameter starts
120+
// with `/`, the base url gets prepended, not including the path portion of your baseUrl.
121+
// If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url
122+
// gets prepended directly.
123+
// baseUrl: 'http://localhost:8080',
124+
//
125+
// Default timeout for all waitFor* commands.
126+
waitforTimeout: 30000,
127+
//
128+
// Default timeout in milliseconds for request
129+
// if browser driver or grid doesn't send response
130+
connectionRetryTimeout: 120000,
131+
//
132+
// Default request retries count
133+
connectionRetryCount: 3,
134+
//
135+
// Test runner services
136+
// Services take over a specific job you don't want to take care of. They enhance
137+
// your test setup with almost no effort. Unlike plugins, they don't add new
138+
// commands. Instead, they hook themselves up into the test process.
139+
services: ['appium'],
140+
141+
// Framework you want to run your specs with.
142+
// The following are supported: Mocha, Jasmine, and Cucumber
143+
// see also: https://webdriver.io/docs/frameworks
144+
//
145+
// Make sure you have the wdio adapter package for the specific framework installed
146+
// before running any tests.
147+
framework: 'mocha',
148+
149+
//
150+
// The number of times to retry the entire specfile when it fails as a whole
151+
// specFileRetries: 1,
152+
//
153+
// Delay in seconds between the spec file retry attempts
154+
// specFileRetriesDelay: 0,
155+
//
156+
// Whether or not retried spec files should be retried immediately or deferred to the end of the queue
157+
// specFileRetriesDeferred: false,
158+
//
159+
// Test reporter for stdout.
160+
// The only one supported by default is 'dot'
161+
// see also: https://webdriver.io/docs/dot-reporter
162+
reporters: ['spec'],
163+
164+
// Options to be passed to Mocha.
165+
// See the full list at http://mochajs.org/
166+
mochaOpts: {
167+
ui: 'bdd',
168+
timeout: 10 * 60 * 1000, // 10 minutes
169+
},
170+
171+
//
172+
// =====
173+
// Hooks
174+
// =====
175+
// WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance
176+
// it and to build services around it. You can either apply a single function or an array of
177+
// methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got
178+
// resolved to continue.
179+
/**
180+
* Gets executed once before all workers get launched.
181+
* @param {object} config wdio configuration object
182+
* @param {Array.<Object>} capabilities list of capabilities details
183+
*/
184+
// onPrepare: function (config, capabilities) {
185+
// },
186+
/**
187+
* Gets executed before a worker process is spawned and can be used to initialize specific service
188+
* for that worker as well as modify runtime environments in an async fashion.
189+
* @param {string} cid capability id (e.g 0-0)
190+
* @param {object} caps object containing capabilities for session that will be spawn in the worker
191+
* @param {object} specs specs to be run in the worker process
192+
* @param {object} args object that will be merged with the main configuration once worker is initialized
193+
* @param {object} execArgv list of string arguments passed to the worker process
194+
*/
195+
// onWorkerStart: function (cid, caps, specs, args, execArgv) {
196+
// },
197+
/**
198+
* Gets executed just after a worker process has exited.
199+
* @param {string} cid capability id (e.g 0-0)
200+
* @param {number} exitCode 0 - success, 1 - fail
201+
* @param {object} specs specs to be run in the worker process
202+
* @param {number} retries number of retries used
203+
*/
204+
// onWorkerEnd: function (cid, exitCode, specs, retries) {
205+
// },
206+
/**
207+
* Gets executed just before initialising the webdriver session and test framework. It allows you
208+
* to manipulate configurations depending on the capability or spec.
209+
* @param {object} config wdio configuration object
210+
* @param {Array.<Object>} capabilities list of capabilities details
211+
* @param {Array.<String>} specs List of spec file paths that are to be run
212+
* @param {string} cid worker id (e.g. 0-0)
213+
*/
214+
// beforeSession: function (config, capabilities, specs, cid) {
215+
// },
216+
/**
217+
* Gets executed before test execution begins. At this point you can access to all global
218+
* variables like `browser`. It is the perfect place to define custom commands.
219+
* @param {Array.<Object>} capabilities list of capabilities details
220+
* @param {Array.<String>} specs List of spec file paths that are to be run
221+
* @param {object} browser instance of created browser/device session
222+
*/
223+
// before: function (capabilities, specs) {
224+
// },
225+
/**
226+
* Runs before a WebdriverIO command gets executed.
227+
* @param {string} commandName hook command name
228+
* @param {Array} args arguments that command would receive
229+
*/
230+
// beforeCommand: function (commandName, args) {
231+
// },
232+
/**
233+
* Hook that gets executed before the suite starts
234+
* @param {object} suite suite details
235+
*/
236+
// beforeSuite: function (suite) {
237+
// },
238+
/**
239+
* Function to be executed before a test (in Mocha/Jasmine) starts.
240+
*/
241+
// beforeTest: function (test, context) {
242+
// },
243+
/**
244+
* Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling
245+
* beforeEach in Mocha)
246+
*/
247+
// beforeHook: function (test, context, hookName) {
248+
// },
249+
/**
250+
* Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling
251+
* afterEach in Mocha)
252+
*/
253+
// afterHook: function (test, context, { error, result, duration, passed, retries }, hookName) {
254+
// },
255+
/**
256+
* Function to be executed after a test (in Mocha/Jasmine only)
257+
* @param {object} test test object
258+
* @param {object} context scope object the test was executed with
259+
* @param {Error} result.error error object in case the test fails, otherwise `undefined`
260+
* @param {*} result.result return object of test function
261+
* @param {number} result.duration duration of test
262+
* @param {boolean} result.passed true if test has passed, otherwise false
263+
* @param {object} result.retries information about spec related retries, e.g. `{ attempts: 0, limit: 0 }`
264+
*/
265+
// afterTest: function(test, context, { error, result, duration, passed, retries }) {
266+
// },
267+
268+
/**
269+
* Hook that gets executed after the suite has ended
270+
* @param {object} suite suite details
271+
*/
272+
// afterSuite: function (suite) {
273+
// },
274+
/**
275+
* Runs after a WebdriverIO command gets executed
276+
* @param {string} commandName hook command name
277+
* @param {Array} args arguments that command would receive
278+
* @param {number} result 0 - command success, 1 - command error
279+
* @param {object} error error object if any
280+
*/
281+
// afterCommand: function (commandName, args, result, error) {
282+
// },
283+
/**
284+
* Gets executed after all tests are done. You still have access to all global variables from
285+
* the test.
286+
* @param {number} result 0 - test pass, 1 - test fail
287+
* @param {Array.<Object>} capabilities list of capabilities details
288+
* @param {Array.<String>} specs List of spec file paths that ran
289+
*/
290+
// after: function (result, capabilities, specs) {
291+
// },
292+
/**
293+
* Gets executed right after terminating the webdriver session.
294+
* @param {object} config wdio configuration object
295+
* @param {Array.<Object>} capabilities list of capabilities details
296+
* @param {Array.<String>} specs List of spec file paths that ran
297+
*/
298+
// afterSession: function (config, capabilities, specs) {
299+
// },
300+
/**
301+
* Gets executed after all workers got shut down and the process is about to exit. An error
302+
* thrown in the onComplete hook will result in the test run failing.
303+
* @param {object} exitCode 0 - success, 1 - fail
304+
* @param {object} config wdio configuration object
305+
* @param {Array.<Object>} capabilities list of capabilities details
306+
* @param {<Object>} results object containing test results
307+
*/
308+
// onComplete: function(exitCode, config, capabilities, results) {
309+
// },
310+
/**
311+
* Gets executed when a refresh happens.
312+
* @param {string} oldSessionId session ID of the old session
313+
* @param {string} newSessionId session ID of the new session
314+
*/
315+
// onReload: function(oldSessionId, newSessionId) {
316+
// }
317+
/**
318+
* Hook that gets executed before a WebdriverIO assertion happens.
319+
* @param {object} params information about the assertion to be executed
320+
*/
321+
// beforeAssertion: function(params) {
322+
// }
323+
/**
324+
* Hook that gets executed after a WebdriverIO assertion happened.
325+
* @param {object} params information about the assertion that was executed, including its results
326+
*/
327+
// afterAssertion: function(params) {
328+
// }
329+
beforeTest: async function (test) {
330+
if (process.env.RECORD_VIDEO === 'true') {
331+
await driver.startRecordingScreen();
332+
}
333+
console.log(`🧪 Start: ${test.parent} - ${test.title}`);
334+
},
335+
336+
afterTest: async function (test, _context, { error }) {
337+
if (!error) return; // Skip artifacts if test passed
338+
339+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
340+
const testNameRaw = `${test.parent || 'unknown'}_${test.title}`;
341+
const testName = testNameRaw.replace(/\s+/g, '_').replace(/[^\w-]/g, '');
342+
const testDir = path.join(__dirname, 'artifacts', testName);
343+
344+
// Ensure per-test directory exists
345+
fs.mkdirSync(testDir, { recursive: true });
346+
347+
// Save screenshot
348+
const screenshotPath = path.join(testDir, `${testName}-${timestamp}.png`);
349+
const screenshot = await driver.takeScreenshot();
350+
fs.writeFileSync(screenshotPath, screenshot, 'base64');
351+
console.log(`📸 Saved screenshot: ${screenshotPath}`);
352+
353+
// Save video if recording was enabled
354+
if (process.env.RECORD_VIDEO === 'true') {
355+
const videoBase64 = await driver.stopRecordingScreen();
356+
const videoPath = path.join(testDir, `${testName}-${timestamp}.mp4`);
357+
fs.writeFileSync(videoPath, videoBase64, 'base64');
358+
console.log(`🎥 Saved test video: ${videoPath}`);
359+
}
360+
},
361+
};

0 commit comments

Comments
 (0)