Take screenshot for specific element for ios devices - safari browser - safari

i'm trying to take a screenshot for any specific element on the safari browser - by appium+webdriverio+browserStack.
appium version : 1.15.0
here are the error logs :
Calling AppiumDriver.getElementScreenshot() with args: ["5028","e154c6f0-73b9-4306-b661-d3206aa7ba8e"]
[debug] [XCUITest] Executing command 'getElementScreenshot'
[debug] [RemoteDebugger] Executing atom 'getElementScreenshot'
[debug] [MJSONWP (e154c6f0)] Encountered internal error running command: Error: Unable to load Atom 'getElementScreenshot' from file '/usr/local/.browserstack/appium_1.14.0_bstack/node_modules/appium-remote-debugger/atoms/getElementScreenshot.js'
[debug] [MJSONWP (e154c6f0)] at getAtoms (/usr/local/.browserstack/appium_1.14.0_bstack/node_modules/appium-remote-debugger/lib/atoms.js:17:13)
2019-11-21 06:44:37:879 - [HTTP] <-- GET
Please help, is there anything I'm doing wrong? Please suggest as i want to take a screenshot of specific webElement by appium on safari browser

Afaik there is currently no way of taking a screenshot of a specific web element (via web selectors) with only webdriverio and appium. While webdriverio provides an element.saveScreenshot function, it does not seem to work on mobile with appium.
The way that I work around it is to take a screenshot of the whole page with browser.saveScreenshot(filepath) (make sure to switch to native context for this) and then crop it to the elements rect with an image library (sharp, in my case).
My util functions look like this:
import fs from 'fs';
import path from 'path';
import sharp from 'sharp';
export function takeScreenshot(element) {
const timestamp = moment().format('YYYYMMDD-HHmmss.SSS');
if (fs.existsSync('reports/screenshots/')) {
const filePath = path.join('reports/screenshots/', timestamp + '.png');
WebView.switchToContext(CONTEXT_REF.NATIVE);
browser.saveScreenshot(filePath);
WebView.switchToContext(CONTEXT_REF.WEBVIEW);
if (element) {
const size = getRealSize(element);
const location = getRealLocation(element);
const outputPath = path.join('reports/screenshots/', element.selector + timestamp + '.png');
sharp(filePath).extract({ width: size.width, height: size.height, left: location.x, top: location.y }).toFile(outputPath)
.then(function () {
fs.unlinkSync(filePath);
fs.renameSync(outputPath, filePath);
})
.catch(function (err) {
console.log(err);
});
}
}
}
export function getPixelRatio() {
return browser.capabilities.pixelRatio ? browser.capabilities.pixelRatio : 1;
}
export function getRealLocation(element) {
const location = element.getLocation();
return {
x: Math.round(location.x * getPixelRatio()),
y: Math.round(location.y * getPixelRatio())
}
}
export function getRealSize(element) {
const size = element.getSize();
return {
width: Math.round(size.width * getPixelRatio()),
height: Math.round(size.height * getPixelRatio())
}
}

Related

React Native Fetch Blob/React Native Blob Util Fail in Production but not in Developer time

I am trying to download a pdf generated through an own api that worked normally for me until yesterday, since then it has stopped working without any modification. Reviewing in developer mode through the metro everything seems to work correctly without any problems (I download the pdf normally), but when deploying the application in the playstore it closes unexpectedly, leaving me without knowing why this happens.
First I was using the React Native Fetch Blob, then I used React Native Blob Util hoping it would solve the problem but it keeps happening. Do you guys have any ideas for why does this happen?
The PDF file download this function:
const generarReciboPdf = async (datosDeuda:FormularioScreenParams,formaPago:ReactText,nroCheque?:string) =>{
const{config,fs} = ReactNativeBlobUtil
if (formaPago === 4 && (nroCheque == ""|| undefined)) {
return console.log('debe llenar todos los campos');
}
const { DownloadDir } = fs.dirs;
const token = await AsyncStorage.getItem('token');
let datosDeudaCompleto= {
...datosDeuda,
forma_pago:formaPago,
nro_cheque:nroCheque
}
let url = 'https://sys.arco.com.py/api/appRecibos/generarReciboPdf/'+JSON.stringify(datosDeudaCompleto)
// return console.log(url);
const options = {
fileCache: true,
addAndroidDownloads: {
useDownloadManager: true, // true will use native manager and be shown on notification bar.
notification: true,
mime:'application/pdf',
path: `${DownloadDir}/recibo_${datosDeuda.mes_deuda.replace(/ /g, "")}_${datosDeuda.razon_social.replace(/ /g, "")}.pdf`,
description: 'Downloading.',
},
};
config(options).fetch('GET', url,{Authorization :'Bearer '+token}).then((res) => {
console.log('se imprimio correctamte el pdf');
setErrorPdf(1)
}).catch((error)=>{
console.log(error);
setErrorPdf(-1);
});
}
Also, this error appears in Play Console: "PlayConsole Error Image".
PlayConsole Error Image

Cannot read property 'requestContent' of undefined. Epubjs

I used Epubjs. But when I run the application. It turns out "Cannot read property 'requestContent' of undefined". Maybe it is about Asynchronous loading.`
// # is an alias to /src
import Epub from 'epubjs'
global.ePub = Epub
export default {
name: 'home',
mounted () {
this.book = new Epub('/public/东京暗鸦_qinkan.net.epub')
this.book.renderTo('read', {
width: window.innerWidth,
height: window.innerHeight
})
}
}
</script>`
I saw this issue in Chrome and loaded the new code into FF instead and it was showing me a Cross Origins blocked error (which makes sense because I hadn't added that to my API yet).
So this appears to be a chrome issue but might want to look into Cross-origin being blocked in your API.

Timeout while file download

In my Fixture, I have an action that will start to download a file with browser. This worked very fine until the server will respond directly.
.expect(fs.existsSync(downloadsFolder()+'/export.xml')).ok()
But now I have some file the server need to create, and so a waiting time will occur. I tried to expand the function:
.expect(fs.existsSync(downloadsFolder()+'/export.xml')).ok('War wohl nicht erfolgreich',{ timeout: 300000 })
But the result is the same with a first tryout. I did some research and found:
async function CheckFileExistsWithTimeDelay(t, timeDelay, fileNameAndPath) {
for (var i = 0; i < timeDelay; i++) {
console.log('Waited for a total of ' + i.toString() + ' microseconds');
await t.wait(1);
if (fs.existsSync(fileNameAndPath)) {
// break;
return;
}
}
};
This also does not work. I think the watch file function blocks the Fs and so the browser cannot download the file (write the file). Also, this does not work:
async function waitForFile (path) {
for (let i = 0; i < 300; i++) {
if (fs.existsSync(path))
return true;
await t.wait(1000);
}
return fs.existsSync(path);
}
await t.expect(await waitForFile(downloadsFolder()+'/export.xml')).ok("War wohl nicht erfolgreich", { timeout: 300000 });
It looks like that the file download will fail until testcafe is waiting some time. If the file is downloaded directly everything is fine.
Is there any good example to wait for a downloaded file without blocking the fs?
It was requested so I add it here: The line where testcafe will get the command to download)
await t
.click(Selector('button').withText('Aktionen'))
.click(Selector('a').withText('Xml Exportieren'));
As I wrote. Immediately download works perfect. Until the download is delayed it fails. It looks like that some hook is hanging on the file and so chrome cannot download.
NEW INFO 1
The server will response exact 38,7 seconds after the download link was clicked. After I do this with testcafe I will get inside the browser window
If I use a real case, it means I will click on the link on the physical website the file is downloaded well after the 38 seconds. No error.
NEW INFO 2
I also tried to add a long .wait(150000) to the fixture and then check if the file exists. The browser tried to download the file in the background while waiting inside .wait(150000) loop. And also this is failed.
So I think it is proof that it is a Testcafe issue and not a node issue.
Here is the another example of how to wait for a downloaded file in test:
import { Selector } from 'testcafe';
import fs from 'fs';
const waitForFileDownloaded = (filePath, timeDelay) => new Promise(resolve => {
let i = 1;
const intervalId = setInterval(() => {
if (fs.existsSync(filePath)) {
clearInterval(intervalId);
resolve(true);
}
i++;
if (i > timeDelay) {
clearInterval(intervalId);
resolve(false);
}
}, 1000);
});
fixture `Downloading`
.page `https://github.com/DevExpress/testcafe`;
test('Test', async t => {
await t
.click(Selector('a').withText('218 releases'))
.click(Selector('a').withText('Source code'))
.expect(await waitForFileDownloaded('c:\\Users\\username\\Downloads\\testcafe-1.6.0.zip', 60)).ok();
});
Also could you please clarify if the downloading process is started after TestCafe clicked on the link (for example, using only await t.wait() with a big timeout)?

How to add a in-app browser in React Native (Expo)

How to open a web browser in expo rather than using the expo browser.I want open the browser in inside the app.
you can use the following library react-native-inappbrowser
follow the installation from the github page
import { Linking } from 'react-native'
import InAppBrowser from 'react-native-inappbrowser-reborn'
...
async openLink() {
try {
const url = 'https://www.google.com'
if (await InAppBrowser.isAvailable()) {
const result = await InAppBrowser.open(url, {
// iOS Properties
dismissButtonStyle: 'cancel',
preferredBarTintColor: '#453AA4',
preferredControlTintColor: 'white',
readerMode: false,
animated: true,
modalPresentationStyle: 'overFullScreen',
modalTransitionStyle: 'partialCurl',
modalEnabled: true,
// Android Properties
showTitle: true,
toolbarColor: '#6200EE',
secondaryToolbarColor: 'black',
enableUrlBarHiding: true,
enableDefaultShare: true,
forceCloseOnRedirection: false,
// Specify full animation resource identifier(package:anim/name)
// or only resource name(in case of animation bundled with app).
animations: {
startEnter: 'slide_in_right',
startExit: 'slide_out_left',
endEnter: 'slide_in_left',
endExit: 'slide_out_right'
},
headers: {
'my-custom-header': 'my custom header value'
},
waitForRedirectDelay: 0
})
Alert.alert(JSON.stringify(result))
}
else Linking.openURL(url)
} catch (error) {
Alert.alert(error.message)
}
}
...
you can check the example app here
for expo it becomes little bit complicated please check the related tutorial by Medium
if you want reading mode in ios please refer this link
reader-mode-webview-component-for-react-native
The expo-web-browser package opens an in app browser.
This worked for me with expo. I tried react-native-inappbrowser-reborn first, but isAvailable() was throwing an error.
import * as WebBrowser from 'expo-web-browser'
...
WebBrowser.openBrowserAsync(url, {showTitle: true})

How to show native popup using Gulp

I am working on Gulp build process for automation. I have created a Gulp task for creating signed APK of android. Now I want to show a notification popup so that I can come to know my android APK is built.
Is there any way to show native popup in Gulp process?
I have done research and found node-notifier and gulp-notify modules but both are not working for me. Please help
As per posted answer,
I have tried with following, but no help... I am not getting notification. Does it requires Windows Toaster Support... I am using Windows 8.1 Pro.
gulp.task('notifier', function(){
notify('Running from notifier task', 'Everything looks good');
});
function notify(title, message) {
// Load dependencies
var path = require('path');
var notifier = require('node-notifier');
var notifyOptions = {
title: title,
message: message,
//icon: path.join(__dirname, 'coulson.jpg'), // Absolute path (doesn't work on balloons)
sound: true, // Only Notification Center or Windows Toasters
wait: true // Wait with callback, until user action is taken against notification
};
// start notifier
notifier.notify(notifyOptions);
}
Try this:
Make sure these are installed by running install once again
Install
npm install path node-notifier --save-dev
Task
gulp.task('notifier', function(){
notify('Running from notifier task', 'Everything looks good');
);
Notifier Function
function notify(title, message) {
// Load dependencies
var path = require('path');
var notifier = require('node-notifier');
var notifyOptions = {
title: title,
message: message,
icon: path.join(__dirname, 'coulson.jpg'), // Absolute path (doesn't work on balloons)
sound: true, // Only Notification Center or Windows Toasters
wait: true // Wait with callback, until user action is taken against notification
};
// start notifier
notifier.notify(notifyOptions);
}
This is too late after asking the question, but I thought it's good to record my solutions here.
So there are different commands to show a native popup for different OS.
1. Windows
Use the command msg * <Your_Message_Here>, for example, msg * Hello World.
This popup closes automatically after 1 minute.
2.iOS
Use the command
osascript -e 'tell app \"System Events\" to display dialog \"<Your_Message>\" with title \"<Your_Title>\"'"
and then you can execute these commands using node exec,
var WINDOWS_POPUP = "msg * MESSAGE";
var MAC_POPUP = "osascript -e 'tell app \"System Events\" to display dialog \"MESSAGE\" with title \"SUCCESS\"'";
function execCMD(cmd, cb) {
exec(cmd,
{
cwd: './',
maxBuffer: 2048 * 2048
},
function (err, stdout, stderr) {
plugins.util.log(stdout);
plugins.util.log(stderr);
if (err) {
cb(err);
} else {
cb(null,stdout);
}
});
}
/**
* Rename android apk
*/
gulp.task('copyAPK', function () {
return gulp.src(APK_PATH)
.pipe(plugins.if(args.signedAPK, plugins.rename(APK_NAME)))
.pipe(gulp.dest(releaseDirName + '/Android/'))
.on('end', function () {
plugins.util.log(plugins.util.colors.green('Good Job! Your APK is ready at following location : ') + plugins.util.colors.cyan(releaseDirName + '/Android/' + APK_NAME))
execCMD(WINDOWS_POPUP.replace('MESSAGE', 'Good Job! Your APK is ready at following location : ' + releaseDirName + '/Android/' + APK_NAME), function () {
})
});
});
/**
* Copy generated IPA
*/
gulp.task('copyIPA', function () {
return gulp.src(IPA_PATH)
.pipe(plugins.rename(IPA_NAME))
.pipe(gulp.dest(releaseDirName + '/iOS/'))
.on('end', function () {
plugins.util.log(plugins.util.colors.green('Good Job! Your IPA is ready at following location : ') + plugins.util.colors.cyan(releaseDirName + '/iOS/' + IPA_NAME))
execCMD(MAC_POPUP.replace('MESSAGE', 'Good Job! Your IPA is ready at following location : ' + releaseDirName + '/iOS/' + IPA_NAME), function () {
})
});
})
Hope this will help someone in scripting :).