SauceLabs hybrid app test automation session is not starting on iOS devices - ios

I'm trying to run the automation tests for hybrid app on SauceLabs (SL) on Android and iOS. For some strange reason when I start execution on SL with iOS devices I can only see device with a spinner that is trying to start a session and it is going in loop for more than 20 min (that is how much I gave tests time to timeout last time I tried). For android devices is working perfectly fine and it finishes test execution. Some input about tools and environment:
Test frameworks: Appium, WebdriverIO, Cucumber.
Language: JS
Selectors used in code (Page objects): HTML custom selectors for each button/input field etc, from ionic (hybrid) app
In order to be able to access those selectors, in appium configuration file for SL I put following ('appium:autoWebview': true) which is suggested when you are dealing with hybrid apps. Checked with other projects that are working too (project that are using saucelabs with appium), config file is written in good format.
Artifacts used: .ipa app build for iOS (built properly, I was able to use it in manual testing), .apk for Android (all good there too).
Is there anything I'm missing to configure on my side to be able to run iOS tests on SL by using frameworks and locator/selector strategy I mentioned above? Or is it maybe some bug on their side that I missed to find? I spent few days researching this issue and couldn't find anything helpful besides official documentation which (I think) I followed in good way.
I'm sharing 3 config files I have for this (1 shared config, 1 iOS and 1 for Android):
Shared config
const { generate } = require('multiple-cucumber-html-reporter');
const { removeSync } = require('fs-extra');
exports.config = {
// ====================
// Runner and framework
// Configuration
// ====================
runner: 'local',
framework: 'cucumber',
sync: false,
logLevel: 'trace',
deprecationWarnings: true,
outputDir: './test-report/output',
bail: 0,
baseUrl: 'http://the-internet.herokuapp.com',
waitforTimeout: 6000,
connectionRetryTimeout: 90000,
connectionRetryCount: 3,
specs: ['tests/features/**/*.feature'],
reporters: [
'spec',
[
'cucumberjs-json',
{
jsonFolder: '.tmp/json/',
language: 'en',
},
],
],
cucumberOpts: {
requireModule: ['#babel/register'],
backtrace: false,
compiler: [],
dryRun: false,
failFast: false,
format: ['pretty'],
colors: true,
snippets: true,
source: true,
profile: [],
strict: false,
tags: [],
timeout: 100000,
ignoreUndefinedDefinitions: false,
tagExpression: 'not #skip',
},
// ====================
// Appium Configuration
// ====================
services: ['appium'],
appium: {
// For options see
// https://github.com/webdriverio/webdriverio/tree/master/packages/wdio-appium-service
// If you need a logs from appium server, make log equal true.
log: false,
args: {
// For arguments see
// https://github.com/webdriverio/webdriverio/tree/master/packages/wdio-appium-service
},
command: 'appium',
},
port: 4723,
// ====================
// Some hooks
// ====================
/**
* Gets executed once before all workers get launched.
* #param {Object} config wdio configuration object
* #param {Array.<Object>} capabilities list of capabilities details
*/
onPrepare: function() {
// Remove the `.tmp/` folder that holds the json and report files
removeSync('.tmp/');
},
/**
* Gets executed after all workers have shut down and the process is about to exit.
* An error thrown in the `onComplete` hook will result in the test run failing.
* #param {Object} exitCode 0 - success, 1 - fail
* #param {Object} config wdio configuration object
* #param {Array.<Object>} capabilities list of capabilities details
* #param {<Object>} results object containing test results
*/
onComplete: () => {
// Generate the report when it all tests are done
generate({
// Required
// This part needs to be the same path where you store the JSON files
// default = '.tmp/json/'
jsonDir: '.tmp/json/',
reportPath: '.tmp/report/',
saveCollectedJSON: true,
});
},
//This code is responsible for taking the screenshot in case of error and attaching it to the report
afterStep(uri, feature, scenario) {
if (scenario.error) {
driver.takeScreenshot();
}
},
afterScenario() {
driver.reset();
},
afterSession() {
driver.closeApp();
},
};
iOS SL config (I put stars to API keys for purpose of privacy):
const { config } = require('../wdio.shared.conf');
// ============
// Specs
// ============
config.cucumberOpts.require = ['./tests/steps/**/app*.steps.js'];
// ============
// Capabilities
// ============
config.capabilities = [
{
deviceName: 'iPhone XR',
// The reference to the app
testobject_app_id: '1',
testobject_api_key: '00768686F013470CB81060**********',
// The name of the test for in the cloud
testobject_test_name: 'IOS run',
// Some default settings
platformName: 'iOS',
idleTimeout: 180,
maxInstances: 6,
// testobject_cache_device: true,
noReset: true,
orientation: 'PORTRAIT',
newCommandTimeout: 180,
phoneOnly: true,
tabletOnly: false,
autoWebview: true
},
];
// =========================
// Sauce RDC specific config
// =========================
config.services = ['sauce'];
config.region = 'eu';
// This port was defined in the `wdio.shared.conf.js`
delete config.port;
exports.config = config;
Android SL config:
const { config } = require('../wdio.shared.conf');
// ============
// Specs
// ============
config.cucumberOpts.require = ['./tests/steps/**/app*.steps.js'];
// ============
// Capabilities
// ============
config.capabilities = [
{
deviceName: 'Samsung Galaxy S9',
// The reference to the app
testobject_app_id: '1',
testobject_api_key: '42724CEF3061453C9F45B1**********',
// The name of the test for in the cloud
testobject_test_name: 'Android run',
// Some default settings
platformName: 'Android',
idleTimeout: 180,
maxInstances: 6,
testobject_cache_device: true,
noReset: true,
orientation: 'PORTRAIT',
newCommandTimeout: 180,
phoneOnly: true,
tabletOnly: false,
autoWebview: true
},
];
// =========================
// Sauce RDC specific config
// =========================
config.services = ['sauce'];
config.region = 'eu';
// This port was defined in the `wdio.shared.conf.js`
delete config.port;
exports.config = config;
Appium Desktop caps:
{
"platformName": "iOS",
"platformVersion": "13",
"deviceName": "iPhone 11 Pro",
"app": "path-to-ipa"
}

Related

How to get rid of the "#rollup/plugin-typescript: Rollup 'sourcemap' option must be set to generate source maps." warning?

I get this warning every time I build for production. When I build for production I disable source maps in the rollup output config.
output: [{ dir: "...", format: "...", sourcemap: isProd ? false : true }]
I use the same tsconfig for dev and production, tsconfig.json:
{
"compilerOptions": {
// Output
"target": "ESNext",
"module": "ESNEXT",
"sourceMap": true,
"jsx": "react",
"noEmit": true,
// Compile time code checking
"strict": true,
// Libraries
"lib": ["dom", "esnext"],
// Imports
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
},
"exclude": ["dist", "app"]
}
I understand that this is the reason for the warning from looking at the rollup plugin source code:
/**
* Validate that the `compilerOptions.sourceMap` option matches `outputOptions.sourcemap`.
* #param context Rollup plugin context used to emit warnings.
* #param compilerOptions Typescript compiler options.
* #param outputOptions Rollup output options.
* #param autoSetSourceMap True if the `compilerOptions.sourceMap` property was set to `true`
* by the plugin, not the user.
*/
function validateSourceMap(context, compilerOptions, outputOptions, autoSetSourceMap) {
if (compilerOptions.sourceMap && !outputOptions.sourcemap && !autoSetSourceMap) {
context.warn(`#rollup/plugin-typescript: Rollup 'sourcemap' option must be set to generate source maps.`);
}
else if (!compilerOptions.sourceMap && outputOptions.sourcemap) {
context.warn(`#rollup/plugin-typescript: Typescript 'sourceMap' compiler option must be set to generate source maps.`);
}
}
But I would prefer to not add the complexity of one tsconfig for dev and another for production.
What would be a good way to get rid of this warning?
In my case, I was using the official Svelte starter template, with TypeScript integration.
In my case, I didn't need to change my tsconfig from the default one extended by the template (which had "sourceMap": true,); I just needed to change the output.sourcemap setting in my rollup.config.js to make it consistent with the options I'd passed into the typescript() plugin:
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'src/main.ts',
output: {
// sourcemap: true, // <-- remove
sourcemap: !production,
format: 'iife',
name: 'app',
file: 'public/build/bundle.js'
},
plugins: [
svelte({
preprocess: sveltePreprocess({ sourceMap: !production }),
compilerOptions: {
dev: !production
}
}),
css({ output: 'bundle.css' }),
resolve({
browser: true,
dedupe: ['svelte']
}),
commonjs(),
typescript({
sourceMap: !production,
inlineSources: !production
}),
!production && serve(),
!production && livereload('public'),
production && terser()
],
watch: {
clearScreen: false
}
};
Use a base tsconfig and add only the options that are different to dev and prod versions, as reference see:
https://github.com/microsoft/TypeScript/issues/9876
https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends

Unit Testing JavaScript in ASP.NET MVC with Jasmine and Karma

I am writing a sample ASP .NET MVC application, which has karma and requirejs to test the scripts. I see below error Uncaught (in promise) Error: No tests were run.
I see below error in command prompt
Chrome 77.0.3865 (Windows 10.0.0): Executed 0 of 0 ERROR (0.012 secs / 0 secs)
Package.json
{
"name": "karmawebapp",
"version": "1.0.0",
"description": "test application for karma tests",
"main": "index.js",
"scripts": {
"test": "karma start"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.3",
"babel-preset-es2015": "^6.24.1",
"karma": "^4.3.0",
"karma-chrome-launcher": "^3.1.0",
"karma-qunit": "^4.0.0",
"karma-requirejs": "^1.1.0",
"protractor": "^5.4.2",
"qunit": "^2.9.3",
"requirejs": "^2.3.6"
}
}
My karma.conf.js
// Karma configuration
// Generated on Tue Oct 15 2019 13:51:47 GMT-0500 (Central Daylight Time)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['requirejs', 'qunit'],
// list of files / patterns to load in the browser
files: [
'test-main.js',
{ pattern: './Scripts/tests/*.specs.js', included: false }
],
// list of files / patterns to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}
My test-main.js
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
// If you require sub-dependencies of test files to be loaded as-is (requiring file extension)
// then do not normalize the paths
var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '');
allTestFiles.push(normalizedTestModule)
};
});
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: '/base',
// dynamically load all test files
deps: allTestFiles,
path: {
qunit: 'qunit',
jquery: 'jquery.3.3.1'
},
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
});
my test.specs.js
define(['qunit'], function (qunit) {
qunit.test("Second test", function (assert) {
assert.ok(true, "Passed!");
});
});
Use the debug set up to open devtools on the browser:
http://karma-runner.github.io/4.0/intro/troubleshooting.html
I was able to run these test cases. Looks whenever their is error in your specs file No tests were run message will come. You need make sure you specs file syntax is correct

Could not start Browser / Emulator error on Nightwatch with Browserstack and Ms Edge 17

I am using Nightwatch with BrowserStack to run a test suite on Ms Edge 17 and I am getting the following error in most builds.
Error retrieving a new session from the selenium server
Connection refused! Is selenium server started?
{
value: { message: 'Could not start Browser / Emulator' },
sessionId: '',
status: 13
}
We have exactly the same code running on chrome browser in BrowserStack without any problems.
This suite runs in parallel using workers. If I disable workers, then it passes, unfortunately we need to use parallel execution otherwise the suite would take too long.
I will post our config file below.
var seleniumJar = require('selenium-server-standalone-jar')
var nightwatchWorkers = parseInt(process.env.NIGHTWATCH_WORKER_THREADS) || 1
var chromeDriver = process.env.CHROME_DRIVER_PATH || './drivers/chromedriver'
var msEdgeDriverPath = process.env.MSEDGE_DRIVER_PATH || './drivers/MicrosoftWebDriver.exe'
var ie11DriverPath = process.env.MSIE11_DRIVER_PATH || './drivers/IEDriverServer.exe'
var localDockerPort = 4444
var browserStackPort = 80
var browserStackHost = 'hub-cloud.browserstack.com'
var browserStackScreenResolution = '1920x1200'
module.exports = {
src_folders: ['./tests'],
output_folder: './results',
live_output: true, //set to false so each thread will output the whole result of the test when it's done
silent: true,
custom_commands_path: './commands',
custom_assertions_path: './assertions',
page_objects_path: './pages',
test_workers: {
enabled: true,
workers: nightwatchWorkers
},
selenium: {
start_process: false,
server_path: seleniumJar.path,
log_path: './results',
port: localDockerPort,
cli_args: {
'webdriver.chrome.driver': chromeDriver,
'webdriver.edge.driver': msEdgeDriverPath,
'webdriver.ie.driver': ie11DriverPath
}
},
test_settings: {
default: {
launch_url: 'http://localhost',
selenium_host: '127.0.0.1',
selenium_port: localDockerPort,
silent: true,
disable_colors: false,
screenshots: {
enabled: true,
on_failure: true,
path: './results/screenshots'
},
desiredCapabilities: {
browserName: 'chrome',
resolution: browserStackScreenResolution,
javascriptEnabled: true,
acceptSslCerts: true,
elementScrollBehavior: 1,
project: 'megarepo',
build: process.env.BROWSERSTACK_BUILD_ID,
'browserstack.user': process.env.BROWSERSTACK_USER,
'browserstack.key': process.env.BROWSERSTACK_KEY
},
globals: require('./data/dev')
},
browserstack_msedge: {
selenium: {
port: browserStackPort
},
selenium_host: browserStackHost,
selenium_port: browserStackPort,
detailed_output: false,
desiredCapabilities: {
os: 'Windows',
os_version: '10',
browserName: 'Edge',
browser_version: '17.0',
resolution: browserStackScreenResolution
}
}
}
}
We have exactly the same code running on chrome browser in BrowserStack without any problems.
This suite runs in parallel using workers. If I disable workers, then it passes, unfortunately we need to use parallel execution otherwise the suite would take too long.

Travis CI - Builds are timing out

My .travis.yml
language: node_js
node_js:
- "0.12"
before_install:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
I have only added a few very simple tests so far (checking that class attributes exist).
I can see the tests are executed.
Then, the last few lines in the Travis output are this:
WARN [web-server]: 404: /css/style.min.css?1435068425.642
No output has been received in the last 10 minutes, this potentially indicates a stalled build or something wrong with the build itself.
The build has been terminated
If the tests are running, then the build and dependencies must have been installed already?
So why is the process not finishing once all tests are executed?
karma.config:
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: [
'jasmine',
'requirejs'
],
// list of files / patterns to load in the browser
files: [
{pattern: 'js/vendor/**/*.js', included: false},
{pattern: 'js/*.js', watched: true, included: false},
{pattern: 'test/**/*Spec.js', watched: true, included: false},
{pattern: 'css/**/*.css', included: false},
'test/test-main.js'
],
// list of files to exclude
exclude: [
'test/lib/**/*.js',
'js/vendor/**/test/*.js', //do not include the vendor tests
'js/_admin.js'
],
preprocessors: {
},
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Firefox'], //'Chrome', 'PhantomJS', 'PhantomJS_custom'
singleRun: false,
});//config.set
};//module.exports
test-main.js in folder test:
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
allTestFiles.push(file);
}
//console.log('test files:', allTestFiles);
});
require.config({
baseUrl: '/base',
paths: {
'jquery': './js/vendor/jquery/jquery-2.1.4.min',
'jquery-ui': './js/vendor/jquery-ui-1.11.4.custom/jquery-ui.min',
'underscore': './js/vendor/underscore/underscore-min',
'backbone': './js/vendor/backbone/backbone-min',
'mustache': './js/vendor/mustache/mustache.min',
'domReady': './js/vendor/requirejs/plugins/domReady/domReady',
'text': './js/vendor/requirejs/plugins/text/text',
//------------------------------------
//custom requireJS application modules
'my': './js/my',
'my-CSS': './js/my-CSS'
},
shim: {
'underscore': {
exports: '_'
}
},
deps: allTestFiles,
callback: window.__karma__.start
});
The my-CSS module loads the css like this:
//custom requireJS module to hold the crowdUI class
define(["my"], function (my) { //prerequisites
'use strict';
//load the CSS definitions
document.head.appendChild(
my.createElement('link', {
attribute: {
id: 'my-CSS',
href: './css/style.min.css?' + crowdUI.TIMESTAMP,
rel: 'stylesheet',
type: 'text/css'
}
})
);
});
If the issue is just that your task requires more than 10 minutes during which it produces no output, the fix is simple: prepend your command with travis_wait.
For instance travis_wait myCommand instead of just myCommand.

Getting Karma, 6to5ify and Istanbul to play ball

I have Browserify, 6to5ify and Karma to play nice, successfully running my specs. When I add code coverage however, things go south. I've tried several approaches:
Add browserify-istanbul transform to my karma.conf.js. However, this results in it trying to run instrumentation on my spec-files as well it would appear.
Run coverage preprocessor on my source files. But because istanbul (even douglasduteil/karma-coverage#next) doesn't read my 6to5ify browserify transform, this crashes immediately on the first file it tries to parse (because of the import statement), or when I use karma-coverage#next, it doesn't respect the browser mapping in my package.json (mobile project, mapped Backbone to Exoskeleton).
Right now my karma.conf.js looks like this:
module.exports = function(karma){
karma.set({
frameworks: ["browserify", "mocha", "chai-sinon"],
browserify: {
debug: true,
extensions: [".js", ".hbs"],
transform: ["6to5ify", "hbsfy"]
},
reporters: ["dots", "osx", "junit", "coverage"],
coverageReporter: {
type: "text"
},
junitReporter: {
outputFile: "spec/reports/test-results.xml"
},
preprocessors: {
"src/javascript/**/*": ["coverage"],
"spec/**/*": ["browserify"]
},
browsers: ["PhantomJS"],
files: ["spec/unit/**/*Spec.js"],
logLevel: "LOG_DEBUG",
autoWatch: true
});
};
I'm kind of lost how to get this all working together. I tried following these instructions, but that didn't work because it didn't follow my browser node in package.json. Any help would be greatly appreciated.
So, apparently I need browserify-istanbul, and I need the browserify configure hook, like so:
var to5ify = require('6to5ify');
var hbsfy = require('hbsfy');
var cover = require('browserify-istanbul');
var coverOptions = {
ignore: ['**/*Spec.js', '**/lib/*.js', '**/fixtures/*.hbs'],
defaultIgnore: true
}
module.exports = function(karma){
karma.set({
frameworks: ["browserify", "mocha", "chai-sinon"],
browserify: {
debug: false,
extensions: [".js", ".hbs"],
configure: function(bundle){
bundle.on('prebundle', function(){
bundle
.transform(to5ify)
.transform(hbsfy)
.transform(cover(coverOptions));
});
}
},
reporters: ["dots", "osx", "junit", "coverage"],
coverageReporter: {
type: "text"
},
junitReporter: {
outputFile: "spec/reports/test-results.xml"
},
preprocessors: {
"spec/**/*": ["browserify"]
},
browsers: ["PhantomJS"],
files: ["spec/unit/**/*Spec.js"],
logLevel: "LOG_DEBUG",
autoWatch: true
});
};

Resources