I've tried:
console.log(element('.users').html());
but the only thing I get is
LOG: { name: 'element \'.users\' html', fulfilled: false }
I assume you are using Angular scenario runner.
The element().html() dsl returns a future (see wikipedia). You are logging the future that will eventually contain the element, but at the point when you are calling console.log, the future is not resolved yet - there is no value in there.
Try this:
element('.users').query(function(elm, done) {
console.log(elm.html());
done();
});
The whole scenario runner works as a queue. The test code is executed (synchronously) and each command (eg. element().html in your case) adds some action into this queue. Then, these actions are executed asynchronously - once first action finishes (by calling done()), the second action is executed, etc... Therefore the individual actions can be asynchronous, but the test code is synchronous, which is more readable.
Related
https://www.protractortest.org/#/async-await shows an example of using async/ await in protractor, but includes the line:
expect(await greeting.getText()).toEqual('Hello Julie!');
But I don't understand how that can be correct: if the greeting.getText() is async (indicated by the await), then the text won't be known until after that line has completed. Isn't:
await expect(await greeting.getText()).toEqual('Hello Julie!');
So we definitely wait for the text to be obtained (and checked) before we move on. In this example, it's not too important (assuming the expect check does execute), but in general, is there any risk of re-ordering the getText() with further operations (which may remove it from the DOM, for example).
Is it in practice safe if it's only browser-based async operations, as they execute serially anyway (so the getText() will complete before a subsequent operation?
Presumably if we included non-browser based async operations (e.g. we did a http request to a server), then the ordering wouldn't be guaranteed, so best practice would be to write 'await expect(...).toX(...)' (which is safe even if the expect expression is not async).
Of course, with all that, we end up with 'await' on the beginning of nearly every line, which looks a bit ugly.
expect(await greeting.getText()).toEqual('Hello Julie!');
is the correct way to go.
await stops execution queue and waits until first command is done before moving on to the second one, IN ORDER TO RESOLVE PROMISE. So if your function is synchronous and doesn't return a promise, why await it?
From protractor page, .getText() returns !webdriver.promise.Promise.<string> - long story short, it returns you a promise, thus it needs to be resolved
expect(await greeting.getText()).toEqual('Hello Julie!'); on the other hand returns undefined (try to console.log it). And since it doesn't return promise, and there is nothing to resolve, await is not needed
Additional example
Lets assume you want a synchronous function to take parameters:
someFunction("2" === "1", 1, await $welcomeMessage.getText());
First thing js does, is it runs each argument of the function as a separarte statement. i.e.
"2" === "1" // false
1 // 1
await $welcomeMessage.getText() // 'welcome user'
So by the time when function will be ready to be executed the overall statement will look like so
someFunction(false, 1, 'welcome user');
In other words, even though it looks like the function takes asynchronous promise which you need to wait for, in fact, this promise is resolved before it's executed. So if someFunction itself is synchronous, it doesn't need to be awaited
Protractor is really simple after the introduction of await, don't need to complicate it
First disable selenium control flow in config file, just add this line in config file:
SELENIUM_PROMISE_MANAGER: false
https://www.protractortest.org/#/control-flow
Now in test use:
it('should find an element by text input model', async function() {
await browser.get('app/index.html#/form');
var username =element(by.model('username'));
await username.clear();
await username.sendKeys('Jane Doe');
var name = element(by.binding('username'));
expect(await name.getText()).toEqual('Jane Doe');
});
Note that i am not using await for
var name = element(by.binding('username'));
This is because in protractor the find element action is not triggered unless you call a method on it
so you don't have to use await there
you won't get element not found unless you call any method on it .
I have two "expect" in my it block and my first it block failed,it still continues the execution and executing the rest of the code in my it block.
My expectation is, if first it block failed, execution stops right there and next it block should get executed.
it ("My se", function() {
expect(true).toBe(false);// it is failing
//my rest of my below code should not get executed.
My functionality code
expect(array[0]).toBe("foo");
});
it ("Second it block", function() {
//Continue the execution
});
Could some please help me with some idea, how i can achieve this. My execution of that particualr it block should stop and the next it should continue.
Ideally, expect statement should be the last statement of the it block. You need to update the test in that way to achieve the desired results.
I'm trying to implement a perpetual workflow that commences with an activity that blocks until a message is delivered (namely, Redis' BLPOP). Once it completes, I want to start a new workflow asynchronously to do some sort of processing and return ContinueAsNew immediately.
I've tried to start the processing workflow using child workflows. What I've observed is that my parent workflow completes before the child is executed. Unless I process the returned future, but I don't really want to do that.
What would be the right way to do this? Is it possible to start a new regular workflow within a workflow? Would such action be implemented as part of the workflow or within an activity?
Thank you in advance!
The solution is to wait for a child workflow to start before completing or continuing as new the parent.
If you are using the Go Cadence Client the workflow.ExecuteChildWorkflow returns a ChildWorkflowFuture which extends a Future that returns the child workflow result. It also has GetChildWorkflowExectution method that returns a Future that becomes ready as soon as the child is started. So to wait for a child workflow to start the following code can be used:
f := workflow.ExecuteChildWorklfow(ctx, childFunc)
var childWE WorkflowExecution
// The following line unblocks as soon as the child is started.
if err := f.GetChildWorkflowExecution().Get(&childWE); err != nil {
return err
}
Child workflow has started with Workflow ID found in childWE.ID and Run ID in childWE.RunID
The Java equivalent is:
ChildType child = Workflow.newChildWorkflowStub(ChildType.class);
// result promise becomes ready when the child completes
Promise<String> result = Async.function(child::executeMethod);
// childWE promise becomes ready as soon as the child is started
Promise<WorkflowExecution> childWE = Workflow.getWorkflowExecution(child);
I want to check if a pdf file is changed or not, and if is changed i want to update the corresponding view. I don't know if it's more suitable to use a background process as a Thread or as an NSOperation to do this task. The Apple Documentation says: "Examples of tasks that lend themselves well to NSOperation include network requests, image resizing, text processing, or any other repeatable, structured, long-running task that produces associated state or data.But simply wrapping computation into an object doesn’t do much without a little oversight".
Also, if I understood correctly from the documentation, a Thread once started can't be stopped during his execution while an NSOperation could be paused or stopped and also they could rely on dependency to wait the completion of another task.
The workflow of this task should be more or less this diagram:
Task workflow
I managed to get the handler working after the notification of type .write has been sent. If i monitor for example a *.txt file everything works as expected and i receive only one notification. But i am monitoring a pdf file which is generated from terminal by pdflatex and thus i receive with '.write' nearly 15 notification. If i change to '.attrib' i get 3 notification. I need the handler to be called only once, not 15 or 3 times. Do you have any idea how can i do it or is not possible with a Dispatch Source? Maybe there is a way to execute a dispatchWorkItem only once?
I have tried to implement it like this(This is inside a FileMonitor class):
func startMonitoring()
{
....
let fileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: fileStringURL)
let fileDescriptor = open(fileSystemRepresentation, O_EVTONLY)
let newfileMonitorSource = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fileDescriptor,
eventMask: .attrib,
queue: queue)
newfileMonitorSource.setEventHandler(handler:
{
self.queue.async
{
print(" \n received first write event, removing handler..." )
self.newfileMonitorSource.setEventHandler(handler: nil)
self.test()
}
})
self.fileMonitorSource = newfileMonitorSource
fileMonitorSource!.resume()
}
func test()
{
fileMonitorSource?.cancel()
print(" restart monitoring ")
startMonitoring()
}
I have tried to reassign the handler in test(), but it's not working(if a regenerate the pdf file, what is inside the new handler it's not executed) and to me, doing in this way, it seems a bit boilerplate code. I have also tried the following things:
suspend the DispatchSource in the setEventHandler of startMonitoring() (passing nil), but then when i am resuming it, i get the remaining .write events.
cancel the DispatchSource object and recall the startMonitoring() as you can see in the code above, but in this way i create and destroy the DispatchSource object everytime i receive an event, which i don't like because the cancel() function shoul be called in my case only when the user decide to disable this feauture i am implementing.
I will try to write better how the workflow of the app should be so you can have an more clear idea of what i am doing:
When the app starts, a functions sets the default value of some checkboxes of the window preference. The user can modify this checkboxes. So when the user open a pdf file, the idea is to launch in a background thread the following task:
I create a new queue call it A and launch asynch an infinite while where i check the value of the UserDefault checkboxe (that i use to reload and update the pdf file) and two things could happen
if the user set the value to off and the pdf document has been loaded there could be two situations:
if there is no current monitoring of the file (when the app starts): continue to check the checkboxe value
if there is currently a monitoring of the file: stop it
if the user set value to on and the pdf document has been loaded in this background thread (the same queue A) i will create a class Monitor (that could be a subclass of NSThread or a class that uses DispatchSourceFileSystemObject like above), then i will call startMonitoring() that will check the date or .write events and when there is a change it will call the handler. Basically this handler should recall the main thread (the main queue) and check if the file can be loaded or is corrupted and if so update the view.
Note: The infinite while loop(that should be running in the background), that check the UserDefault related to the feature i am implementing it's launched when the user open the pdf file.
Because of the problem above (multiple handlers calls), i should use the cancel() function when the user set checkboxe to off, and not create/destroy the DispatchSource object everytime i receive a .write event.
I am new to protractor-cucumber. I am trying to execute below step definition from protractor conf.js.
this.Given(/^I go to sparqHomePage$/, function (callback) {
homepage.goToHomePage()
homepage.login(data[0].UserName,data[0].Password).then(callback);
});
this.Then(/^I create a process$/, function () {
homepage.clickDesign();
homepage.clickFlowDesigner();
console.log(params.flow.procName + ' '+ params.flow.procDesc);
designPage.createNewProc(params.flow.procName, params.flow.procDesc);
});
this.Then(/^I should see process is saved in db$/, function (callback) {
var sql = "select * from process where name = ?";
sql = mysql.format(sql, params.flow.procName);
console.log(sql);
dbConn.query(sql, function(err, rows, fields){
if(!err) {
procDbObj = rows;
console.log(rows);
expect(procDbObj[0].name).to.eventually.equal( params.flow.procName);
expect(procDbObj[0].description).to.eventually.equal(params.flow.procDesc).and.notify(callback);
}
});
});
As soon as I start the execution, the console log shows, feature file execution was completed, but the actual execution is not yet completed.
In my 3rd step I am doing some db validation based on the step 1 and step 2 actions. As cucumber trying to execute all the steps before the completion of real execution with browser, my 3rd test is always failing.
How can I make cucumber to wait for step execution is completed before moving to the next step.
You are calling
homepage.goToHomePage() and homepage.login(data[0].UserName,data[0].Password).then(callback);. Are both methods correct promises that are correctly handled? It now looks like it is calling both methods but giving a direct callback before resolving the promise.
As Ross stated, you can also chain the promises, but first be sure the promises are correctly handled
Edit:
As Ross stated, you can also chain the promises, but first be sure the promises are correctly handled.
You can also return the promise in stead of the callback, just use it as this
this.Given(/^I go to sparqHomePage$/, function () {
homepage.goToHomePage();
return homepage.login(data[0].UserName,data[0].Password);
});
homepage.goToHomePage()
homepage.login(data[0].UserName,data[0].Password).then(callback);
I'm not sure exactly what is happening in the first line but I assume thats going to be doing a click, you will need to make that return a promise and re-write it like
homepage.goToHomePage().then(()=>{
homepage.login(data[0].UserName,data[0].Password).then(callback);
})
And then follow this pattern for the rest of your code as I can see this same issue throughout