In Flutter end-to-end testing, a permission is to be allowed during the test. driver.tap(find.text("ALLOW") does not work. How to click "ALLOW".
You can grant the permissions before running the test.
import 'dart:io';
import 'package:path/path.dart';
// ...
setUpAll(() async {
final envVars = Platform.environment;
final adbPath = join(
envVars['ANDROID_SDK_ROOT'] ?? envVars['ANDROID_HOME'],
'platform-tools',
Platform.isWindows ? 'adb.exe' : 'adb',
);
await Process.run(adbPath, [
'shell',
'pm',
'grant',
'com.example.yourapp', // replace with your app id
'android.permission.RECORD_AUDIO'
]);
driver = await FlutterDriver.connect();
});
Other answers will not help you if you are using the latest Flutter Integration Testing as there we don't require FlutterDriver to connect.
So now, you need to add the below code in test_driver.dart file where we initialize integrationDriver()
Future<void> main() async {
final Map<String, String> envVars = Platform.environment;
String? adbPath = join(envVars['ANDROID_SDK_ROOT'] ?? envVars['ANDROID_HOME']!,
'platform-tools',
Platform.isWindows ? 'adb.exe' : 'adb',
);
await Process.run(adbPath , ['shell' ,'pm', 'grant', 'com.example', 'android.permission.CAMERA']);
await Process.run(adbPath , ['shell' ,'pm', 'grant', 'com.example', 'android.permission.WRITE_EXTERNAL_STORAGE']);
await integrationDriver();
}
This change is required as FlutterDriver makes the connection once you initialized and connect it, but the new flow of integration testing already had a connection, so we need to initialize it before the connection happens.
To run code, use the below command on terminal, as you see for better result I have created two folder,
test_driver: Contains the driver code mentioned above.
integration_test: Contains test files.
flutter drive --driver=test_driver/test_driver.dart --target=integration_test/my_test.dart
for me above code is not working don't know why
then i'm tried with below code and its working
setUpAll(() async {
await Process.run('add_adb_path/adb.exe' , ['shell' ,'pm', 'grant', 'add_app_package_name', 'android.permission.ACCESS_MEDIA_LOCATION']);
await Process.run('add_adb_path/adb.exe' , ['shell' ,'pm', 'grant', 'add_app_package_name', 'android.permission.READ_EXTERNAL_STORAGE']);
await Process.run('add_adb_path/adb.exe' , ['shell' ,'pm', 'grant', 'add_app_package_name', 'android.permission.WRITE_EXTERNAL_STORAGE']);
driver = await FlutterDriver.connect();
});
Related
Issue:
I am trying to get TestCafe to open an internal website that triggers a windows authentication pop up on opening, but the TestCafe built in Authentication feature doesn't work for some weird reason and the website complains with "401 - Unauthorized: Access is denied due to invalid credentials."
Note manually I can open the website with the same login credentials.
Also note the Authentication feature does work for other websites, and I am doing this at work, so there is a work proxy.
The site that TestCafe is failing to open up:
Is made up of a server name & port only & lives internally eg.
http://[ServerName]:[Port]
The Code:
Made up of 2 files....
The Test Script:
import {Selector} from 'testcafe';
fixture('My Test')
.page('http://[ServerIP]:[Port]/') // Also tried ('http://[ServerName]:[Port]')
.httpAuth({
username: 'domain\name',
password: 'password_here'
})
test ('Opening this internal site', async t => {
await t
.debug()
});
The Runner file:
const createTestCafe = require('testcafe');
let testcafe = null;
createTestCafe('localhost', '8081')
.then(tc => {
testcafe = tc;
const runner = testcafe.createRunner();
return runner
.src([
'My_Test.js'
])
.browsers('chrome')
.useProxy('webproxy01:8080', '[ServerIP]:[Port]') // I tried including the website that I want to test incase it needs to be ByPassed
.run({
skipJsErrors: true,
concurrency: 1
})
})
.then(failedCount => {
console.log(`Tests failed: ` + failedCount);
testcafe.close();
});
Just to add I've tried this too and it doesn't work either:
.httpAuth({
username: 'name',
password: 'password_here',
domain: 'domain_here',
workstation: 'computer_name'
})
Many thanks!
I am writing test cases for Javascript using mocha. My code exactly looks like this apigee
This javascript is deployed in apigee cloud. Where it has access to platform variables. This is myscript my-code.js
var responseCode = parseInt(context.getVariable(properties.source));
var log = {
org: context.getVariable(organization.name),
env: context.getVariable(environment.name),
responseCode: responseCode,
isError: (responseCode >= 400)
};
if (log.isError) {
log.errorMessage = context.getVariable(flow.error.message);
}
var logglyRequest = new Request(
'https://loggly.com/aaa',
'POST',
{'Content-Type': 'application/json'},
JSON.stringify(log)
);
httpClient.send(logglyRequest);
javascript code would have access to properties.source at run time. Apigee platform has its own internal way of how jc access those params. My question is if I am writing test case for this jc, how would I mock the values for properties.source. I am able to mock function call context.getVariable(). I am getting ReferenceError: properties is not defined. Test script in same in the apigee link given.
Try adding the following to your tests:
global.properties = {
source: 'jwt.Decode-IAM-JWT.decoded.header.kid'
};
That is what I do and it works fine.
I am executing my protractor test suite from my desktop and I am using a remote selenium server. I have configured the 'protractor-video-reporter' to capture execution for my local windows environment (using ffmpeg codec) and when I execute using my local selenium server, the video capture works fine. But when I execute on remote VMs, it captures my desktop screen.
I understand that I need to provide the remote location path to ffmpeg codec, but I do not know how to provide appropriate user credentials so that my automation can invoke the remote plugin?
My present configuration is as follows:
const VideoReporter = require('protractor-video-reporter');
...
let config = {
...
onPrepare: () => {
...
VideoReporter.prototype.jasmineStarted = function () {
var self = this;
if (self.options.singleVideo) {
var videoPath = path.join(self.options.baseDirectory, 'protractor-specs.mpg');
self._startScreencast(videoPath);
if (self.options.createSubtitles) {
self._subtitles = [];
self._jasmineStartTime = new Date();
}
}
};
...
jasmine.getEnv().addReporter(new VideoReporter({
baseDirectory: './test-output/videoreport',
createSubtitles: false,
saveSuccessVideos: true,
singleVideo: true,
ffmpegCmd: "C:/FFmpeg/bin/ffmpeg.exe", /*Probably some changes needed here*/
ffmpegArgs: [
'-f', 'gdigrab',
'-framerate', '30',
'-video_size', 'wsxga',
'-i', 'desktop',
'-q:v', '10',
]
}));
...
}
...
}
export { config };
Considering that execution and video capture both has to happen in remote server, please suggest a suitable solution.
Hello it's my first time doing a sign in process in a mobile app with Titanium and I wonder what information should I save and the best practice to do it?
My server is configured in this way:
The server requires I send a user and password and if the information match it will provide a token session.
This is the code I use for signing in:
function signIn(e) {
//function to use HTTP to connect to a web server and transfer the data.
var sendit = Ti.Network.createHTTPClient({
onerror : function(e) {
Ti.API.debug(e.error);
alert('There was an error during the connection');
},
timeout : 100000,
});
//Here you have to change it for your local ip
sendit.open('POST', 'http://myserver');
var params = {
user : $.txtUsuario.value,
password : $.txtPassword.value
};
sendit.send(params);
//Function to be called upon a successful response
sendit.onload = function() {
var json = this.responseText;
var response = JSON.parse(json);
if (response.success == "true")
{
var landing = Alloy.createController("menu").getView();
$.index.close();
landing.open();
}
else
{
alert(response);
}
};
};
the code above is working, however I do not know how to manage the sign out. I would like my application works like the most apps do, e.g:
You sign in once and after that if you do not close the app you are able to continues using it and even making a request.
Thank you for any explanation.
It depends on your app requirements. for exemple if you will use the token in your app later you can save it as an AppProperty :
Ti.App.Properties.setString('token',yourTokenGoHere);
and in the app starting you can get it back :
var myToken = Ti.App.Properties.getString('token');
and then you can make a test for example if the token is still valid or not :
if(myToken === 'invalidtoken')
youSholdLogin();
else
youCanGoFurther();
and when the user disconnect rest the token to be invalid :
Ti.App.Properties.setString('token', 'invalidtoken');
I need to write multiple tests (e.g. login test, use application once logged in tests, logout test, etc.) and need them all to be in separate files. The issue I run into is after each test, at the beginning of the next test being run, a new browser session start and it is no longer logged in due to the new session, so all my tests will fail except the login test.
So, is there a way to use the same browser session to run all of my tests sequentially without having to duplicate my login code? Sorry if this is a repost but I have searched and researched and not found any answers.
OR, is there a way to chain the test files somehow? Like having one file that you run that just calls all the other test files?
Using this function to chain together files:
extend = function(target) {
var sources = [].slice.call(arguments, 1);
sources.forEach(function (source) {
for (var prop in source) {
target[prop] = source[prop];
}
});
return target;
}
and adding files to this master file like this:
require("./testName.js");
module.exports = extend(module.exports,testName);
and having the test file look like this:
testName = {
"Test" : function(browser) {
browser
// Your test code
}
};
allowed me to have one file that could link all the tests to, and keep the same browser session the entire time. It runs the tests in the order you require them in the master file and if you do not call browser.end() until the last test is finished it will use one browser window for all tests.
Reuse of session is not good idea as you may run tests in different oreder, but
You could place login code into before function or even extract it into custom commands.
Example:
https://github.com/dimetron/backbone_app/blob/master/nightwatch/custom-commands/login.js
1 - In nightwatch config add
"custom_commands_path" : "nightwatch/custom-commands",
2 - Create custom-commands/login.js
exports.command = function(username, password, callback) {
var self = this;
this
.frame(null)
.waitForElementPresent('input[name=username]', 10000)
.setValue('input[name=username]', username)
.waitForElementPresent('input[name=password]', 10000)
.setValue('input[name=password]', password)
.click('#submit');
if( typeof callback === "function"){
callback.call(self);
}
return this; // allows the command to be chained.
};
3 - Test code - Before using .login(user, apssword)
module.exports = {
before: function(browser) {
console.log("Setting up...");
browser
.windowSize('current', 1024, 768)
.url("app:8000/")
.waitForElementVisible("body", 1000)
.login('user', 'password')
},
after : function(browser) {
browser.end()
console.log("Closing down...");
},
beforeEach: function(browser) {
browser
.pause(2000)
.useCss()
},
"Test 1": function(browser) {
browser
.assert.containsText("#div1", "some tex")
.pause(5000);
},
"Test 2": function(browser) {
browser
.assert.containsText("#div2", "some text")
.pause(5000);
}
}