diff --git a/.github/workflows/cross-browser-testing-android.yml b/.github/workflows/cross-browser-testing-android.yml new file mode 100644 index 000000000..a3e1da209 --- /dev/null +++ b/.github/workflows/cross-browser-testing-android.yml @@ -0,0 +1,39 @@ +name: 'BrowserStack Android Mobile Test' +on: [push, pull_request, workflow_dispatch] + +jobs: + browserstack-android-test: + name: 'BrowserStack Android Mobile Test' + runs-on: ubuntu-latest + steps: + - name: 'BrowserStack Env Setup' + uses: browserstack/github-actions/setup-env@master + with: + username: ${{ secrets.BROWSERSTACK_USERNAME }} + access-key: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} + + - name: 'BrowserStack Local Tunnel Setup' + uses: browserstack/github-actions/setup-local@master + with: + local-testing: start + local-identifier: random + + - name: 'Checkout the repository' + uses: actions/checkout@v3 + + - name: 'Run NPM CI' + run: npm ci + + - name: Run Build IIFE + run: npm run build:iife + + - name: 'Run NPM build test bundle' + run: npm run build:test-bundle + + - name: 'Run Browserstack Android Mobile Tests' + run: npm run test:browserstack-android + + - name: 'BrowserStackLocal Stop' + uses: browserstack/github-actions/setup-local@master + with: + local-testing: stop diff --git a/.github/workflows/cross-browser-testing-iOS.yml b/.github/workflows/cross-browser-testing-iOS.yml new file mode 100644 index 000000000..a21596f8d --- /dev/null +++ b/.github/workflows/cross-browser-testing-iOS.yml @@ -0,0 +1,39 @@ +name: 'BrowserStack iOS Mobile Test' +on: [push, pull_request, workflow_dispatch] + +jobs: + browserstack-iOS-test: + name: 'BrowserStack iOS Mobile Test' + runs-on: ubuntu-latest + steps: + - name: 'BrowserStack Env Setup' + uses: browserstack/github-actions/setup-env@master + with: + username: ${{ secrets.BROWSERSTACK_USERNAME }} + access-key: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} + + - name: 'BrowserStack Local Tunnel Setup' + uses: browserstack/github-actions/setup-local@master + with: + local-testing: start + local-identifier: random + + - name: 'Checkout the repository' + uses: actions/checkout@v3 + + - name: 'Run NPM CI' + run: npm ci + + - name: Run Build IIFE + run: npm run build:iife + + - name: 'Run NPM build test bundle' + run: npm run build:test-bundle + + - name: 'Run Browserstack iOS Mobile Tests' + run: npm run test:browserstack-iOS + + - name: 'BrowserStackLocal Stop' + uses: browserstack/github-actions/setup-local@master + with: + local-testing: stop diff --git a/package.json b/package.json index c293e2fd9..c83c3ffd3 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,10 @@ "test": "npm run build && npm run build:test-bundle && cross-env DEBUG=false karma start test/karma.config.js", "test:browserstack": "karma start test/cross-browser-testing/browserstack.karma.config.js", "test:browserstack:debug": "cross-env DEBUG=true karma start test/cross-browser-testing/browserstack.karma.config.js", + "test:browserstack-android": "karma start test/cross-browser-testing/browserstack.karma.android.config.js", + "test:browserstack-android:debug": "cross-env DEBUG=true karma start test/cross-browser-testing/browserstack.karma.android.config.js", + "test:browserstack-iOS": "karma start test/cross-browser-testing/browserstack.karma.iOS.config.js", + "test:browserstack-iOS:debug": "cross-env DEBUG=true karma start test/cross-browser-testing/browserstack.karma.iOS.config.js", "test:debug": "cross-env DEBUG=true karma start test/karma.config.js", "test:stub": "cross-env TESTTYPE=stub ENVIRONMENT=prod rollup --config rollup.test.config.js && karma start test/stub/karma.stub.config.js", "test:integrations": "npm run test:requirejs && npm run test:integrations:cjs && npm run test:integrations:module", diff --git a/test/cross-browser-testing/browserstack.karma.android.config.js b/test/cross-browser-testing/browserstack.karma.android.config.js new file mode 100644 index 000000000..10ace82c9 --- /dev/null +++ b/test/cross-browser-testing/browserstack.karma.android.config.js @@ -0,0 +1,147 @@ +const { DEBUG } = process.env; + +const files = [ + '../lib/geomock.js', + '../../dist/mparticle.js', + '../test-bundle.js', +]; + +let captureConsole = false; +let browserConsoleLogOptions = {}; + +if (DEBUG === 'true') { + browserConsoleLogOptions = { + level: 'log', + format: '%b %T: %m', + terminal: true, + }; + captureConsole = true; +} else { + browserConsoleLogOptions = { + terminal: false, + }; +} + +const customLaunchers = { + // Android 16 - all browsers + bs_android_16_chrome: { + base: 'BrowserStack', + device: 'Google Pixel 10 Pro', + os: 'android', + os_version: '16.0', + real_mobile: true, + browser: 'chrome' + }, + bs_android_16_firefox: { + base: 'BrowserStack', + device: 'Google Pixel 10', + os: 'android', + os_version: '16.0', + real_mobile: true, + browser: 'firefox' + }, + bs_android_16_opera: { + base: 'BrowserStack', + device: 'Google Pixel 10 Pro', + os: 'android', + os_version: '16.0', + real_mobile: true, + browser: 'opera' + }, + bs_android_16_samsung: { + base: 'BrowserStack', + device: 'Google Pixel 10 Pro XL', + os: 'android', + os_version: '16.0', + real_mobile: true, + browser: 'samsung' + }, + + // Android 15 - all browsers + bs_android_15_chrome: { + base: 'BrowserStack', + device: 'Samsung Galaxy S25', + os: 'android', + os_version: '15.0', + real_mobile: true, + browser: 'chrome' + }, + bs_android_15_firefox: { + base: 'BrowserStack', + device: 'Samsung Galaxy Tab S10 Plus', + os: 'android', + os_version: '15.0', + real_mobile: true, + browser: 'firefox' + }, + bs_android_15_opera: { + base: 'BrowserStack', + device: 'Google Pixel 9 Pro', + os: 'android', + os_version: '15.0', + real_mobile: true, + browser: 'opera' + }, + bs_android_15_samsung: { + base: 'BrowserStack', + device: 'Samsung Galaxy S25 Ultra', + os: 'android', + os_version: '15.0', + real_mobile: true, + browser: 'samsung' + }, + + // Android 14 - chrome + bs_android_14_chrome: { + base: 'BrowserStack', + device: 'Samsung Galaxy S24', + os: 'android', + os_version: '14.0', + real_mobile: true, + browser: 'chrome' + }, + + // Android 13 - chrome + bs_android_13_chrome: { + base: 'BrowserStack', + device: 'Samsung Galaxy S23 Ultra', + os: 'android', + os_version: '13.0', + real_mobile: true, + browser: 'chrome' + }, +}; + +module.exports = function(config) { + config.set({ + browserStack: { + username: process.env.BS_USERNAME, + accessKey: process.env.BS_ACCESS_KEY, + local: true, + }, + autoWatch: false, + customLaunchers, + browsers: Object.keys(customLaunchers), + frameworks: ['mocha', 'should'], + files, + reporters: ['progress', 'junit'], + colors: true, + singleRun: true, + debug: true, + logLevel: config.LOG_INFO, + browserConsoleLogOptions, + client: { + captureConsole, + mocha: { + timeout: 10000 + } + }, + junitReporter: { + outputDir: 'reports/', + outputFile: 'test-karma-mobile.xml', + }, + browserDisconnectTimeout: 50000, + browserDisconnectTolerance: 5, + concurrency: 5, + }); +}; diff --git a/test/cross-browser-testing/browserstack.karma.iOS.config.js b/test/cross-browser-testing/browserstack.karma.iOS.config.js new file mode 100644 index 000000000..c98c08c94 --- /dev/null +++ b/test/cross-browser-testing/browserstack.karma.iOS.config.js @@ -0,0 +1,131 @@ +const { DEBUG } = process.env; + +const files = [ + '../lib/geomock.js', + '../../dist/mparticle.js', + '../test-bundle.js', +]; + +let captureConsole = false; +let browserConsoleLogOptions = {}; + +if (DEBUG === 'true') { + browserConsoleLogOptions = { + level: 'log', + format: '%b %T: %m', + terminal: true, + }; + captureConsole = true; +} else { + browserConsoleLogOptions = { + terminal: false, + }; +} + +const customLaunchers = { + // iOS 26 - chrome, firefox, safari + bs_ios_26_safari: { + base: 'BrowserStack', + device: 'iPhone 17 Pro', + os: 'ios', + os_version: '26', + real_mobile: true, + browser: 'safari' + }, + bs_ios_26_chrome: { + base: 'BrowserStack', + device: 'iPad Air 5', + os: 'ios', + os_version: '26', + real_mobile: true, + browser: 'chrome' + }, + bs_ios_26_firefox: { + base: 'BrowserStack', + device: 'iPhone Air', + os: 'ios', + os_version: '26', + real_mobile: true, + browser: 'firefox' + }, + + // iOS 18 - chrome, firefox, safari + bs_ios_18_safari: { + base: 'BrowserStack', + device: 'iPhone 16e', + os: 'ios', + os_version: '18', + real_mobile: true, + browser: 'safari' + }, + bs_ios_18_chrome: { + base: 'BrowserStack', + device: 'iPad Pro 11 2021', + os: 'ios', + os_version: '18', + real_mobile: true, + browser: 'chrome' + }, + bs_ios_18_firefox: { + base: 'BrowserStack', + device: 'iPhone 14', + os: 'ios', + os_version: '18', + real_mobile: true, + browser: 'firefox' + }, + + // iOS 17 - chrome + bs_ios_17_chrome: { + base: 'BrowserStack', + device: 'iPhone 12', + os: 'ios', + os_version: '17', + real_mobile: true, + browser: 'chrome' + }, + + // iOS 16 - safari + bs_ios_16_safari: { + base: 'BrowserStack', + device: 'iPad 10th', + os: 'ios', + os_version: '16', + real_mobile: true, + browser: 'safari' + }, +}; + +module.exports = function(config) { + config.set({ + browserStack: { + username: process.env.BS_USERNAME, + accessKey: process.env.BS_ACCESS_KEY, + local: true, + }, + autoWatch: false, + customLaunchers, + browsers: Object.keys(customLaunchers), + frameworks: ['mocha', 'should'], + files, + reporters: ['progress', 'junit'], + colors: true, + singleRun: true, + debug: true, + logLevel: config.LOG_INFO, + browserConsoleLogOptions, + client: { + captureConsole, + mocha: { + timeout: 10000 + } + }, + junitReporter: { + outputDir: 'reports/', + outputFile: 'test-karma-mobile.xml', + }, + browserDisconnectTimeout: 50000, + browserDisconnectTolerance: 5, + concurrency: 5, + }); +};