How to use external data file (for example a json file) for scenario outline for iterate over a scenario - webdriver-io

How to use external data file (for example a json file) for scenario outline to iterate over a scenario in CucumberJS

You need use a custom code to inject the data in Examples of Scenario Outline. NoraUi automation Framework use this technic.
Example of scenario:
#loginLogout
Feature: loginLogout (Scenario that login and logout with any good user.)
Scenario Outline: Scenario that login and logout with any good user.
Given I check that 'user' '<user>' is not empty
Given I check that 'user' '<password>' is not empty
Given 'BAKERY_HOME' is opened
Then The BAKERY home page is displayed
When I log in to BAKERY as '<user>' '<password>'
Then The administrator part of the BAKERY portal is displayed?
|key|expected|actual|
|profile|admin|<profile>|
Then The referencer part of the BAKERY portal is displayed?
|key|expected|actual|
|profile|referencer|<profile>|
And I wait 3 seconds
When I log out of BAKERY
Then The BAKERY logout page is displayed
And I go back to 'BAKERY_HOME'
Examples:
#DATA
|id|user|password|profile|
|1|foo|123456|admin|
|2|bar|123456|referencer|
#END
Exemple of injector in java, you need use the same technic with your favorite languge:
public static void injectDataInGherkinExamples(String filename, Map<Integer, List<String[]>> examplesTable) {
try {
if (!examplesTable.isEmpty()) {
final Path filePath = getFeaturePath(filename);
final String fileContent = new String(Files.readAllBytes(filePath), Constants.DEFAULT_ENDODING);
String lang = getFeatureLanguage(fileContent);
LOGGER.info(lang);
StringBuilder examplesString;
final String[] scenarioOutlines = "fr".equals(lang) ? fileContent.split(SCENARIO_OUTLINE_SPLIT_FR) : fileContent.split(SCENARIO_OUTLINE_SPLIT);
for (final Entry<Integer, List<String[]>> examples : examplesTable.entrySet()) {
examplesString = new StringBuilder();
examplesString.append(" ");
for (int j = 0; j < examples.getValue().size(); j++) {
examplesString.append(SCENARIO_EXAMPLE_COLUMNS_SEPARATOR);
examplesString.append(j + 1);
for (final String col : examples.getValue().get(j)) {
examplesString.append(SCENARIO_EXAMPLE_COLUMNS_SEPARATOR);
examplesString.append(col);
}
examplesString.append(SCENARIO_EXAMPLE_COLUMNS_SEPARATOR + "\n ");
}
scenarioOutlines[examples.getKey() + 1] = scenarioOutlines[examples.getKey() + 1].replaceAll("(" + DATA + "\r?\n.*\r?\n)[\\s\\S]*(" + DATA_END + ")",
"$1" + examplesString.toString() + "$2");
}
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath.toString()), Constants.DEFAULT_ENDODING));) {
int i = 0;
bw.write(scenarioOutlines[i]);
while (++i < scenarioOutlines.length) {
if ("fr".equals(lang)) {
bw.write(SCENARIO_OUTLINE_SPLIT_FR + scenarioOutlines[i]);
} else {
bw.write(SCENARIO_OUTLINE_SPLIT + scenarioOutlines[i]);
}
}
}
}
} catch (final IOException e) {
LOGGER.error("error GherkinFactory.injectDataInGherkinExamples()", e);
}
}
you can find all source here on github.

Related

Unable to unload DLL in .NET Core 3

I am trying to unload an external assemble but it still sitting in the memory and I can not delete the dll file. Here is my code - What am I doing wrong ?
The uploaded dll is very simple - just 1 class and one method. no dependencies.
I had a look at many samples and see no issue in the code but it still does not work.
Thank you !
class SimpleUnloadableAssemblyLoadContext : AssemblyLoadContext
{
public SimpleUnloadableAssemblyLoadContext( ) : base(isCollectible: true)
{
}
protected override Assembly Load(AssemblyName name)
{
return null;
}
}
public class PluginLoader2
{
[MethodImpl(MethodImplOptions.NoInlining)]
public string getExternalText()
{
string res = "";
var sourcesPath = Path.Combine(Environment.CurrentDirectory, "Plugins");
string[] fileEntries = Directory.GetFiles(sourcesPath);
foreach (string fileName in fileEntries)
{
SimpleUnloadableAssemblyLoadContext context = new SimpleUnloadableAssemblyLoadContext();
WeakReference w_r = new WeakReference(context, trackResurrection: true);
var myAssembly = context.LoadFromAssemblyPath(fileName);
context.Unload();
for (var i = 0; i < 10 && w_r.IsAlive; i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
res += "<br /><br />" + fileName + " live status is " + w_r.IsAlive.ToString();
}
return res;
}
}

AsyncTask doInBackground() does not execute correctly on run, but works on debugger

#Override
protected ArrayList<HashMap<String, String>> doInBackground(Void... params) {
ArrayList<HashMap<String, String>> PLIST = new ArrayList<>();
HttpHandler sh = new HttpHandler();
String jsonStr = sh.makeServiceCall(jsonUrl);
ArrayList<String> URLList = new ArrayList<>();
if (jsonStr != null) {
placesList.clear();
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
JSONArray placesJsonArray = jsonObj.getJSONArray("results");
String pToken = "";
// looping through All Places
for (int i = 0; i < placesJsonArray.length(); i++) {
JSONObject placesJSONObject = placesJsonArray.getJSONObject(i);
String id = placesJSONObject.getString("id");
String name = placesJSONObject.getString("name");
HashMap<String, String> places = new HashMap<>();
// adding each child node to HashMap key => value
places.put("id", id);
places.put("name", name);
PLIST.add(places);
}
//TODO: fix this...
if (SEARCH_RADIUS == 1500) {
Log.e(TAG, "did it get to 1500?");
try {
for (int k = 0; k < 2; k++) {
//error is no value for next_page_token... this
ERROR HERE
pToken = jsonObj.getString("next_page_token"); //if I place breakpoint here, debugger runs correctly, and returns more than 20 results if there is a next_page_token.
String newjsonUrl = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location="
+ midpointLocation.getLatitude() + "," + midpointLocation.getLongitude()
+ "&radius=" + SEARCH_RADIUS + "&key=AIzaSyCiK0Gnape_SW-53Fnva09IjEGvn55pQ8I&pagetoken=" + pToken;
URLList.add(newjsonUrl);
jsonObj = new JSONObject(new HttpHandler().makeServiceCall(newjsonUrl)); //moved
Log.e(TAG, "page does this try catch");
}
}
catch (Exception e ) {
Log.e(TAG, "page token not found: " + e.toString());
}
for (String url : URLList){
Log.e(TAG, "url is : " + url);
}
I made an ArrayList of URLS after many attempts to debug this code, I planned on unpacking the ArrayList after all the urls with next_page_tokens were added, and then parsing through each of them later. When running the debugger with the breakpoint on pToken = getString("next_page_token") i get the first url from the Logger, and then the second url correctly. When I run as is, I get the first url, and then the following error: JSONException: No value for next_page_token
Things I've tried
Invalidating Caches and restarting
Clean Build
Run on different SDK versions
Made sure that the if statement is hitting (SEARCH_RADIUS == 1500)
Any help would be much appreciated, thanks!
Function is called in a listener function like this.
new GetPlaces(new AsyncResponse() {
#Override
public void processFinish(ArrayList<HashMap<String, String>> output) {
Log.e(TAG, "outputasync:" );
placesList = output;
}
}).execute();
My onPostExecute method.
#Override
protected void onPostExecute(ArrayList<HashMap<String, String>> result) {
delegate.processFinish(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
}
It turns out that the google places api takes a few milliseconds to validate the next_page_token after it is generated. As such, I have used the wait() function to pause before creating the newly generated url based on the next_page_token. This fixed my problem. Thanks for the help.

Unable to print the Text associated with the li tag

I have a Google Search bar with a drop down and the options are under a UL and the actual ones under the li. I am unable to retrieve the data field of the li, while I am able to retrieve the count. Have tried with the List elements and looping thru it ,but no luck. The drop with all the Options is Not visible.
I have to print the Titles associated with the li using Selenium Web driver.
Below is what I tried:
ul class=classname> xxx – GSA 2 days ago
wb.findElement(By.xpath("<>")).click();
List items = html_list.findElements(By.tagName("li")); System.out.println("The size of the elements is " + items.size()); for(WebElement item : items) { html_list.sendKeys( Keys.DOWN ); //simulate visual movement
wb.manage().timeouts().implicitlyWait(1000, TimeUnit.SECONDS); System.out.println(item.getText());
}
Hypohesis #1: You don't wait for the page to load after the click on line 1. The li elements are in the DOM but they are not completely loaded. You could test the hypothesis by introducing a delay between line 1 and line 2. I have code that I use to wait for page loads but the specifics depend on the JavaScript framework (e.g. jQuery, AngularJs), on the loading spinner implementation and browser readystate. My readystate logic looks like this:
/**
* Wait for browser readystate to be complete. But don't wait forever.
*
* #param webDriver
*/
public void waitForBrowserReadystateComplete(WebDriver webDriver) {
for (int a=0; a<20; a++) {
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) webDriver;
if (javascriptExecutor.executeScript("return document.readyState")
.toString().equals("complete")) {
break;
}
sleepResponsibly(500);
}
}
public void sleepResponsibly(int timeMillisecond){
try{
Thread.sleep(timeMillisecond);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
throw new RuntimeException(ex);
}
}
Hypthosis #2: The text nodes are complex. I have experienced a failure in method getText() to return text when the text nodes code complex formatting. I got around this by invoking the following instead:
public static String getTextFromElementsTextNodes(WebDriver webDriver, WebElement element) throws IllegalArgumentException {
String text = "";
if (webDriver instanceof JavascriptExecutor) {
text = (String)((JavascriptExecutor) webDriver).executeScript(
"var nodes = arguments[0].childNodes;" +
"var text = '';" +
"for (var i = 0; i < nodes.length; i++) {" +
" if (nodes[i].nodeType == Node.TEXT_NODE) {" +
" text += nodes[i].textContent;" +
" }" +
"}" +
"return text;"
, element);
} else {
throw new IllegalArgumentException("driver is not an instance of JavascriptExecutor");
}
return text;
}
A caveat is that getTextFromElementsTextNodes() may return non-ASCII charcters so I do the following:
System.out.println(getTextFromElementsTextNodes(wb,item).replaceAll("[^\\x00-\\x7F]", " "));
I could finally able to retrieve the options under the li. This is what I did and it worked
for(WebElement MyListOptions: listOfLiTags) {
String myoptions=serchOptions.getAttribute("<<The actual attribute value which is storing my options>>");
System.out.println("THE List Options are" + txt3);
}

How to test login page with multiple webpage(present in notepad) using selenium web driver Java?

I am testing like 100 url everything is working good. my problem is when the test starts it get web url from notepad then open the url here my process is to check the login or not in some case if the for example 10th url shows 404 error the test terminate here it cant process further urls. Any solution for this process...
my codes
public class File {
#Test(dataProvider="testdata")
public void sum(String url)
{
System.out.println(url);
}
#DataProvider
public Object[][] testdata(){
int count=20;
Object[][] obj = new Object[count][1];
for(int i=0;i<=count;i++)
{
String fileName = "E:\\ework\\Web\\bin\\Websearch\\test.txt";
try {
String line = null;
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
while((line = bufferedReader.readLine()) != null)
{
String[] abs={line};
int size = abs.length;
for(int j=0;j<=size;j++)
{
obj[i][0]=abs[j];
}
}
bufferedReader.close();
}
catch(FileNotFoundException ex) {
System.out.println(
"Unable to open file '" +
fileName + "'");
}
catch(IOException ex) {
System.out.println(
"Error reading file '"
+ fileName + "'");
}
`}
return obj;
}
}
thank you.:)
If you are using framework like TestNG then look at DataProviders for the same.
Use Try{} Catch(Exception e){} block. Insert your assertion in try block and once the assertion fails then try to capture the exception in some list or other data structure and after all urls are processed then iterate over the exception list and report it in your Reports or logs.

Osmdroid - from offline folder

I am using OSMdroid to display both online and offline data in my app. The offline data are stored in a .zip file with the required structure.
Is it possible to have these offline tiles stored in a directory (extracted .zip file with the same structure)?
Could somebody please tell me how could I achive this?
Thank you.
I am sorry. I should try more before asking. But I am leaving this question here, somebody could find it useful.
Solution:
New MapTileFileProvider. I called it MapTileFileFolderProvider, it is a lightly modified MapTileFileArchiveProvider. It is using folders instead of archives. The modifications are not perfect, it is a "hot solution" that needs someone more experienced in Java/Android to make it properly.
Benefits from loading Tiles from folders:
Faster loading of tiles (I know, I won't recognize the difference).
Easier updates focused only on changed tiles not whole map plans.
Application can download tiles when is in "online mode" and then use the downloaded Tiles offline.
MapTileFileFolderProvider - only modifications
public class MapTileFileArchiveProvider extends MapTileFileStorageProviderBase
public class MapTileFileFolderProvider extends MapTileFileStorageProviderBase {
private final boolean mSpecificFoldersProvided;
private final ArrayList<String> mFolders = new ArrayList<String>();
private final AtomicReference<ITileSource> mTileSource = new AtomicReference<ITileSource>();
...
}
public MapTileFileArchiveProvider(...)
public MapTileFileFolderProvider(final IRegisterReceiver pRegisterReceiver,
final ITileSource pTileSource,
final String[] pFolders) {
super(pRegisterReceiver, NUMBER_OF_TILE_FILESYSTEM_THREADS,
TILE_FILESYSTEM_MAXIMUM_QUEUE_SIZE);
setTileSource(pTileSource);
if (pFolders == null) {
mSpecificFoldersProvided = false;
findFolders();
} else {
mSpecificFoldersProvided = true;
for (int i = pFolders.length - 1; i >= 0; i--) {
mFolders.add(pFolders[i]);
}
}
}
findArchiveFiles()
private void findFolders() {
mFolders.clear();
if (!getSdCardAvailable()) {
return;
}
String baseDirPath = Environment.getExternalStorageDirectory().toString()+"/ctu_navigator"; // TODO get from Config
File dir=new File(baseDirPath);
final File[] files = dir.listFiles();
if (files != null) {
String fileName;
for (File file : files) {
if (file.isDirectory()) {
fileName = baseDirPath + '/' + file.getName();
mFolders.add(fileName);
Utils.log(PlanTileProviderFactory.class, "Added map source: " + fileName);
}
}
}
}
#Override
protected String getName() {
return "Folders Provider";
}
#Override
protected String getThreadGroupName() {
return "folder";
}
protected class TileLoader extends MapTileModuleProviderBase.TileLoader {
#Override
public Drawable loadTile(final MapTileRequestState pState) {
ITileSource tileSource = mTileSource.get();
if (tileSource == null) {
return null;
}
final MapTile pTile = pState.getMapTile();
// if there's no sdcard then don't do anything
if (!getSdCardAvailable()) {
Utils.log("No sdcard - do nothing for tile: " + pTile);
return null;
}
InputStream inputStream = null;
try {
inputStream = getInputStream(pTile, tileSource);
if (inputStream != null) {
Utils.log("Use tile from folder: " + pTile);
final Drawable drawable = tileSource.getDrawable(inputStream);
return drawable;
}
} catch (final Throwable e) {
Utils.log("Error loading tile");
Utils.logError(getClass(), (Exception) e);
} finally {
if (inputStream != null) {
StreamUtils.closeStream(inputStream);
}
}
return null;
}
private synchronized InputStream getInputStream(final MapTile pTile, final ITileSource tileSource) {
for (final String folder : mFolders) {
final String path = folder + '/' + tileSource.getTileRelativeFilenameString(pTile);
File mapTileFile = new File(path);
InputStream in = null;
try {
in = new BufferedInputStream(new FileInputStream(mapTileFile));
} catch (IOException e) {
//Utils.log("Tile " + pTile + " not found in " + path);
}
if (in != null) {
Utils.log("Found tile " + pTile + " in " + path);
return in;
}
}
Utils.log("Tile " + pTile + " not found.");
return null;
}
}
Well, as far as I understand what you are trying to get... this is more or less what the standard XYTileSource is already doing.
So if you simply use a ready-to-use tile source like this one:
map.setTileSource(TileSourceFactory.MAPNIK);
you will see downloaded tiles files stored in /sdcard/osmdroid/tiles/Mapnik/
The main difference is that it adds a ".tile" extension at the end of each tile file (probably to prevent tools like Android gallery to index all those images).
If you have a ZIP file with tiles ready to use, you could extract them in this directory, and add .tile extension to each tile (355.png => 355.png.tile)
And TileSourceFactory.MAPNIK will be able to use them.