I'd like to run different functions in my onPrepare function based on what capabilities I am running. I'd also like to be able to set capabilities from the command line. For example I run every test suite by typing "protractor" at the moment. Something like "protract -android" or "protractor directConnect = true" or anything that functions in a similar manner is what I am looking for.
Then in the onPrepare I have a function that maximizes my window which will not work when I run my android tests. I'm looking for a solution so that when I run the tests on android it just ignores that block of code.
In protractor you can use global variables using params object in the config.js file. Try the below solution to solve your problem.
In config.js file create a params object with new variable as android.Following will be a demo config file.
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
capabilities: {
'browserName': 'chrome'
},
onPrepare: function () {
if(browser.params.android == 'true'){
//do whatever code you need to execute
}else{
}
},
params: {
android: 'false',
}
}
You can now pass the value for android variable as a commond line argument when you run the protractor test.
protractor config.js --params.android true
Related
Framework: Appium + Protractor + Cucumber + Typescript using POM model
I have the protractor framework for appium designed in POM structure
The initial page of the app will identify the locators calling in a different ts file and the functions such as tap, isDisplayed calling it in a different ts file.
But once it passes the initial pages in the app,say 3 pages. the locators are not identified which are calling other function, but they are identified when they are passed directly ( like driver.findelements(by.css('')).click ) this works.
The problem is I can't pass this code like this within the step definition .ts file always as it is not a good structure
Note: By the way, this script was working fine earlier.
tried to test using a different workaround, like building the binary again, trying to run on android and ios application, downgrading or upgrading the node packages. But nothing solved the problem. has anyone faced this kind of issue. Any suggestions or solutions for this problem, please?
Code which works: (Passing the locators directly in the function, rather than from the onboarding.ts file will work)
Then(/^VIC should be selected from the state or territory drop down$/, async () => {
await browser.driver.findElement(by.css('button[sp-automation-id=\'select-state-toggle\']')).click();
await browser.driver.findElement(by.css('page-action-sheet label[sp-automation-id=\'action-sheet-option-VIC\']')).click(); });
Code which does not work: (Onboarding.ts file contains the locators defined for State and VIC same as the above code block. But reading from there it does not work.)
Then(/^VIC should be selected from the state or territory drop down$/, async () => {
await AutomationAction.tap(Onboarding.State);
await AutomationAction.tap(Onboarding.VIC); });
Code which works (The below code is called before the above code block, it's a page before calling the above pages)
Then(/^I enter the mobile number and tap next button on the your mobile number screen$/, async () => {
MobileNo = AutomationAction.getMobileNumber("mobileNumber");
SameMobileNo = MobileNo;
await AutomationAction.sendKeyText(Onboarding.InputMobileNo,MobileNo);
await AutomationAction.tap(Onboarding.Next_BTN_YourMobileNumber);
});
Because of the page where it is failing the automation thinks its as non-angular page and the locators used to fail or not locate them when calling it in a different function. When I introduced browser.ignoreSycnhronization=true to make Angular sync for non-angular apps/pages it worked.
How to run multiple test cases of Flutter integration tests in single command or from single file.
1. If I run two separate commands for two files then report generates only for last command.
2. When I try to do separate groups in single file then app stays on same page doesn't restart.
Here I need to restart app for further processing. Is there any way to combine multiple test cases to run from multiple files.?
Thing to consider: I am using ozzie as a report generator.
Thanks in advance.
You may trying to run all test-case from one file. it may help, though its late replay.
Suppose you have 3 test file which is,
login.dart and login_test.dart (where all the test-case has to be written in login_test.dart)
register.dart and register_test.dart
forgotPassword.dart and forgotPassword_test.dart
Put all those test-cases into a main function. (describing only one test file code[login_test.dart])
main(){
loginTest();
}
Future<void> loginTest()async{
group('Login Page Automation Test :', () {
//Write your test-cases here
}
so, now create a test file and call all the main functions on that file, which will be used to run all cases at once.
testAll.dart & testAll_test.dart
Write in these format on testAll_test.dart
import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart';
import 'login_test.dart';
import 'register_test.dart';
import 'forgotPassword_test.dart';
main() {
testAll();
}
Future<void> testAll() async {
group('All TestCase at Once: ', () {
//code here
FlutterDriver driver;
// Connect to the Flutter driver before running any tests.
setUpAll(() async {
driver = await FlutterDriver.connect();
});
// Close the connection to the driver after the tests have completed.
tearDownAll(() async {
if (driver != null) {
driver.close();
}
});
//main methods below
forgotPasswordTest();
registerTest();
loginTest();
});
}
and finally run the app using this.
flutter drive --target=test_driver/testAll.dart
I started using Appium to run UI test on Android apps (and possibly iOS once I get it to work on Android)
I'm trying to run a test using nodeJS and webdriverio.
The thing is, I can't seem to click on an element of a list (the list is dynamically created so elements all have the same id)
Here is the node code. When I run it, appium correctly starts an emulator and opens my app:
const wdio = require("webdriverio");
const opts = {
port: 4723,
desiredCapabilities: {
platformName: "Android",
platformVersion: "8.0",
deviceName: "Android Emulator",
app: "/path/to/application.apk",
appWaitActivity: "com.package.SomeActivity",
automationName: "UiAutomator2",
avd: "Nexus_5X_API_26"
}
};
const client = wdio.remote(opts);
client
.init()
.elements('id:theIdOfTheList') // This retrieves a list of 4 elements
.element()[3] // This gives a NoSuchElementError
.end();
What should I use in place of .element()[3] to make this work (or is there a completely different way I should do it?)
I see in appium that the 4 elements of the list are retrieved:
Got response with status 200: {"sessionId":"1c21baa1-60ec-4e5f-b51f-f738698660ad","status":0,"value":[{"ELEMENT":"53d31f1f-af25-4621-85cd-b2f881a5c770"},{"ELEMENT":"4c3909ab-6f65-426a-b831-9a7d5e069ba8"},{"ELEMENT":"e0fd1f12-0193-48ea-a168-4d45f63d27b3"},{"ELEMENT":"87b7abda-3738-4411-a544-572243cd7502"}]}
I'm not familiar with Node.js, but from the looks of it you're not storing that array of elements anywhere and your subsequent element() call is merely looking for another unrelated element. Since you've provided it no search parameters, it finds nothing.
Pardon my ignorance of your language, but something like the following should get you what you want:
.elements('id:theIdOfTheList')[3]
How about something like this. ( I use sync mode for webdriverio). This may work in
asyc mode.
client
.init()
.elements('id:theIdOfTheList', function(err, resp) {
resp.value.forEach(function(elem) {
// log elem
})
})
.end();
I am wanting to run JavaScript on each and every page that is loaded within the browser. The JavaScript should only be run after the page is loaded and needs to access all elements within the DOM.
I am able to successfully execute the following JavaScript within Scratchpad, although having problems porting it over to my bootstrap.js.
// Use the current content window as the execution context.
// To make properties defined by scripts executing on the page
// available to your sandbox script, use content.wrappedJSObject
// instead.
let context = content;
// Create the Sandbox
let sandbox = Components.utils.Sandbox(context, {
// Make properties of the context object available via the
// script's global scope
sandboxPrototype: context,
// Wrap objects retrieved from the sandbox in XPCNativeWrappers.
// This is the default action.
wantXrays: true
});
// The script that will be executed:
let script = "document.body.style.background = 'red'; alert('test')";
// Evaluate the script:
Components.utils.evalInSandbox(script, sandbox,
// The JavaScript version
"1.8",
// The apparent script filename:
"zz-9://plural/zed/alpha",
// The apparent script starting line number:
42);
Could anyone kindly shed some light as to where exactly the above code needs to be placed within the bootstrap.js?
You need to make a framescript out of it, this is complete example, your script that will execute in the DOM should go into the contentscript.js file: https://github.com/Noitidart/modtools
If you use the addon-sdk, it handles this for you, I prefer not to though thats why my repo linked above does it this way.
I'm (newly) using protractor to run e2e cucumber tests.
I got a web-app which is angularJS based. I'm using appium to remotely run the test on a real android device. Here are the versions i'm using :
windows8.1
protractor#1.3.1 (with submodule selenium-webdriver#2.43.5)
appium#1.3.0beta1
android device with 4.4.4
my protractor configuration (extracts), corresponding to https://github.com/angular/protractor/blob/master/docs/browser-setup.md:
currentDeviceUDID = (...);
var appToTestURL = 'http://my.website.com:9000/app/index.html';
exports.config = {
seleniumAddress: 'http://localhost:4723/wd/hub';
chromeOnly: false,
specs: ['features/sample.feature'],
capabilities: {
browserName: 'chrome',
'appium-version': '1.0',
platformName: 'Android',
platformVersion: '4.4.4',
udid: currentDeviceUDID
},
baseUrl: appToTestURL
framework: 'cucumber',
cucumberOpts: {
require: 'features/stepDefinitionsSample.js',
tags: '#dev',
format: 'progress'
},
// configuring wd in onPrepare
onPrepare: function () {
var wd = require('wd'),
protractor = require('protractor'),
wdBridge = require('wd-bridge')(protractor, wd);
wdBridge.initFromProtractor(exports.config);
},
allScriptsTimeout: 30000,
getPageTimeout: 30000
};
As you can see, i have replaced the protractor's webdriver url with the appium webdriver. i start the appium from commandline with "appium &", then i run the test with "protactor cucumbertest.conf"
The phone opens chrome browser and navigates to the url i give it with "browser.get(url)"
the problem is the following:
the call waitForAngular(), which is asynchronously waiting for the website to load and on all open http request (as far as i understand), is not executed sucessfully on the phone. the phone does not react to the call, and the webdriver proxy returns a 500.
Corresponding to https://github.com/angular/protractor/issues/1358, i understood that the waitForAngular() function is mixed in protractor into the calls
['getCurrentUrl', 'getPageSource', 'getTitle'];
Behind waitForAngular() in the file protractor.js is the function below, which is proxied to the phone:
functions.waitForAngular = function(selector, callback) {
var el = document.querySelector(selector);
try {
if (angular.getTestability) {
angular.getTestability(el).whenStable(callback);
} else {
angular.element(el).injector().get('$browser').
notifyWhenNoOutstandingRequests(callback);
}
} catch (e) {
callback(e);
}
};
Additional information: when i stimulate an error on the webdriver (browser) object, the error message points to the chromedriver.exe inside the protractor directory. i dont understand why the error is not from appium's chromedriver
so tldr;
without the successful call waitForAngular, i cannot (stable or at all) access elements on the page on the phone, so not testing. maybe im misunderstanding some fundamental configuration detail here, all hints are welcome.
edit: added appium server logs here: http://pastebin.com/vqBGUdXH
I assume i have identified the problem. Appium and Protractor work fine.
My angularJS app causes the issue. It uses $timeout for polling (im forced on angular 1.07 which has no $interval). This causes protractor to expect the page to be still in the loading stage and not finished. Therefore the function call waitForAngular() never returns and the test timeouts after the specified timeout-timespan.
This behaviour is expected and known, also documented (better read doc first ;) ) at http://angular.github.io/protractor/#/timeouts
The doc suggests the following for continuous polling: replace $timeout with $interval:
If your application continuously polls $timeout or $http, it will never be registered as completely loaded. You should use the $interval service (interval.js) for anything that polls continuously (introduced in Angular 1.2rc3).
For now, i fixed the issue another way: disable the built-in angular sync and manually sync
this.Before(function(next){
ptor = protractor.getInstance();
ptor.ignoreSynchronization = true; //disables waitForangular()
next();
});
Sync method 1:
//at a testcase, wait for an element to be visible with a promise/then
browser.wait(function () {
element.all(by.css('.myCssClass')).then(function (items) {
items[0].getText().then(function (text) {
console.log(text);
});
});
return true;
}
Sync method 2 :
// "eventually" (chai-as-promised) internally uses "promise" (and therefore acts like "then")
browser.get(url);
expect(browser.getTitle()).to.eventually.equal("connect me").and.notify(next);