Using of if-else in Cypress test - if-statement

Just learning how to write conditional tests using JS in Cypress. Write sample test as per Cypress.io
Test I trying to run:
describe ('sample tests', () => {
it('conditional test', () => {
cy.visit('https://example.cypress.io/commands/actions');
if (cy.get('input[placeholder*="Email"]')) => {
cy.type('email-1#mail.com')
} else {
cy.visit('https://www.google.com/')
}
})
})
Displayed error:
Error: Webpack Compilation Error
./cypress/e2e/4-home-page/test4.cy.js
Module build failed (from C:/Users/userName/AppData/Local/Cypress/Cache/12.3.0/Cypress/resources/app/node_modules/babel-loader/lib/index.js):
SyntaxError: C:\Users\userName\Desktop\Cypressinstall\cypress\e2e\4-home-page\test4.cy.js: Unexpected token (7:51)
5 | it('conditional test', () => {
6 | cy.visit('https://example.cypress.io/commands/actions');
> 7 | if (cy.get('input[placeholder*="Email"]')) => {
| ^
8 | cy.type('email-1#mail.com')
9 | } else {
10 | cy.visit('https://www.google.com/')
What I tried:
I moved "=>" in different location but Cypress display that "No tests found".
Expected behavior:
Cypress must run test without error, using condition if-else.

Understanding the use of "=>" is essential here and it has nothing to do with cypress.
The "=>" belongs to Javascript arrow functions
This is used to introduce shorter functions.
Now let's understand the then() method, reading this document
With the above, you should be able to understand how to use these principles correctly.
More to note:
If an element doesn't exist conditionally, we cannot use cy.get for that element (will trigger No Such Element Exception). Use
cy.get("body).then($body => {
//cy.get("body") returns the dom element which we can capture
with "then"
//Check if element exists
if($body.find("input[placeholder*=\"Email\"]").length > 0){
cy.get("input[placeholder*=\"Email\"]").type("email-1#mail.com");
}
else{
cy.visit('https://www.google.com/')
}
})
To learn more on cypress if conditions read the Cypress Documentations
Hope this helps!

As far as I understand you, the purpose in your given example is to verify if the element (email field) exists and if so, type there a value. In this case you'd better use conditional testing the following way and verify if the field is visible:
const emailField = 'input[placeholder*="Email"]';
cy.get('body').then(($email) => {
if ($email(emailField).is(':visible')) {
cy.type('email-1#mail.com')
}
else {
// Anything to do here
}
});
Or you can just check that element exist (if it's hidden for any reason):
const emailField = 'input[placeholder*="Email"]';
cy.get('body').then(($parent) => {
if ($parent.find(emailField).length > 0) {
cy.type('email-1#mail.com')
}
else {
// Anything to do here
}
});
Instead of cy.get('body').then... you can use any DOM element which is higher in the hierarchy than your desired element.

Related

The method 'putIfAbsent' was called on null

I am trying to create a LinkedHashMap and populate it with a DateTime as the key and a List as the value in my flutter app. I keep running into problems with creating this.
Here is what I am trying right now without success:
List<dynamic> _getEventsForDay(DateTime day) {
for (int i = 0; i < eventDoc.length; i++ ) {
if (day.year == eventDate.year && day.day == eventDate.day && day.month == eventDate.month) {
List<dynamic> eventList = [];
eventList.add(eventDoc[i].agencyId);
eventList.add(eventDoc[i].agentId);
eventList.add(eventDoc[i].eventDate);
eventList.add(eventDoc[i].eventDescription);
eventList.add(eventDoc[i].eventDuration);
eventList.add(eventDoc[i].eventName);
eventList.add(eventDoc[i].eventStartTime);
return kEvents.putIfAbsent(eventDateUTC, () => eventList);
}
}
}
Everything is working except the last line and the putIfAbsent call. The eventDateUTC and the eventList both have values.
I am getting this error when I try to execute the
return kEvents.putIfAbsent(eventDateUTC, () => eventList);
line. When this line executes I get this error:
The method 'putIfAbsent' was called on null.
Receiver: null
Tried calling: putIfAbsent(Instance of 'DateTime', Closure: () => List<dynamic>)
kEvents is declared like this:
LinkedHashMap<DateTime, List> kEvents;
I am sure I am missing something small but I don't have enough experience with flutter to know what it is. Please help if you can.

Add new counter (trap_id) field which increments by 1

Code:
filter {
if ([trap_id]) {
mutate {
update => { "trap_id" => "trap_id"++ }
}
else
mutate {
add_field => { "trap_id" => 1 }
}
}
}
Scenario:
I'm trying to introduce a new field(trap_id) which needs to increment by 1 every time a trap is generated.
Error:
:ConfigurationError", :message=>"Expected one of #, {, } at line 26, column 50 (byte 1229) after filter {\n
which points to line : update => { "trap_id" => "trap_id"++ }
Question:
How do I fix the error? or Is this the right way to do for the given scenario.
You cannot increment a field using that syntax. You might be able to use the math filter (although you would need to install it, and it has not been updated for three years), or you could do it in ruby.
ruby {
init => '#trap_id = 0'
code => '
#trap_id += 1
event.set("trap_id", #trap_id)
'
}
You will need to set pipeline.workers to 1 for this to work reliably. If there are multiple pipeline worker threads then access to the instance variable will not be synchronised across them. It may work almost all of the time but it is not impossible for two threads to increment #trap_id before either of them calls event.set. If for some reason the call to event.set actually has to reference memory again (as opposed to a register) then this will get the wrong result.

Assert a string contains a certain value (and fail the test if it doesn't)

As part of my nightwatch.js testing, I have the following code that will list all the values of an element (in this case, a list of UK towns);
"Page 2 Location SEO Crawl paths are displayed": function (browser) {
browser.elements('xpath', '//a[contains(#href,"location")]', function (results) {
results.value.map(function(element) {
browser.elementIdAttribute(element.ELEMENT, 'innerText', function(res) {
var resme = res.value;
console.log(resme)
});
});
});
},
This correctly list all the element values, as such;
What I'd now like to do is check that Nottingham is listed in the result, and Fail the test if it's not.
I installed the assert npm package to see if that would help, which changed my code to;
"Page 2 Location SEO Crawl paths are displayed": function (browser) {
browser.elements('xpath', '//a[contains(#href,"location")]', function (results) {
results.value.map(function(element) {
browser.elementIdAttribute(element.ELEMENT, 'innerText', function(res) {
var resme = res.value;
console.log(resme);
if (resme.includes("Nottingham")) {
assert.ok(true);
}
else {
assert.ok(false);
}
});
});
});
},
but this didn't work, as I kept getting the following error;
Is using the assert package the best way of testing this, or it there a more straightforward way of asserting that Nottingham is included in this list, and the tests fails if it's not.
I've tried using resme.includes("Nottingham"), but this doesn't fail the test.
Any help would be greatly appreciated.
Thanks.
Looks like the inner-most function (the one that has res as parameter) is called for every item, and resme is the item you are currently iterating, not an array, so the includes function is not working as expected.
I'm not familiar with this library but I guess you have to do something like this:
"Page 2 Location SEO Crawl paths are displayed": function (browser) {
var found = false;
browser.elements('xpath', '//a[contains(#href,"location")]', function (results) {
results.value.map(function(element) {
browser.elementIdAttribute(element.ELEMENT, 'innerText', function(res) {
var resme = res.value;
console.log(resme);
if (resme === "Nottingham") {
found = true;
// Maybe return something like null or 0 to stop iterating (would depend on your library).
}
});
});
});
assert.ok(found)
},
You init a variable "found" with a false value, and when you iterate over every value you set it to true if you find it. Optionally, you should break the iteration at that point. When the whole process is finished, assert that you found the value you wanted.

Unit testing Cloud Functions for Firebase: what's the "right way" to test/mock `transaction`s with sinon.js

Man, this firebase unit testing is really kicking my butt.
I've gone through the documentation and read through the examples that they provide, and have gotten some of my more basic Firebase functions unit tested, but I keep running into problems where I'm not sure how to verify that the transactionUpdated function passed along to the refs .transaction is correctly updating the current object.
My struggle is probably best illustrated with their child-count sample code and a poor attempt I made at writing a unit test for it.
Let's say my function that I want to unit test does the following (taken straight from that above link):
// count.js
exports.countlikechange = functions.database.ref('/posts/{postid}/likes/{likeid}').onWrite(event => {
const collectionRef = event.data.ref.parent;
const countRef = collectionRef.parent.child('likes_count');
// ANNOTATION: I want to verify the `current` value is incremented
return countRef.transaction(current => {
if (event.data.exists() && !event.data.previous.exists()) {
return (current || 0) + 1;
}
else if (!event.data.exists() && event.data.previous.exists()) {
return (current || 0) - 1;
}
}).then(() => {
console.log('Counter updated.');
});
});
Unit Test Code:
const chai = require('chai');
const chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);
const assert = chai.assert;
const sinon = require('sinon');
describe('Cloud Functions', () => {
let myFunctions, functions;
before(() => {
functions = require('firebase-functions');
myFunctions = require('../count.js');
});
describe('countlikechange', () => {
it('should increase /posts/{postid}/likes/likes_count', () => {
const event = {
// DeltaSnapshot(app: firebase.app.App, adminApp: firebase.app.App, data: any, delta: any, path?: string);
data: new functions.database.DeltaSnapshot(null, null, null, true)
}
const startingValue = 11
const expectedValue = 12
// Below code is misunderstood piece. How do I pass along `startingValue` to the callback param of transaction
// in the `countlikechange` function, and spy on the return value to assert that it is equal to `expectedValue`?
// `yield` is almost definitely not the right thing to do, but I'm not quite sure where to go.
// How can I go about "spying" on the result of a stub,
// since the stub replaces the original function?
// I suspect that `sinon.spy()` has something to do with the answer, but when I try to pass along `sinon.spy()` as the yields arg, i get errors and the `spy.firstCall` is always null.
const transactionStub = sinon.stub().yields(startingValue).returns(Promise.resolve(true))
const childStub = sinon.stub().withArgs('likes_count').returns({
transaction: transactionStub
})
const refStub = sinon.stub().returns({ parent: { child: childStub }})
Object.defineProperty(event.data, 'ref', { get: refStub })
assert.eventually.equals(myFunctions.countlikechange(event), true)
})
})
})
I annotated the source code above with my question, but I'll reiterate it here.
How can I verify that the transactionUpdate callback, passed to the transaction stub, will take my startingValue and mutate it to expectedValue and then allow me to observe that change and assert that it happened.
This is probably a very simple problem with an obvious solution, but I'm very new to testing JS code where everything has to be stubbed, so it's a bit of a learning curve... Any help is appreciated.
I agree that unit testing in the Firebase ecosystem isn't as easy as we'd like it to be. The team is aware of it, and we're working to make things better! Fortunately, there are some good ways forward for you right now!
I suggest taking a look at this Cloud Functions demo that we've just published. In that example we use TypeScript, but this'll all work in JavaScript too.
In the src directory you'll notice we've split out the logic into three files: index.ts has the entry-logic, saythat.ts has our main business-logic, and db.ts is a thin abstraction layer around the Firebase Realtime Database. We unit-test only saythat.ts; we've intentionally kept index.ts and db.ts really simple.
In the spec directory we have the unit tests; take a look at index.spec.ts. The trick that you're looking for: we use mock-require to mock out the entire src/db.ts file and replace it with spec/fake-db.ts. Instead of writing to the real database, we now store our performed operations in-memory, where our unit test can check that they look correct. A concrete example is our score field, which is updated in a transaction. By mocking the database, our unit test to check that that's done correctly is a single line of code.
I hope that helps you do your testing!

Moq SetUp.Return not working for repository mock

I am trying to mock my repository's Get() method to return an object in order to fake an update on that object, but my setup is not working:
Here is my Test:
[Test]
public void TestUploadDealSummaryReportUploadedExistingUpdatesSuccessfully()
{
var dealSummary = new DealSummary {FileName = "Test"};
_mockRepository.Setup(r => r.Get(x => x.FileName == dealSummary.FileName))
.Returns(new DealSummary {FileName = "Test"}); //not working for some reason...
var reportUploader = new ReportUploader(_mockUnitOfWork.Object, _mockRepository.Object);
reportUploader.UploadDealSummaryReport(dealSummary, "", "");
_mockRepository.Verify(r => r.Update(dealSummary));
_mockUnitOfWork.Verify(uow => uow.Save());
}
Here is the method that is being tested:
public void UploadDealSummaryReport(DealSummary dealSummary, string uploadedBy, string comments)
{
dealSummary.UploadedBy = uploadedBy;
dealSummary.Comments = comments;
// method should be mocked to return a deal summary but returns null
var existingDealSummary = _repository.Get(x => x.FileName == dealSummary.FileName);
if (existingDealSummary == null)
_repository.Insert(dealSummary);
else
_repository.Update(dealSummary);
_unitOfWork.Save();
}
And here is the error that I get when I run my unit test:
Moq.MockException :
Expected invocation on the mock at least once, but was never performed: r => r.Update(.dealSummary)
No setups configured.
Performed invocations:
IRepository1.Get(x => (x.FileName == value(FRSDashboard.Lib.Concrete.ReportUploader+<>c__DisplayClass0).dealSummary.FileName))
IRepository1.Insert(FRSDashboard.Data.Entities.DealSummary)
at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable1 setups, IEnumerable1 actualCalls, Expression expression, Times times, Int32 callCount)
at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall expected, Expression expression, Times times)
at Moq.Mock.Verify(Mock mock, Expression1 expression, Times times, String failMessage)
at Moq.Mock1.Verify(Expression`1 expression)
at FRSDashboard.Test.FRSDashboard.Lib.ReportUploaderTest.TestUploadDealSummaryReportUploadedExistingUpdatesSuccessfully
Through debugging I have found that the x => x.FileName is returning null, but even if i compare it to null I still get a null instead of the Deal Summary I want returned. Any ideas?
I'm guessing your setup isn't matching the call you make because they're two different anonymous lambdas. You may needs something like
_mockRepository.Setup(r => r.Get(It.IsAny<**whatever your get lambda is defined as**>()).Returns(new DealSummary {FileName = "Test"});
You could verify by setting a breakpoint in the Get() method of your repository and seeing if it is hit. It shouldn't be.