Sort table using async await in protractor - async-await

I am trying to sort a data table using async await. Here is my code.
let lastActivity = await Promise.all(_.map(elementfinder, function(elm) {
return elm.getText();
}));
let sortedLastActivity = _.sort(lastActivity);
expect(lastActivity).toEqual(sortedLastActivity);
However i get an error:-
elm.getText() is not a function.
I am unable to understand the bug here.
Please help!
TIA

If the elementfinder represent only one element, you should change your code to _map([elementfinder], function(ele){...}).
And the elementfinder must be ElementArrayFinder type.

Related

Solana Hello World Example in Documentation Uses Deprecated Functions

I am working through the hello world example and am getting an error when I compile with node. The issue is
let airdropSignature = await connection.requestAirdrop(
SyntaxError: await is only valid in async functions and the top level bodies of modules
It appears here that the connection.confirmTransaction is deprecated. In my VS code, I see a cross through the "confirmTransaction" portion of my code indicating an error there. How can I correct the code so that I avoid this error? Should the hello_world example in the documentation be updated to reflect this?
Your code is running into two problems:
the confirmTransaction method is not fully deprecated
your code is incorrectly using JavaScript async/await
1. confirmTransaction method is not fully deprecated
The #solana/web3.js method you (and the example code from the Solana docs) are using is not a fully deprecated method. But rather, the desired parameter format changed.
NOTE: You can see the source code of the confirmTransaction method here which may help you see the difference.
So in a sense, the confirmTransaction(string_of_tx_sig) format was deprecated. The new desired parameter format should pass an object as the first parameter, with the signature field defined. Like this:
await connection.confirmTransaction({ signature: airdropSignature });
Updating your code to using this updated parameter format will get rid of the "deprecated method line through". But either way, this should not cause your code to fail like it is.
2. Incorrect usage of async/await
The specific error message you are getting is due to the improper use of JavaScript's async/await functions.
Since you did not include much of your source code, I am guessing that you are attempting to call the await connection.requestAirdrop() function out side of an async function.
Perhaps just in the normal flow of a single JavaScript function like this:
const web3 = require("#solana/web3.js");
let airdropSignature = await connection.requestAirdrop(
payer.publicKey,
web3.LAMPORTS_PER_SOL
);
// using the deprecated parameter
await connection.confirmTransaction(airdropSignature);
Attempting to run this code above will result in the specific error message you gave since the requestAirdrop is not being run inside of a async function.
You can fix code in a few different ways, either:
creating a new "named" function with the async keyword before it, adding all the code above to within that function, then running that function. or,
creating an "arrow" fucntion that does effectively the same thing as the option above
For example:
Using a "named" function:
const web3 = require("#solana/web3.js");
async function main(){
let airdropSignature = await connection.requestAirdrop(
payer.publicKey,
web3.LAMPORTS_PER_SOL
);
// using the non-deprecated parameter
await connection.confirmTransaction({ signature: airdropSignature });
}
// now run the "named" function
main()
Using an "arrow" function:
const web3 = require("#solana/web3.js");
// create an run an inline "arrow" function
const runs_automatically = async () => {
let airdropSignature = await connection.requestAirdrop(
payer.publicKey,
web3.LAMPORTS_PER_SOL
);
// using the non-deprecated parameter
await connection.confirmTransaction({ signature: airdropSignature });
}
NOTE: We do not need to call our "arrow" function for it to execute the function's internal logic, unlike the "named" function
You can read more about arrow functions here on the Moz JavaScript docs.

Nightwatch - How to subscribe to CDP Events?

As you may already know, Nightwatch 2 now includes methods for making calls to CDP protocol.
So, I'm trying to capture network responses. I know that the "Network" target has to be enabled and also we have to subscribe a callback to the Network.responseReceived event. I've already done it in another framework tool, but I can't find any related example in the Nightwatch documentation that uses CDP events.
At this point, I don't know which is the method that allows this subscription or where is it, is it in browser.driver or in cdpConnection objects?
This is the code I'm currently trying:
module.exports = {
'#tags': ['njs2-03'],
async myTest (browser) {
await browser.driver.sendAndGetDevToolsCommand('Network.enable')
const cdpConnection = await browser.driver.createCDPConnection('page');
cdpConnection._wsConnection.on('Network.responseReceived', entry => {
console.log('ENTRY >>', entry)
})
await browser.url('https://duckduckgo.com/')
}
}
Any suggestion would be really helpful, Thanks!
I was looking for an answer to a similar problem myself. It appears that it is sometimes much better to analyze the source code of Nightwatch directly. Especially after version 2 was released.
Analysis of the CDP commands eg. the mockNetworkResponse method in the Nightwatch code in the method-mappings.js file give answers.
https://github.com/nightwatchjs/nightwatch/blob/098306cf77d4e380b69ab836231947fe94a12ca0/lib/transport/selenium-webdriver/method-mappings.js
Mind that you are using directly the _wsConnection object. Therefore, that is the message event you are looking for. https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/message_event
Thus, try the following
async myTest (browser) {
await browser.driver.sendAndGetDevToolsCommand('Network.enable')
const cdpConnection = await browser.driver.createCDPConnection('page')
cdpConnection._wsConnection.on('message', message => {
const messageParsed = JSON.parse(message)
if (messageParsed.method === 'Network.responseReceived') {
console.log('DEVTOOLS EVENT PARAMS >>', messageParsed.['params'])
}
})
await browser.url('https://duckduckgo.com/')
}

JS: Async function with await statement results in undefined promise. What am I doing wrong? Simple example

I'm new to JS and am currently immersing myself in asynchronous functions and promises. Having quite some experience in Python and R, this is totally new for me. I read many different websites, topics and solutions for returning a value in an asynchronous function - but I can't get it to work. Below I boiled it down to a simplification of the function I wrote, designed to get information from google about a location and return it. Simple as that. I followed the advice online and tried to rewrite the following advice from Benjamin Gruenbaum on How do I return the response from an asynchronous call?.
async function foo(){
var data = await fetch("/echo/json"); // notice the await
// code here only executes _after_ the request is done
return data.json(); // data is defined
}
Please see my own code below. It seems to me that it I'm doing the same thing, but it still logs as PromiseĀ {<pending>}... What am I doing wrong? data should be an array. Even if I only replace my googleapi url and use fetch() and .json(), it logs as PromiseĀ {<pending>}.
async function foo() {
var data = await axios.get("https://maps.googleapis.com/maps/api/geocode/json?address=Amsterdam&key=API_KEY");
return data;
}
console.log(foo())
try This way of calling async function
async function foo()
{
let response = await fetch(`https://maps.googleapis.com/maps/api/geocode/json?address=Amsterdam&key=API_KEY`);
let data = await response.json()
return data;
}
foo().then(data => console.log(data));
Can you try below code to know what is going on in the "data" you got .
This is not the solution of your problem but just you will know what you got in result
console.log(JSON.stringify(foo()));

Amazon IAP Plugin for Xamarin - crash when using TaskCompletionSource

I'm trying to implement a wrapper for the Amazon IAP Plugin for Xamarin. It uses an event based system in the following way:
You can initiate method calls and listen for events. Method calls initiate requests, some of which return a response. Events are asynchronous system-generated messages that are sent in response to method calls to return the requested data to you.
See more here
My goal is to wrap this event based system into some API which allows me to use the plugin with tasks, so I can use the async-await syntax. To achieve that I'm using the TaskCompletionSource like in the following example:
public async Task<bool> GetProductInfoAsync(params string[] productIds)
{
var iapService = AmazonIapV2Impl.Instance;
var tcs = new TaskCompletionSource<bool>();
var skus = new SkusInput { Skus = productIds.ToList() };
var requestId = iapService.GetProductData(skus).RequestId;
GetProductDataResponseDelegator delegator = null;
delegator = new GetProductDataResponseDelegator(response =>
{
if(response.Id == requestId) {
var result = GetResultFromResponse(response);
tcs.SetResult(result);
//iapService.RemoveGetProductDataResponseListener(delegator.responseDelegate);
}
});
iapService.AddGetProductDataResponseListener(delegator.responseDelegate);
return await tcs.Task;
}
This code seems to work fine if the method gets called once, but if it gets called two times in a row the app crashes immediately and the only thing printed to the console is the following message..
[mono] Unhandled Exception:
[mono] System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
[mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
..which kinda makes no sense at all.
So is there something obvious I'm missing here? Or could it be a bug from the plugin?
I have created a repository with the code above so you can reproduce the problem. It's my playground, so please ignore the whole structure of the project and just focus on the classes AmazonIAPService and MainActivity.
Hint 1:
The commented line //iapService.RemoveGetProductDataResponseListener(delegator.responseDelegate); causes also a crash with the same message but already at the first call of the method.
Hint 2:
The AmazonIAPService contains a commented method which uses await Task.Delay(TimeSpan.FromMilliseconds(1)) and solves the problem from above in a very hacky way which I really don't like.
Problem seems to be that those functions have to run asynchronously. Also mentioned here in the doc. So once you run those functions synchronously somehow they throw exception, i dont what is happening in the library but your hacky solution is the actual solution for that. If you write the function as below. it also works.
PurchaseResponseDelegator delegator = null;
delegator = new PurchaseResponseDelegator(async response =>
{
await Task.Run(() =>
{
if (response.RequestId == requestId)
{
var result = GetPurchaseEventHandler(response);
var sucess = taskCompletionSource.TrySetResult(result);
context.RemovePurchaseResponseListener(delegator.responseDelegate);
}
} );
});
// Register for an event
context.AddPurchaseResponseListener(delegator.responseDelegate);
One other exception I had despite the async-await solution, somehow, it always throws exception for the line taskCompletionSource.SetResult(result); for PurchaseUpdates functions only. if i use instead this line var sucess = taskCompletionSource.TrySetResult(result); it works fine

Returning value from AJAX request in a global variable

Sorry if this question is duplicated but I couldn't solve my problem from other solutions.
I've got this code in a sepate file included in my main index:
var getSuggestedData = {
serviceURL: $("input[name=suggestedServices]").val(),
dataR:"",
doRequest:function(){
//request data to controller
$.ajax({
url:this.serviceURL,
success:function(msg){
this.dataR = msg;
}
})
}
}
When I'm trying to get the variable "dataR" from my index this way it's UNDEFINED! PLEASE, can someone help me out?
$().ready(function() {
getSuggestedData.doRequest();
alert(getSuggestedData.dataR);
});
Thank you in advance!
The reason you are not able to access the dataR object is because it is not in the same context as the result returned from the success method.
One technique is to hold a reference to this in a variable as shown below:
var self = this;
using the jquery library!
$(this.button).bind('click',{self:this},function(event)
{
var that = event.data.self;
alert(that.num);
});
You can also check out the post below in which I explained in detailed about the "this" keyword.
http://azamsharp.com/Posts/57_I_mean__this__not__this_.aspx
If memory serves me right...
this.dataR = msg;
probably needs to be
getSuggestedData.dataR = msg
the 'this' reference would be to the object fed to jQuery, you need to reference the original object. I forget if you could access it by its name directly such as this or if you need to use another method, let me know if it doesn't work out though.

Resources