Protractor - check if element is present and either stop test or continue - protractor

I have a Protractor test that pulls various values from the UI and stores them as variables for comparison with values from a different database.
Now this test needs to run against multiple sites BUT of the 25 maximum data points recorded, some sites only have 22.
Clearly the test fails on those "22" sites since the elements are not present.
What I want to achieve is where there's a "22" site, the tests against the not present elements are ignored and the test proceeds to the end. Conveniently, the "missing" elements are the last ones in the spec.
Crudely speaking...
if element-y is not present end test or if element-y is present continue
Grateful if anyone could advise.
Thanks #sergey. I've modified your example as below....
if (!(await element(by.xpath('//*[#id="root"]/div/div[2]/main/div/div/section[5]/div/div/div[1]/section/div/span')).isPresent())) {
console.warn ('Functions are not present, closing the session')
await browser.close()
I get this error:
if (!(await element(by.xpath('//*[#id="root"]/div/div[2]/main/div/div/section[5]/div/div/div[1]/section/div/span')).isPresent())) {
^^^^^^^
SyntaxError: Unexpected identifier
I've tried using a 'var' instead of the actual element, but get the same result.
Thanks

well the best option that I recall is still pretty dirty... you can do something like this
if (!(await element.isPresent())) {
console.warn('Element not present, closing the session')
await browser.close()
}
And then the rest of test cases will fail as session not found or similar error
The reason you can't do anything better because in protractor you can't do conditional test cases based on a Promise-like condition, if that makes sense...

Related

What is the correct way to express "select all when nothing is specified in parameter"?

Let's say we have an HTTP endpoint to get all elements by name?
GET /elements?name={name}
{name} can have a value of CSV or be absent
valid:
GET /elements?name=Bill,Mary,Ann
GET /elements?name=Mike
GET /elements
invalid:
GET /elements?name=
Somehow we find out in controller that name is not passed. We know that the contract implies to return all values for elements. Possible decisions on further actions (I've seen in different projects) are:
using a NULL or a "dummy" substitution like a secret char sequence "!#$#%#$" and juggling them in database while building a query
using if (present) { executeQueryA } else { executeQueryB } logic
I am not sure I like either of these approaches, because when there is more than one optional filter these designs become unmaintainable. Something makes me believe that there is a better way to handle the situation.
What would be a proper design on back-end and in database query to handle the case "select all" when nothing is given? Just a general idea and some pseudo-code will be much appreciated.

Properties in TestResultsHttpClientBase.GetTestResultDetailsForBuildAsync are null

I try to get all test results from a speficic AzureDevOps build. I need at least those information from any test result: AutomatedTestName, Outcome and ErrorMessage.
Running TestManagementHttpClient.GetTestResultDetailsForBuildAsync(this.ProjectId, this.build.Id) returns all tests, but almost all properties on the test results are null, e.g. AutomatedTestName.
TestManagementHttpClient.GetTestResultDetailsForBuildAsync(this.ProjectId, this.build.Id, shouldIncludeResults: true) is also not working.
Is there a way to load all properties?
A workaround is to call TestManagementHttpClient.GetTestResultsAsync(this.ProjectId, runId) but there the number of results are limited to 10000. This ends in paging until no more results are found. This is potentially a bottleneck and performs bad, if we have e.g. 500'000 tests....
We can load all properties via below REST API
GET https://dev.azure.com/{organization}/{project}/_apis/test/Runs/{runId}/results?api-version=5.1
With optional parameters:
GET https://dev.azure.com/{organization}/{project}/_apis/test/Runs/{runId}/results?detailsToInclude={detailsToInclude}&$skip={$skip}&$top={$top}&outcomes={outcomes}&api-version=5.1
If you have 500'000 tests, we can use the URI Parameters $skip specify the number of test results to skip from beginning.
Update1
A workaround is to call TestManagementHttpClient.GetTestResultsAsync(this.ProjectId, runId) but there the number of results are limited to 10000.
We can call TestManagementHttpClient.GetTestResultsAsync(this.ProjectId, runId, skip number) to specify the number of test results to skip from beginning.
Please refer this doc for more details.

Using "is null" when retrieving prices doesn't work

I am trying to get the price items for performance block storage that are generic (not specific to a certain datacenter). I can see that these have the locationGroupId set to blank or null, but I can't seem to get the objectFilter to work with that, the query returns nothing. If I omit the locationGroupId filter I get a result that contain both location-specific and non-location specific prices.
GET /rest/v3.1/SoftLayer_Product_Package/759/getItemPrices.json?objectMask=mask[locationGroupId,id,categories,item]&objectFilter={"itemPrices":{"categories":{"categoryCode":{"operation":"performance_storage_space"}},"item":{"keyName":{"operation":"$=GBs"}},"locationGroupId":{"operation":"is null"}}}
I am guessing there is something wrong with the object filter, any ideas?
If I filter on locationGroupId 509 it works:
/rest/v3.1/SoftLayer_Product_Package/759/getItemPrices.json?objectMask=mask[locationGroupId,id,categories,item]&objectFilter={"itemPrices":{"categories":{"categoryCode":{"operation":"performance_storage_space"}},"item":{"keyName":{"operation":"$=GBs"}},"locationGroupId":{"operation":509}}}
The reason it the first query didn't work while the second did was that I used the command "curl -sg" to do the request. While that eliminates the need to escape the {}[] characters - it also turns off escaping other characters correctly in the URL - like the space in "is null". Changing that to "is%20null" solves the issue.
I am posting this as the answer as I find it likely for others to encounter this problem.

Cannot update one field at a time with VSTO for Word

When fields are nested, there is a problem.
foreach (Word.Field field in this.Application.ActiveDocument.Fields)
{
field.Update();
text = field.Result.Text;
}
The above code does not work.
The process starts, but winds up in an endless loop or some other process that hangs the system.
Thinking about it, I can surmise that when you update a field, it might have an effect on the fields collection - thus, the loop fails.
Does anyone have any ideas on implementing this?
P.S. I know there is a Document.UpdateFields() method to update ALL fields. However, there are reasons why I cannot use this and need to only update specific field types.
My apologies! I was going to give an example of a nested field but was trying to test some more before sending anyone (Jack) on a goose-chase.
I waited and waited and waited, and after a good 2 or 3 minutes, it finished. After the last field, it crashed with this message:
Object has been deleted.
The error was generated from the following line inside the loop:
string text = field.Code.Text;
The template is being tested on mergefields that are not being found because I am testing without database connectivity. It would be odd, but explainable, that it goes through all the fields and then, at the end of the day, the very OUTER IF field's result is "Error! Reference source not found." But I still don't get why this could happen.
Nor do I understand why looping takes 3 minutes while a call to document.Fields.Update() will do the same thing in about 1 second and NOT result in the error described above.
Again, my apologies. I never considered updating inside a loop would be vastly slower that a call to doc.fields.update().

Redirect in around filter after action has been yielded

I'm using an around filter which on certain occasions should redirect user to other path AFTER an action has been yielded (either ending with render or redirect).
Writing redirect_to in around filter after yield statement results in double render error. Trying to "reconfigure" response object (by setting body to nil and location header to desired url) results in folloing error (taken from controller specs):
Failure/Error: Unable to find matching line from backtrace
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each
Has anybody done anything similar to this?
actually I manged to do redirect in around filter after action has been yielded. You just have to redefine the response.location attribute and reset the response.status to 302 (instead of 200).
You can't yield and then redirect/render afterwards. If you need to use some of the logic in the controller action in your around filter, consider moving that logic to a before_filter, or the first block of your around filter so that its available both in the around filter to determine what to do (redirect, or otherwise yield), and also available to the action you will be yielding to